diff mbox series

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

Message ID 20190408113810.GA1486@delia
State New
Headers show
Series [RFC,doc] Note variable shadowing at max macro using statement expression | expand

Commit Message

Tom de Vries April 8, 2019, 11:38 a.m. UTC
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?

Thanks,
- Tom

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

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 | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

Comments

Sandra Loosemore April 9, 2019, 8:51 p.m. UTC | #1
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 mbox series

Patch

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.