2007-01-08 18:57:47

by Robert P. J. Day

[permalink] [raw]
Subject: macros: "do-while" versus "({ })" and a compile-time error


just to stir the pot a bit regarding the discussion of the two
different ways to define macros, i've just noticed that the "({ })"
notation is not universally acceptable. i've seen examples where
using that notation causes gcc to produce:

error: braced-group within expression allowed only inside a function

i wasn't aware that there were limits on this notation. can someone
clarify this? under what circumstances *can't* you use that notation?
thanks.

rday


2007-01-09 17:08:56

by H. Peter Anvin

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

Robert P. J. Day wrote:
> just to stir the pot a bit regarding the discussion of the two
> different ways to define macros, i've just noticed that the "({ })"
> notation is not universally acceptable. i've seen examples where
> using that notation causes gcc to produce:
>
> error: braced-group within expression allowed only inside a function
>
> i wasn't aware that there were limits on this notation. can someone
> clarify this? under what circumstances *can't* you use that notation?
> thanks.
>

Well, you can apparently not use it as a part of a constant expression
(which makes sense; do-while is illegal there too.) That would be the
only case in which an expression is permitted outside a function at all.

-hpa

2007-01-09 17:33:22

by Stefan Richter

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

Robert P. J. Day wrote:
> just to stir the pot a bit regarding the discussion of the two
> different ways to define macros,

You mean function-like macros, right?

> i've just noticed that the "({ })"
> notation is not universally acceptable. i've seen examples where
> using that notation causes gcc to produce:
>
> error: braced-group within expression allowed only inside a function

And function calls and macros which expand to "do { expr; } while (0)"
won't work anywhere outside of functions either.

> i wasn't aware that there were limits on this notation. can someone
> clarify this? under what circumstances *can't* you use that notation?
> thanks.

The limitations are certainly highly compiler-specific.
--
Stefan Richter
-=====-=-=== ---= -=--=
http://arcgraph.de/sr/

2007-01-09 19:23:06

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error


On Tue, 9 Jan 2007, Stefan Richter wrote:

> Robert P. J. Day wrote:
>> just to stir the pot a bit regarding the discussion of the two
>> different ways to define macros,
>
> You mean function-like macros, right?
>
>> i've just noticed that the "({ })"
>> notation is not universally acceptable. i've seen examples where
>> using that notation causes gcc to produce:
>>
>> error: braced-group within expression allowed only inside a function
>
> And function calls and macros which expand to "do { expr; } while (0)"
> won't work anywhere outside of functions either.
>
>> i wasn't aware that there were limits on this notation. can someone
>> clarify this? under what circumstances *can't* you use that notation?
>> thanks.
>
> The limitations are certainly highly compiler-specific.

I don't think so. You certainly couldn't write working 'C' code like
this:

do { a = 1; } while(0);

This _needs_ to be inside a function. In fact any runtime operations
need to be inside functions. It's only in assembly that you could
'roll your own' code like:

main:
ret 0


Most of these errors come about as a result of changes where a macro
used to define a constant. Later on, it was no longer a constant in
code that didn't actually get compiled during the testing.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.16.24 on an i686 machine (5592.72 BogoMips).
New book: http://www.AbominableFirebug.com/
_


****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2007-01-09 20:19:32

by Stefan Richter

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

linux-os (Dick Johnson) wrote:
> On Tue, 9 Jan 2007, Stefan Richter wrote:
>> The limitations are certainly highly compiler-specific.
>
> I don't think so.

I referred to the ({ expr; }) in this remark, not to do-while. It's not
a valid construct in many flavors of the C language in the first place.
Also, occurrences of ({ expr; }) could be expandable to a constant
expression but would still not be accepted by gcc's parser outside of
functions.
--
Stefan Richter
-=====-=-=== ---= -=--=
http://arcgraph.de/sr/

2007-01-10 06:25:47

by Robert P. J. Day

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

On Tue, 9 Jan 2007, linux-os (Dick Johnson) wrote:

