Message ID | 20190408113810.GA1486@delia |
---|---|
State | New |
Headers | show |
Series | [RFC,doc] Note variable shadowing at max macro using statement expression | expand |
On 4/8/19 5:38 AM, Tom de Vries wrote: > Hi, > > When suggesting to rewrite the unsafe (with respect to multiple evaluation of > arguments) macro definition: > ... > #define max(a,b) ((a) > (b) ? (a) : (b)) > ... > into the safe macro definition: > ... > #define maxint(a,b) \ > ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) > ... > mention the variable shadowing problem for: > ... > #define maxint3(a, b, c) \ > ({int _a = (a), _b = (b), _c = (c); maxint (maxint (_a, _b), _c); }) > ... > > Any comments? The content looks reasonable, but I have some copy-editing nits. > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index 8e0deac26c3..27ed0fb014f 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -143,13 +143,34 @@ follows: > But this definition computes either @var{a} or @var{b} twice, with bad > results if the operand has side effects. In GNU C, if you know the > type of the operands (here taken as @code{int}), you can define > -the macro safely as follows: > +the macro safe (from evaluating operands more than once) as follows: That doesn't read well. I suggest ...you can avoid this problem by defining the macro as follows: > > @smallexample > #define maxint(a,b) \ > (@{int _a = (a), _b = (b); _a > _b ? _a : _b; @}) > @end smallexample > > +Note that introducing variable declarations (as we do in maxint) can @code{maxint} > +cause variable shadowing, so while this example using the max macro will @code{max} > +produce correct results: s/will produce/produces/ > +@smallexample > +int _a = 1, _b = 2, c; > +c = max (_a, _b); > +@end smallexample > +this example using maxint will not: @noindent this example using @code{maxint} does not: > +@smallexample > +int _a = 1, _b = 2, c; > +c = maxint (_a, _b); > +@end smallexample > + > +This problem may for instance occur when we use this pattern recursively, like > +so: > + > +@smallexample > +#define maxint3(a, b, c) \ > + (@{int _a = (a), _b = (b), _c = (c); maxint (maxint (_a, _b), _c); @}) > +@end smallexample > + > Embedded statements are not allowed in constant expressions, such as > the value of an enumeration constant, the width of a bit-field, or > the initial value of a static variable. > -Sandra
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8e0deac26c3..27ed0fb014f 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -143,13 +143,34 @@ follows: But this definition computes either @var{a} or @var{b} twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here taken as @code{int}), you can define -the macro safely as follows: +the macro safe (from evaluating operands more than once) as follows: @smallexample #define maxint(a,b) \ (@{int _a = (a), _b = (b); _a > _b ? _a : _b; @}) @end smallexample +Note that introducing variable declarations (as we do in maxint) can +cause variable shadowing, so while this example using the max macro will +produce correct results: +@smallexample +int _a = 1, _b = 2, c; +c = max (_a, _b); +@end smallexample +this example using maxint will not: +@smallexample +int _a = 1, _b = 2, c; +c = maxint (_a, _b); +@end smallexample + +This problem may for instance occur when we use this pattern recursively, like +so: + +@smallexample +#define maxint3(a, b, c) \ + (@{int _a = (a), _b = (b), _c = (c); maxint (maxint (_a, _b), _c); @}) +@end smallexample + Embedded statements are not allowed in constant expressions, such as the value of an enumeration constant, the width of a bit-field, or the initial value of a static variable.