27

In multiple ARM back-end of Linux, I'm seeing in files clkdev.h this macro definition:

#define __clk_get(clk) ({ 1; })

See for example ./arch/arm/mach-versatile/include/mach/clkdev.h

This macro is using GCC extension Statements and Declarations in Expressions

Later this macro is used in file ./drivers/clk/clkdev.c, in function clk_get_sys()

 if (cl && !__clk_get(cl->clk))
         cl = NULL;

I'm wondering why not using here a simple macro:

#define __clk_get(clk) (1)

EDIT:

I've found some other usage of this construct throughout the kernel sources using the following grep pattern:

grep -R '({[[:space:]]*[a-zA-Z0-9_()+=/!&*>., ?:-]\+[[:space:]]*;[[:space:]]*})' .

Here's some of the matches:

./kernel/trace/trace_selftest.c:# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
./kernel/profile.c:#define create_hash_tables()         ({ 0; })
./include/asm-generic/bug.h: * Use of ({0;}) because WARN_ON_SMP(x) may be used either as
./include/asm-generic/bug.h:# define WARN_ON_SMP(x)         ({0;})
./include/linux/key.h:#define key_get(k)            ({ NULL; })
./include/linux/key.h:#define key_get(k)            ({ NULL; })
./include/linux/audit.h:#define audit_alloc(t) ({ 0; })
./include/linux/audit.h:#define audit_bprm(p) ({ 0; })
./include/linux/audit.h:#define audit_sockaddr(len, addr) ({ 0; })
./include/linux/audit.h:#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
./include/linux/audit.h:#define audit_log_start(c,g,t) ({ NULL; })
./include/linux/atalk.h:#define atalk_proc_init()   ({ 0; })
./include/linux/ftrace.h:#define register_ftrace_function(ops) ({ 0; })
./include/linux/ftrace.h:#define unregister_ftrace_function(ops) ({ 0; })
./include/linux/ftrace.h:#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; })
./include/linux/ftrace.h:#define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; })
./include/linux/ftrace.h:#define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; })
./include/linux/cpu.h:#define unregister_hotcpu_notifier(nb)    ({ (void)(nb); })
./include/linux/proc_fs.h:#define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
./arch/powerpc/include/asm/pgtable-ppc64.h:#define pgd_set(pgdp, pudp)  ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
./arch/sh/math-emu/math.c:#define WRITE(d,a)    ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
./arch/sh/math-emu/math.c:#define READ(d,a) ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
[...]

Note: the construct ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;}) seems to be a good usage of the compound statement. But this can also be replaced by more typical do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0)

One match returned by grep is interesting: in ./include/asm-generic/bug.h there's a comment of usage of ({ 0; }). This is quite the same answer of AndreyT.

Indeed, one cannot use ((void)0), since it won't be usable as a r-value. ({ 0; }) is working in each case.

So if you have a macro that can used like a function returning a value that can be used or not, the compound statement seems to be your only option.

But __clkget() is never used as anything else as a r-value

Some links

Community
  • 1
  • 1
Yann Droneaud
  • 5,277
  • 1
  • 23
  • 39
  • 1
    My guess is there used to be some meat to the macro, and at some point someone hacked it to always evaluate to 1 without removing the GCC extension paren-bracket syntax. – phonetagger Dec 18 '12 at 17:44
  • 7
    No, now I think maybe the GCC extension paren-bracket syntax may defeat a "conditional expression always true" warning? – phonetagger Dec 18 '12 at 17:49
  • @phonetagger Is that a gcc warning? But I do see a MSVC C4127 warning is possible. – Joseph Quinsey Dec 18 '12 at 19:14
  • @JosephQuinsey - I don't get such a warning myself, but a guy who works with me keeps making tweaks to code everybody else checks in because his version of GCC on his own linux box is much newer than the version everybody else uses on the server, and everybody else's normal coding practices apparently don't work so well (in terms of warnings) on whatever version he uses. I don't know what version he uses. – phonetagger Dec 18 '12 at 19:55
  • 1
    @H2CO3 I don't think anyone can compile the vanilla Linux kernel with any Microsoft products. – Alvin Wong Dec 19 '12 at 12:16
  • @AlvinWong I don't think you got my point :) –  Dec 19 '12 at 16:25
  • Does this answer your question? [Can someone please explain this macro definition?](https://stackoverflow.com/questions/64040245/can-someone-please-explain-this-macro-definition) – Yunnosch Sep 24 '20 at 08:32

3 Answers3

9

I notice that in -Wall mode a standalone (1); expression statement generates a "statement with no effect" warning, while a standalone ({ 1; }); expression statement produces no warnings.

Maybe somewhere in the code they somehow end up with standalone __clk_get calls that ignore the result. The (1) definition would result in warning for such calls, while ({ 1; }) keeps it quiet while producing the same effect in other contexts.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    I suspect this is getting somewhat closer to the truth. Sometimes, certain macros are defined in particular odd-looking ways because the want to a) work properly in a variety of different settings (and possibly even prevent certain wrong usages) without any unexpected side effects and b) avoid generating compiler diagnostics no matter how the macro ends up being used... Defining it the "obvious" way may be 95% of the way there, but certain unusual cases might require some otherwise odd looking tweaks... – twalberg Dec 16 '14 at 18:39
8

Why this macro is defined as ({ 1; })?

It all depends on the programmer's coding style. All it does is return the value 1. For example, on x86 arch in "include/asm-generic/clkdev.h", __clk_get is defined as

static inline int __clk_get(struct clk *clk) { return 1; }

Also in linux/arch/c6x/include/asm/clkdev.h

static inline int __clk_get(struct clk *clk)
{
        return 1;
}
manav m-n
  • 11,136
  • 23
  • 74
  • 97
  • When grepping kernel sources for `({ 1; })` there's no other result than the `__clk_get()` macro. – Yann Droneaud Dec 19 '12 at 06:19
  • Maybe you are using kernel source tree for ARM only. Try using the complete kernel codebase. http://lxr.linux.no/linux+v3.7.1/include/asm-generic/clkdev.h#L20 – manav m-n Dec 19 '12 at 06:27
  • 1
    It's a matter of style, to the extent that an ill-conceived, gratuitous use of a compiler extension is style. – Kaz Jun 09 '13 at 21:03
0

A possible explanation is to prevent usage in undesirable situations.
This is useful to improve code portability - if another architecture's implementation of the macro would fail, we want this one to fail too.

Example: static int x = __clk_get(clk); - there's no sense in statically initializing with the clock.
With #define __clk_get(clk) (1), it will work.
With #define __clk_get(clk) ({ 1; }), it will fail.

ugoren
  • 16,023
  • 3
  • 35
  • 65
  • A non-constant expression can be obtained in standard C, like `1 ? 1 : 1`. – Kaz Jun 09 '13 at 21:05
  • @Kaz, Maybe `__clk_get` could have been implemented this way too. – ugoren Jun 10 '13 at 07:32
  • @Kaz: `?:` is allowed in constant expressions in standard C. Actually, virtually all operators are allowed. As long as all operands are constant expressions, operators produce constant expressions. So, `1 ? 1 : 1` is a constant expression in C. What made you think it should be non-constant? – AnT stands with Russia Nov 19 '13 at 05:41
  • @AndreyT My bad; it's a comma operator we want, not ternary: *Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.* [ISO 9899:1990 6.6 Constant Expressions, Constraints] ... though I seem to recall that ternary expressions weren't constant either in C90. – Kaz Nov 19 '13 at 05:52
  • @AndreyT The thing is, it's not useful if the compiler doesn't actually diagnose it as required. – Kaz Nov 19 '13 at 05:55