>
> On Tue, 9 Jan 2007, Stefan Richter wrote:
>
> > Robert P. J. Day wrote:
> >> just to stir the pot a bit regarding the discussion of the two
> >> different ways to define macros,
> >
> > You mean function-like macros, right?
> >
> >> i've just noticed that the "({ })"
> >> notation is not universally acceptable. i've seen examples where
> >> using that notation causes gcc to produce:
> >>
> >> error: braced-group within expression allowed only inside a function
> >
> > And function calls and macros which expand to "do { expr; } while (0)"
> > won't work anywhere outside of functions either.
> >
> >> i wasn't aware that there were limits on this notation. can someone
> >> clarify this? under what circumstances *can't* you use that notation?
> >> thanks.
> >
> > The limitations are certainly highly compiler-specific.
>
> I don't think so. You certainly couldn't write working 'C' code like
> this:
>
> do { a = 1; } while(0);
>
> This _needs_ to be inside a function. In fact any runtime operations
> need to be inside functions. It's only in assembly that you could
> 'roll your own' code like:
>
> main:
> ret 0
>
>
> Most of these errors come about as a result of changes where a macro
> used to define a constant. Later on, it was no longer a constant in
> code that didn't actually get compiled during the testing.

just FYI, the reason i brought this up in the first place is that i
noticed that the ALIGN() macro in kernel.h didn't verify that the
alignment value was a power of 2, so i thought -- hmmm, i wonder if
there are any invocations where that's not true, so i (temporarily)
rewrote ALIGN to incorporate that check, and the build blew up
including include/net/neighbour.h, which contains the out-of-function
declaration:

