From patchwork Thu Apr 11 08:31:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 1083759 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-499091-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="rZh8q/BU"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44fvQW4L06z9s3q for ; Thu, 11 Apr 2019 18:31:57 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=HMLgAPnJplZZNzNte mRBUOjCy4WsGyItV42JV2BwYFo0TufSR7G4l7VabSBP5b1PnDX1yJKBGfd7wm1ZF 3hRObmPsBimoZBAucRrvsw6BzVZdgT7HSJj+Ovi7S0+cqmNsur/njmUY0fEgicdS IAXbfIdDguhqWBcxON3ErsmjRg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=f150ZHWWF94AaA4s1FqAwZR 93s8=; b=rZh8q/BUu3XLTybx6PM2o9ROo/0mpqVbUpLDBKzJDgH+8jeGuR29Cgb CTQ6o2+fbf9vGZWYnTG4MQYE0GvOYgGcO3S8/JSMBTiQWiRtyELPLmEWOYt4Rfl4 2IHDBu432ZuGX7JNQzpgilBql+EJQ8C4jZtCSGmsVyTxsWS9UdNE= Received: (qmail 117023 invoked by alias); 11 Apr 2019 08:31:49 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 117012 invoked by uid 89); 11 Apr 2019 08:31:49 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=Statement, HTo:U*gerald, UD:info X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 11 Apr 2019 08:31:47 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 3BB53AE8A; Thu, 11 Apr 2019 08:31:45 +0000 (UTC) Subject: [PATCH, doc] Note variable shadowing at max macro using statement expression To: Sandra Loosemore , gcc-patches@gcc.gnu.org, Gerald Pfeifer , Joseph Myers References: <20190408113810.GA1486@delia> From: Tom de Vries Message-ID: <49ced89e-d2f5-f8dd-27f3-f4aeb1385ed1@suse.de> Date: Thu, 11 Apr 2019 10:31:43 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.5.1 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes [ 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); }) [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 * 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.