diff mbox series

[doc] Note variable shadowing at max macro using statement expression

Message ID 49ced89e-d2f5-f8dd-27f3-f4aeb1385ed1@suse.de
State New
Headers show
Series [doc] Note variable shadowing at max macro using statement expression | expand

Commit Message

Tom de Vries April 11, 2019, 8:31 a.m. UTC
[ was: Re: [RFC, doc] Note variable shadowing at max macro using
statement expression ]

On 09-04-19 22:51, Sandra Loosemore wrote:
> 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.
> 

Hi Sandra,

thanks for the review.

I've attached the updated patch, as well as the resulting relevant
gcc.info portion.

OK for trunk?

Thanks,
- Tom
This feature is especially useful in making macro definitions "safe"
(so that they evaluate each operand exactly once).  For example, the
"maximum" function is commonly defined as a macro in standard C as
follows:

     #define max(a,b) ((a) > (b) ? (a) : (b))

But this definition computes either A or 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 'int'), you can avoid this problem by defining
the macro as follows:

     #define maxint(a,b) \
       ({int _a = (a), _b = (b); _a > _b ? _a : _b; })

 Note that introducing variable declarations (as we do in 'maxint') can
cause variable shadowing, so while this example using the 'max' macro
produces correct results:
     int _a = 1, _b = 2, c;
     c = max (_a, _b);
this example using maxint will not:
     int _a = 1, _b = 2, c;
     c = maxint (_a, _b);

 This problem may for instance occur when we use this pattern
recursively, like so:

     #define maxint3(a, b, c) \
       ({int _a = (a), _b = (b), _c = (c); maxint (maxint (_a, _b), _c); })

Comments

Sandra Loosemore April 11, 2019, 2:47 p.m. UTC | #1
On 4/11/19 2:31 AM, Tom de Vries wrote:
> Hi Sandra,
> 
> thanks for the review.
> 
> I've attached the updated patch, as well as the resulting relevant
> gcc.info portion.
> 
> OK for trunk?

This version looks OK.  Thanks for helping to improve the docs!

-Sandra
diff mbox series

Patch

[doc] Note variable shadowing at max macro using statement expression

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); })
...

2019-04-08  Tom de Vries  <tdevries@suse.de>

	* doc/extend.texi (@node Statement Exprs): Note variable shadowing at
	max macro using statement expression.

---
 gcc/doc/extend.texi | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8e0deac26c3..cad7ad49e56 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -142,14 +142,36 @@  follows:
 @cindex side effects, macro argument
 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:
+type of the operands (here taken as @code{int}), 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 @code{maxint}) can
+cause variable shadowing, so while this example using the @code{max} macro
+produces correct results:
+@smallexample
+int _a = 1, _b = 2, c;
+c = max (_a, _b);
+@end smallexample
+@noindent
+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.