struct neighbour
{
...
unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
...

so it's not a big deal, it was just me goofing around and breaking
things.

rday

2007-01-10 12:17:03

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error


On Wed, 10 Jan 2007, Robert P. J. Day wrote:

> On Tue, 9 Jan 2007, linux-os (Dick Johnson) wrote:
>
>>
>> On Tue, 9 Jan 2007, Stefan Richter wrote:
>>
>>> Robert P. J. Day wrote:
>>>> just to stir the pot a bit regarding the discussion of the two
>>>> different ways to define macros,
>>>
>>> You mean function-like macros, right?
>>>
>>>> i've just noticed that the "({ })"
>>>> notation is not universally acceptable. i've seen examples where
>>>> using that notation causes gcc to produce:
>>>>
>>>> error: braced-group within expression allowed only inside a function
>>>
>>> And function calls and macros which expand to "do { expr; } while (0)"
>>> won't work anywhere outside of functions either.
>>>
>>>> i wasn't aware that there were limits on this notation. can someone
>>>> clarify this? under what circumstances *can't* you use that notation?
>>>> thanks.
>>>
>>> The limitations are certainly highly compiler-specific.
>>
>> I don't think so. You certainly couldn't write working 'C' code like
>> this:
>>
>> do { a = 1; } while(0);
>>
>> This _needs_ to be inside a function. In fact any runtime operations
>> need to be inside functions. It's only in assembly that you could
>> 'roll your own' code like:
>>
>> main:
>> ret 0
>>
>>
>> Most of these errors come about as a result of changes where a macro
>> used to define a constant. Later on, it was no longer a constant in
>> code that didn't actually get compiled during the testing.
>
> just FYI, the reason i brought this up in the first place is that i
> noticed that the ALIGN() macro in kernel.h didn't verify that the
> alignment value was a power of 2, so i thought -- hmmm, i wonder if
> there are any invocations where that's not true, so i (temporarily)
> rewrote ALIGN to incorporate that check, and the build blew up
> including include/net/neighbour.h, which contains the out-of-function
> declaration:
>
> struct neighbour
> {
> ...
> unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
> ...
>
> so it's not a big deal, it was just me goofing around and breaking
> things.
>
> rday


Hmmm, in that case you would be trying to put code inside a structure!
Neat --if you could do it!


Cheers,
Dick Johnson
Penguin : Linux version 2.6.16.24 on an i686 machine (5592.72 BogoMips).
New book: http://www.AbominableFirebug.com/
_


****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2007-01-10 13:51:45

by Robert P. J. Day

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

On Wed, 10 Jan 2007, linux-os (Dick Johnson) wrote:

>
> On Wed, 10 Jan 2007, Robert P. J. Day wrote:

> > just FYI, the reason i brought this up in the first place is that
> > i noticed that the ALIGN() macro in kernel.h didn't verify that
> > the alignment value was a power of 2, so i thought -- hmmm, i
> > wonder if there are any invocations where that's not true, so i
> > (temporarily) rewrote ALIGN to incorporate that check, and the
> > build blew up including include/net/neighbour.h, which contains
> > the out-of-function declaration:
> >
> > struct neighbour
> > {
> > ...
> > unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
> > ...
> >
> > so it's not a big deal, it was just me goofing around and breaking
> > things.
> >
> > rday
>
>
> Hmmm, in that case you would be trying to put code inside a
> structure! Neat --if you could do it!

well, yes, but it does raise a potential issue. currently, that
ALIGN() macro is being used to define one of the members of that
structure. since it's a "simple" macro, there's no problem.

but there are *plenty* of macros in the source tree that incorporate
either the "do-while" or "({ })" notation. what the above implies is
that the ALIGN() macro can *never* be extended in that way because of
the way it's being used in the struct definition above, outside of a
function.

doesn't that place an unnecessarily limit on what might be done with
ALIGN() in the future? because of how it's being used in that single
structure definition, it is forever restricted from being extended.
isn't that perhaps a dangerous restriction for any macro?

rday

2007-01-10 14:07:38

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error


On Wed, 10 Jan 2007, Robert P. J. Day wrote:

> On Wed, 10 Jan 2007, linux-os (Dick Johnson) wrote:
>
>>
>> On Wed, 10 Jan 2007, Robert P. J. Day wrote:
>
>>> just FYI, the reason i brought this up in the first place is that
>>> i noticed that the ALIGN() macro in kernel.h didn't verify that
>>> the alignment value was a power of 2, so i thought -- hmmm, i
>>> wonder if there are any invocations where that's not true, so i
>>> (temporarily) rewrote ALIGN to incorporate that check, and the
>>> build blew up including include/net/neighbour.h, which contains
>>> the out-of-function declaration:
>>>
>>> struct neighbour
>>> {
>>> ...
>>> unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
>>> ...
>>>
>>> so it's not a big deal, it was just me goofing around and breaking
>>> things.
>>>
>>> rday
>>
>>
>> Hmmm, in that case you would be trying to put code inside a
>> structure! Neat --if you could do it!
>
> well, yes, but it does raise a potential issue. currently, that
> ALIGN() macro is being used to define one of the members of that
> structure. since it's a "simple" macro, there's no problem.
>
> but there are *plenty* of macros in the source tree that incorporate
> either the "do-while" or "({ })" notation. what the above implies is
> that the ALIGN() macro can *never* be extended in that way because of
> the way it's being used in the struct definition above, outside of a
> function.
>
> doesn't that place an unnecessarily limit on what might be done with
> ALIGN() in the future? because of how it's being used in that single
> structure definition, it is forever restricted from being extended.
> isn't that perhaps a dangerous restriction for any macro?
>
> rday

Remember that a macro simply substitutes "text." If the new text doesn't make
any sense, the compiler will barf. There are gnu extensions such as
__attribute__ that can be used to manipulate structure members in
non-default ways.

Also alignment only occurs when data-space in allocated either at runtime or at
link time. This knowledge is useful when you are defining structures that will
have elements accessed by pointers. You put the largest elements (a.k.a.
sizeof()) at the beginning of the structure.


Cheers,
Dick Johnson
Penguin : Linux version 2.6.16.24 on an i686 machine (5592.72 BogoMips).
New book: http://www.AbominableFirebug.com/
_


****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2007-01-10 18:25:25

by Stefan Richter

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

Robert P. J. Day wrote:
[...]
> what the above implies is
> that the ALIGN() macro can *never* be extended in that way because of
> the way it's being used in the struct definition above, outside of a
> function.
>
> doesn't that place an unnecessarily limit on what might be done with
> ALIGN() in the future?
[...]

The one occurrence which is different from others could be changed.

But more importantly: Don't overuse macros.
--
Stefan Richter
-=====-=-=== ---= -=-=-
http://arcgraph.de/sr/

2007-01-10 21:49:48

by J.A. Magallón

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

On Wed, 10 Jan 2007 07:16:55 -0500, "linux-os \(Dick Johnson\)" <[email protected]> wrote:

>
> On Wed, 10 Jan 2007, Robert P. J. Day wrote:
>
> > On Tue, 9 Jan 2007, linux-os (Dick Johnson) wrote:
> >
> >>
> >> On Tue, 9 Jan 2007, Stefan Richter wrote:
> >>
> >>> Robert P. J. Day wrote:
> >>>> just to stir the pot a bit regarding the discussion of the two
> >>>> different ways to define macros,
> >>>
> >>> You mean function-like macros, right?
> >>>
> >>>> i've just noticed that the "({ })"
> >>>> notation is not universally acceptable. i've seen examples where
> >>>> using that notation causes gcc to produce:
> >>>>
> >>>> error: braced-group within expression allowed only inside a function
> >>>
> >>> And function calls and macros which expand to "do { expr; } while (0)"
> >>> won't work anywhere outside of functions either.
> >>>
> >>>> i wasn't aware that there were limits on this notation. can someone
> >>>> clarify this? under what circumstances *can't* you use that notation?
> >>>> thanks.
> >>>
> >>> The limitations are certainly highly compiler-specific.
> >>
> >> I don't think so. You certainly couldn't write working 'C' code like
> >> this:
> >>
> >> do { a = 1; } while(0);
> >>
> >> This _needs_ to be inside a function. In fact any runtime operations
> >> need to be inside functions. It's only in assembly that you could
> >> 'roll your own' code like:
> >>
> >> main:
> >> ret 0
> >>
> >>
> >> Most of these errors come about as a result of changes where a macro
> >> used to define a constant. Later on, it was no longer a constant in
> >> code that didn't actually get compiled during the testing.
> >
> > just FYI, the reason i brought this up in the first place is that i
> > noticed that the ALIGN() macro in kernel.h didn't verify that the
> > alignment value was a power of 2, so i thought -- hmmm, i wonder if
> > there are any invocations where that's not true, so i (temporarily)
> > rewrote ALIGN to incorporate that check, and the build blew up
> > including include/net/neighbour.h, which contains the out-of-function
> > declaration:
> >
> > struct neighbour
> > {
> > ...
> > unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
> > ...
> >
> > so it's not a big deal, it was just me goofing around and breaking
> > things.
> >
> > rday
>
>
> Hmmm, in that case you would be trying to put code inside a structure!
> Neat --if you could do it!
>

The ({ }) is a block expression, ie, it allows declaring variables and
executing code. Its a gcc extension trying to resemble what other languages
like ML have:

ML:
f = let
y = x*x
in
2*y + sin(y)
end

GNU C:
f = ({ int y = x*x;
2*y + sin(y); })

So you can put it on every place you could also put a { } block or declare a
variable. {} is a compund command and ({ }) is a compund expression
(or block expression, do not know which is the good name in engelish).

--
J.A. Magallon <jamagallon()ono!com> \ Software is like sex:
\ It's better when it's free
Mandriva Linux release 2007.1 (Cooker) for i586
Linux 2.6.19-jam03 (gcc 4.1.2 20061110 (prerelease) (4.1.2-0.20061110.1mdv2007.1)) #1 SMP PREEMPT

2007-01-10 22:04:30

by Andreas Schwab

[permalink] [raw]
Subject: Re: macros: "do-while" versus "({ })" and a compile-time error

"J.A. Magall?n" <[email protected]> writes:

> {} is a compund command and ({ }) is a compund expression
> (or block expression, do not know which is the good name in engelish).

gcc calls it a statement expression.

Andreas.

--
Andreas Schwab, SuSE Labs, [email protected]
SuSE Linux Products GmbH, Maxfeldstra?e 5, 90409 N?rnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."