Received: by 10.213.65.68 with SMTP id h4csp172594imn; Wed, 21 Mar 2018 15:29:17 -0700 (PDT) X-Google-Smtp-Source: AG47ELsWDVklr2zXa6c2jU5NsnRQ+4ebHAeuLXRflKHOPvnl7mgBYXXDfj5/xBHrhdgE+eXA4cLw X-Received: by 10.98.238.2 with SMTP id e2mr18409197pfi.68.1521671357305; Wed, 21 Mar 2018 15:29:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521671357; cv=none; d=google.com; s=arc-20160816; b=DeAEUgHjnE2BMsbzzwgB2d5FLJOSwe+bPB4DZ8VL1TyAkP5L5f0brYR87N3H2ujIdk vNivTx24YZ72blLzmubzmdJbbI5PSCx1xHraTlYLwRI8fQMo03t+UZH58TrlcuDog31T t5hU+FHMUMI1emX6dYXE/AX+43o1pMOGNWFMoD10vxHQvXO/Nstv/AJqA0aC97nEprtS a8wZVfwCsnDWi8LN7dVjCa1f1SOgs39m/aUGswY+O5+rjp+5w4CzBBCrwarUA3V1YATT ufmR4hUe4yL89qpDxvmBYlCJgUkywNdnOdnuFlBK3dz4J1LsquCY+hTw5qEPF0k1EALZ zSpA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature:dkim-signature :arc-authentication-results; bh=2rgwOXhdZJxD2Kmt57gR65OTd4O2hHdZz2/FNTSQXg4=; b=YdEi0abbSHtBcbpLrS9SfJE3sC7SeeVHbxdG06Qve/N4/pwxIn1joXbfzznQd5nt0w DMTiWNYhqqRZ1toAjdnKt+d5naIycsxNeuc3L2lDaQBL54XLFrLtvGpUjOMO39irafdP K2HQUL82xCqglrQ6n7hJ91aP8vEbJoVHBi2FLnjujqn+VI5vyadGNpUv7QW6UBFA3P1G bo6iYsIm/f15NsLWM1N8QsEvpugJayKo/Bc/eFOOLXcoStBZon/cHOyXqk132NrYfoNB ziXhist+PXrAfwKTILOFy2Ga1MVnv9RnsLYd4skrYlla16EJUINDukrtMLuX/EZmoZZH YUzg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=BBYA784T; dkim=fail header.i=@linux-foundation.org header.s=google header.b=YVOwW+rU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g12-v6si4607831pln.330.2018.03.21.15.29.02; Wed, 21 Mar 2018 15:29:17 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=BBYA784T; dkim=fail header.i=@linux-foundation.org header.s=google header.b=YVOwW+rU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753989AbeCUW16 (ORCPT + 99 others); Wed, 21 Mar 2018 18:27:58 -0400 Received: from mail-it0-f41.google.com ([209.85.214.41]:35491 "EHLO mail-it0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753964AbeCUW1v (ORCPT ); Wed, 21 Mar 2018 18:27:51 -0400 Received: by mail-it0-f41.google.com with SMTP id v194-v6so8695723itb.0 for ; Wed, 21 Mar 2018 15:27:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc; bh=2rgwOXhdZJxD2Kmt57gR65OTd4O2hHdZz2/FNTSQXg4=; b=BBYA784T6+MWBk4/Zh0uTlc+VW2ZRTgLp6TdyIgud9Aocab893K5DtOfdogEaNBSuD CWoC4ZMgMbAKQ591bB56n/cZJNvhh1eWCg19t6+6Oo0CDcP4ZAFP4J1UMJ0c4iZENBaw q5ArtU2dtilCd14iJYMuum5RdFsrGSHPJxVSyNPmaj0SHqpMdGjM5LCxHWeDHl5ckwRP 7ObPnD8aj8jYXw8mbffcJemWfdW3SY3viKLdEje4cggpn+LLHJxEn/kFcRSfyszvZ8Da l0qDPy/y4K9oS2jYs9bPqQaZkECVHkaTIYitONhVLHEbUrbV1CGuAzS5PbIytpKcPbKA fWlQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=google; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc; bh=2rgwOXhdZJxD2Kmt57gR65OTd4O2hHdZz2/FNTSQXg4=; b=YVOwW+rUiccOanRXXFtr/omRt4u+MXEQTcWFuCNh7ZQQr5zKFWJnATeVvYKz+CN37C gCa20Zx9Ol6bWs12PwD5oDp28bfio7r1GE5MN4sm521ax3i2iz9wI689e2TD8ejX+OQN SwoOPU34yvbeQUUpHfG0pJTBPktHq9T2evSQc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:in-reply-to:references:from :date:message-id:subject:to:cc; bh=2rgwOXhdZJxD2Kmt57gR65OTd4O2hHdZz2/FNTSQXg4=; b=rbdHGPJ95UZFePJwXDpvTD1IZT+NIH/lsM+6bf8vRXfg7urESt0hX4BICG8OBeOdFF /jS/ce6VMTOplV/3v9fqKgSiPq9zm+Whe5xtwHMfBI7xQoKFIqmaLkicolBX4Fum9BbV Xfn+xs9B/nllHQpDv9I+mC6Pyttyc4FhIPYzM15JNRc00T9QtxFRUCBuWPqoPVJv+E1I IJDbj2s2NeKTffbFUM2IFPA/5eu9qwDiaUN4UoSP3isKErQEvMAy8s1AdfVFXaXRQvhz PnpJssJ0rZVZI2AgLv2HgRh9zwSBRcUJUoIlNkU6Hj+fhRteD5xNDdb6Ur1S+ZGM4bXZ 6v1A== X-Gm-Message-State: AElRT7Gk2xn5BpzpjLyYciNUYzZtZty9H+cfD9SeIJbEX9Q6sxoNiZAI LciwumMgNqHv7NlGppS+iO4oj1y6YgiQyuIfvA5xOHdn X-Received: by 2002:a24:45c4:: with SMTP id c65-v6mr6236458itd.16.1521671270359; Wed, 21 Mar 2018 15:27:50 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.95.15 with HTTP; Wed, 21 Mar 2018 15:27:49 -0700 (PDT) In-Reply-To: <6d771077-bee3-07c9-61c3-440dfed8e567@rasmusvillemoes.dk> References: <1521584015.31174.3.camel@med.uni-goettingen.de> <6d771077-bee3-07c9-61c3-440dfed8e567@rasmusvillemoes.dk> From: Linus Torvalds Date: Wed, 21 Mar 2018 15:27:49 -0700 X-Google-Sender-Auth: QKCvH1KmNQ_0FvKlGf-czcbjQ7w Message-ID: Subject: Re: detecting integer constant expressions in macros To: Rasmus Villemoes Cc: "Uecker, Martin" , "linux-kernel@vger.kernel.org" Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Mar 21, 2018 at 2:10 PM, Rasmus Villemoes wrote: >> >> Oh, I think it's guaranteed by the standard that 'sizeof()' doesn't >> evaluate the argument value, only the type. > > Even if there's some hypothetical scenario where x ends up containing > something of variably-modified type, could one just use 0? instead of 1? > . That doesn't affect the type of the whole expression. Fair enough. > I'm not really worthy of commenting or trying to improve on this, but I > think it's important that 'git blame' will forever give Martin the > credit for this You're saying "please don't ever blame me". Gotcha ;) > two minor suggestions: > > - Cast (x) to (long) to allow x to have type u64 on a 32-bit platform > without giving "warning: cast to pointer from integer of different > size". That also allows x to have pointer type (it's theoretically > useful to take max() of two pointers into an array), and not so > important for the kernel, floating point type. Fair enough. > - Maybe use (int*)4 to avoid the compiler complaining about creating a > non-aligned pointer. Yes. > I tried putting the below ugly test code through various gcc versions. > In no cases could I get different optimization options to generate > different results. I also couldn't get -Wall -Wextra to produce any > warnings that wasn't just due to the silly input (i.e., yes, I know I > have a comma expression with no side effects....). Most importantly, > ICE_P was always accepted as an ICE itself. Everything from 4.6 onwards > gives the same and expected output, namely 1 in the first four lines, 0 > otherwise. gcc 4.4 instead produces this: Ok, so since we're going to get rid of 4.4 support anyway because of our requirement of "asm goto", and since 4.5 was apparently never shipped in any distros, I think the minimum compiler version we care about is gcc-4.6. So the above sounds fine, and I won't worry about the fact that gcc-4.4 apparently does expression simplifications early. > So it seems to accept/treat (x)*0l as NULL as long as x has no > side-effects - where a function call is treated as having side effects > unless the function is declared with the const attribute, That's actually _largely_ the main thing we care about anyway in most places, so even the 4.4 behavior is probably acceptable in practice. For example, for "min/max()", it's true that constants are what we're looking at, but at the same time, the expression simplification really only cares about "no side effects". In some other cases, we really do want to see constants, though (the example I mentioned earlier with build-time simplification of bswap comes to mind). > comma-expressions are hard-coded as having side-effects [and what else > would they be good for, so that's not totally unreasonable...] Actually, I think one of our more common uses of a comma expression is not for side effects, but because of things like type warnings. I guess that is a "side effect" too, although it's really a build-time one, not a run-time one. > and statement expressions have side effects if they have more than one > statement. Ok, that's just odd semantics. But I guess it's actually a very natural result of "do obvious simplifications early", ie one of those expression simplifications that gcc-4.4 does on the early parse-tree level is to just turn a single-statement statement expression directly into just the expression. So I think the gcc-4.4 behavior is "understandable", even if it happens to be very much non-standard, and happens to break the "x*0" trick that Martin's masterpiece uses. If we knew exactly what gcc ends up simplifying, we might be able to work around it. For example, is the front-end tree simplification smart enough to realize that 1+(unsigned long)(x)+~(unsigned long)(x) is also 0? For a true *constant*, that's very easy for a compiler to see (just evaluate the damn thing). For an expression that isn't constant, it's a bit less obvious, and depends on knowing that "~x+1" is the same as "-x" in 2's complement. Of course, compilers *do* have that logic, but it's often deeper down than at parse-tree time. Doing some simple testing on godbolt, I see that gcc-4.1 actually accepts this program: unsigned long x; void *ptr= (void *)(x-x); and clearly considers "(void *)(x-x)" to be NULL. But if you write it as unsigned long x; void *ptr= (void *)(1+x+~x); it fails with 4.1. But then it succeeds again with 4.4 and sees that it's just an odd way to write 0. Damn clever compiler writers to hell, they clearly started doing that simplification early. There are other weird ways to calculate 0, though. We're not *just* limited to "*0" and trivial bit tricks. I bet we could come up with something that always evaluates to zero, but is too hard for gcc to turn into zero symbolically. For example, gcc-4.4 does not realize that #define rightmost(x) ((x)&-(x)) #define lowmask(x) (rightmost(x)-1) unsigned long x; void *ptr= (void *)(x&lowmask(x)); is a *really* weird way to write a constant zero. But if 'x' really is a constant, it's immediately obvious because it just evaluates the expression and get zero. So if you use "#define x 0x1234", it turns into NULL again. So we *could* make this work even for gcc-4.4. Linus