From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id n/kCOFIjAWHXFwAAWB0awg (envelope-from ) for ; Wed, 28 Jul 2021 05:28:50 -0400 Received: by simark.ca (Postfix, from userid 112) id D5AB41EDFB; Wed, 28 Jul 2021 05:28:50 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,T_DKIM_INVALID,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id F32FD1E813 for ; Wed, 28 Jul 2021 05:28:48 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 53853398EC17 for ; Wed, 28 Jul 2021 09:28:48 +0000 (GMT) Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by sourceware.org (Postfix) with ESMTPS id 625153853C03 for ; Wed, 28 Jul 2021 09:28:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 625153853C03 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wm1-x332.google.com with SMTP id f14-20020a05600c154eb02902519e4abe10so3774963wmg.4 for ; Wed, 28 Jul 2021 02:28:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=p79dguqIQFfX9+Q7QmL9qIYV7fKm4bfAUZdqg+3gd1w=; b=FtFe4E8er0h7oknSgiGKD0hkyw0LAqashm6UG2MGXtoovwaRNDqaYvTqgJX5vCfd9E +VFp+OzRK7NKEcO1jMluJ/mEag7UbrERTKBKGYClIAqK9gdcXDCkTaDWRlg+aMuYgi3j vcaZkWRu9xwBI1JCKui9PRRC0p6F5vv5UdKFIHDdhYWlM2evnIebrcyrOzgerCTF6W+j QZ0EsKeUdrcoWuzfdFLkBrMvnj9t1cdbhpSuG7PpKuuJnXRpvBAv9+OS7I9O8n9ff3/q icz369beWejdC2qMT2DQfTrklIr8LA59uDKG3DMaDcATF3bzqaPtlSsb03msCMw9hpOt ElZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=p79dguqIQFfX9+Q7QmL9qIYV7fKm4bfAUZdqg+3gd1w=; b=iUjPQFHK0a4z5koEf5xQOSDDzcoE/NEesXkYT2h2xXXK3eVac7RWQlzAKVM0QJw02m LHKcO/fAvEvev0JYj4CL68V+Kx5NZJ5CHJQFrYaXAhEIJtQdMzk1d/KMMpy8Oag2W2F6 5pW5GKfkzN51j2QB0mvihL1e7VaJza5j+pg5DlBhdhoxHolOq5ZlrcSfUJ3mPFuKoHko td88VF0mpCibRGtjh+Azv36TUShfpYtxzHYkslHGbRQ+lC2hafYagIBH5K1QpEIuZkii ys3r9htcJjEjUoBFkNgFirZUAs42hjpXfDs0aX8BjR+BkLRyjDI+PnuCSdCpvE99dpZs NsSw== X-Gm-Message-State: AOAM531BPDGJbL2z/RKE+Tni4DNR37gTbCp78wWC4fPq0kqVy61mlxdP XXcRh6mSZ7phV6Pxs6cC8PbVkQ== X-Google-Smtp-Source: ABdhPJw8DI93ndZyPdiBB9y05UNeLBYw8PnW6krjk867EX55f8oluPCrxHhR3n3pBWESu23NLw6tFQ== X-Received: by 2002:a1c:cc02:: with SMTP id h2mr25859229wmb.39.1627464514410; Wed, 28 Jul 2021 02:28:34 -0700 (PDT) Received: from localhost (host86-161-16-194.range86-161.btcentralplus.com. [86.161.16.194]) by smtp.gmail.com with ESMTPSA id w15sm5672243wmi.3.2021.07.28.02.28.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Jul 2021 02:28:34 -0700 (PDT) Date: Wed, 28 Jul 2021 10:28:32 +0100 From: Andrew Burgess To: Tom de Vries Subject: Re: [gdb/build] Fix Werror=nonnull-compare build breaker with gcc 12 Message-ID: <20210728092832.GA8980@embecosm.com> References: <20210726211101.ivychvbfgaafxjtz@lug-owl.de> <20210727100354.GB4037238@embecosm.com> <20210727113511.GC4037238@embecosm.com> <6cf80ba9-b010-bb42-c92d-84e4f396813c@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Operating-System: Linux/5.8.18-100.fc31.x86_64 (x86_64) X-Uptime: 10:26:26 up 15:33, 1 user, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "gdb-patches@sourceware.org" Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" * Tom de Vries [2021-07-27 18:28:30 +0200]: > [ was : Re: Building with recent GCC versions: > gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' > compared to NULL [-Werror=nonnull-compare] ] > > [ Moving discussion to gdb-patches ] > > On 7/27/21 3:38 PM, Tom de Vries wrote: > > On 7/27/21 1:49 PM, Tom de Vries wrote: > >> On 7/27/21 1:35 PM, Andrew Burgess wrote: > >>> * Tom de Vries [2021-07-27 12:44:10 +0200]: > >>> > >>>> On 7/27/21 12:03 PM, Andrew Burgess wrote: > >>>>> * Jan-Benedict Glaw [2021-07-26 23:11:01 +0200]: > >>>>> > >>>>>> Hi! > >>>>>> > >>>>>> I'm running some CI builds and noticed that, when building GDB with > >>>>>> quite recent GCC versions, it breaks. > >>>>>> > >>>>>> With ie. this "gcc-snapshot" GCC from Debian: > >>>>>> > >>>>>> /usr/lib/gcc-snapshot/bin/gcc --version > >>>>>> gcc (Debian 20210630-1) 12.0.0 20210630 (experimental) [master revision 6bf383c37e6:93c270320bb:35da8a98026849bd20d16bbf9210ac1d0b44ea6a] > >>>>>> > >>>>>> we see: > >>>>>> > >>>>>> ./configure --target=i686-linux --prefix=/tmp/gdb-i686-linux > >>>>>> [...] > >>>>>> all make V=1 all-gdb > >>>>>> [...] > >>>>>> [all 2021-07-26 20:39:22] /usr/lib/gcc-snapshot/bin/g++ -x c++ -I. -I. -I./config -DLOCALEDIR="\"/tmp/gdb-i686-linux/share/locale\"" -DHAVE_CONFIG_H -I./../include/opcode -I./../readline/readline/.. -I./../zlib -I../bfd -I./../bfd -I./../include -I../libdecnumber -I./../libdecnumber -I./../gnulib/import -I../gnulib/import -I./.. -I.. -DTUI=1 -I./.. -pthread -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-variable -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-error=maybe-uninitialized -Wno-mismatched-tags -Wsuggest-override -Wimplicit-fallthrough=3 -Wduplicated-cond -Wshadow=local -Wdeprecated-copy -Wdeprecated-copy-dtor -Wredundant-move -Wmissing-declarations -Wstrict-null-sentinel -Wformat -Wformat-nonliteral -Werror -g -O2 -c -o compile/compile.o -MT compile/compile.o -MMD -MP -MF compile/.deps/compile.Tpo compile/compile.c > >>>>>> [all 2021-07-26 20:39:26] In file included from ./../gdbsupport/common-defs.h:126, > >>>>>> [all 2021-07-26 20:39:26] from ./defs.h:28, > >>>>>> [all 2021-07-26 20:39:26] from compile/compile.c:20: > >>>>>> [all 2021-07-26 20:39:26] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)': > >>>>>> [all 2021-07-26 20:39:26] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare] > >>>>>> [all 2021-07-26 20:39:26] 35 | ((void) ((expr) ? 0 : \ > >>>>>> [all 2021-07-26 20:39:26] | ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > >>>>>> [all 2021-07-26 20:39:26] 36 | (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0))) > >>>>>> [all 2021-07-26 20:39:26] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > >>>>>> [all 2021-07-26 20:39:26] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert' > >>>>>> [all 2021-07-26 20:39:26] 38 | gdb_assert (filename != NULL); > >>>>>> [all 2021-07-26 20:39:26] | ^~~~~~~~~~ > >>>>>> [all 2021-07-26 20:39:27] cc1plus: all warnings being treated as errors > >>>>>> [all 2021-07-26 20:39:27] make[1]: *** [Makefile:1642: compile/compile.o] Error 1 > >>>>>> [all 2021-07-26 20:39:27] make[1]: Leaving directory '/var/lib/laminar/run/gdb-i686-linux/4/binutils-gdb/gdb' > >>>>>> [all 2021-07-26 20:39:27] make: *** [Makefile:11410: all-gdb] Error 2 > >>>>>> > >>>>>> > >>>>>> I also discussed this on the GCC patches mailing list > >>>>>> (https://gcc.gnu.org/pipermail/gcc-patches/2021-July/575568.html), > >>>>>> where Martin suggested that this should be fixed here in GDB. > >>>>>> > >>>>>> Any thoughts about this? > >>>>> > >>>>> As I understand it the nonnull attribute only provides compile time > >>>>> protection against explicitly passing NULL, there's no compiled in > >>>>> non-null check (well, maybe with -fisolate-erroneous-paths-attribute, > >>>>> but the assert might give a better error message). > >>>>> > >>>>> This means its still possible to pass NULL to a nonnull function, its > >>>>> just the behaviour of the program is undefined in that case. > >>>>> > >>>>> So, it doesn't seem crazy that we might want to both (a) have a > >>>>> function declared nonnull, to prevent explicitly passing NULL, and (b) > >>>>> have a NULL check inside the function to catch logic bugs that result > >>>>> in NULL being passed. > >>>>> > >>>>> We could, of course, push the assert outside of the function, but that > >>>>> would really suck due to code duplication, and the risk of missing an > >>>>> assert, so that seems like a non-starter. > >>>>> > >>>>> We could drop either the assert, or the nonnull attribute, but that > >>>>> would suck as both give a valuable, but different form of protection. > >>>>> > >>>>> After some experimenting, I suspect that the assert is being optimised > >>>>> away anyway, which kind of makes sense, as we're telling the compiler > >>>>> it can assume that the pointer is non-null. > >>>>> > >>>> > >>>> Yes, in fact that's what the nonnull-compare warning specifically warns > >>>> against: there's some code that may be optimized away, due to the > >>>> nonnull attribute. > >>>> > >>>>> So, what we probably want is someway to tell (or trick) GCC into > >>>>> including the null check even in the nonnull function.... > >>>>> > >>>>> ... here's what I came up with, add this somewhere: > >>>>> > >>>>> template > >>>>> bool __attribute__ ((noinline)) > >>>>> nonnull_arg_is_really_not_null (const T *ptr) > >>>>> { > >>>>> return ptr != nullptr; > >>>>> } > >>>>> > >>>>> then change the assert to: > >>>>> > >>>>> gdb_assert (nonnull_arg_is_really_not_null (filename)); > >>>>> > >>>>> Seems to keep the assert, and silence the warning. Thoughts? > >>>>> > >>>> > >>>> I understand why it works, but it seems fragile to me. At some point > >>>> some compiler may get smart enough to also optimize this case, and then > >>>> we're back in the same situation. > >>> > >>> Good point. > >>> > >>> The GCC documentation for noinline[1] suggests we can avoid the call > >>> being removed by adding 'asm ("");' into the function: > >>> > >>> template > >>> bool __attribute__ ((noinline)) > >>> nonnull_arg_is_really_not_null (const T *ptr) > >>> { > >>> asm (""); > >>> return ptr != nullptr; > >>> } > >>> > >>> I'm not really arguing for this approach over any other, just sharing > >>> what I discovered. > >>> > >> > >> Ack, understood. Note that the added asm doesn't stop a compiler from > >> doing: > >> ... > >> gdb_assert (nonnull_arg_is_really_not_null (filename)); > >> ... > >> -> > >> ... > >> nonnull_arg_is_really_not_null (filename); > >> gdb_assert (true); > >> ... > >> > >> Thanks, > >> - Tom > >> > >>> Thanks, > >>> Andrew > >>> > >>> [1] https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes > >>> > >>>> > >>>> I wonder whether using volatile is a better idea (can't try this out > >>>> right now). > >>>> > > > > I was thinking of something like this: > > ... > > diff --git a/gdbsupport/gdb_unlinker.h b/gdbsupport/gdb_unlinker.h > > index bda6fe7ab54..3d99b41e7ad 100644 > > --- a/gdbsupport/gdb_unlinker.h > > +++ b/gdbsupport/gdb_unlinker.h > > @@ -20,6 +20,13 @@ > > #ifndef COMMON_GDB_UNLINKER_H > > #define COMMON_GDB_UNLINKER_H > > > > +template > > +const T *volatile > > +ignore_nonnull (const T *ptr) > > +{ > > + return ptr; > > +} > > + > > namespace gdb > > { > > > > @@ -35,7 +42,7 @@ class unlinker > > unlinker (const char *filename) ATTRIBUTE_NONNULL (2) > > : m_filename (filename) > > { > > - gdb_assert (filename != NULL); > > + gdb_assert (ignore_nonnull (filename) != NULL); > > } > > > > ~unlinker () > > ... > > > > This builds for me, though I haven't got a setup yet where the warning > > reproduces, so I can't check whether it actually fixes things. > > I managed now to reproduce, and wrote a patch along these lines. > > Any comments? > > In particular, any suggestion where to put ignore_nonnull? > > Or, is it perhaps a better idea to have a gdb_assert_nonnull and > implement things there? > > Thanks, > - Tom > [gdb/build] Fix Werror=nonnull-compare build breaker with gcc 12 > > When building gdb using current gcc trunk, we run into: > ... > gdbsupport/gdb_unlinker.h: \ > In constructor 'gdb::unlinker::unlinker(const char*)': > gdbsupport/gdb_assert.h:35:4: error: \ > 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare] > 35| ((void) ((expr) ? 0 : \ > | ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > 36| (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0))) > | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert' > 38| gdb_assert (filename != NULL); > | ^~~~~~~~~~ > cc1plus: all warnings being treated as errors > make[1]: *** [compile/compile.o] Error 1 > ... > > The warning triggers in this code: > ... > unlinker (const char *filename) ATTRIBUTE_NONNULL (2) > : m_filename (filename) > { > gdb_assert (filename != NULL); > } > ... > > The attribute nonnull (applied here to the filename parameter) has two > effects: > - if the compiler determines that a null pointer is passed in argument > filename, and the -Wnonnull option is enabled, a warning is issued. > - the compiler may perform optimizations based on the knowledge that > filename != NULL (unless disabled by the -fno-delete-null-pointer-checks > option). > > The warning Werror=nonnull-compare warns that the compiler may perform the > optimization: > .... > gdb_assert (filename != NULL); > ... > -> > ... > gdb_assert (true); > ... > in which case "unlinker (obfuscated_NULL)" no longer will trigger the assert. > And we want to keep the gdb_assert to detect cases that -Wnonnull doesn't > detect. > > We could simply fix this by dropping the attribute, but that means that we no > longer get the -Wnonnull warning. > > Fix this by ignoring the nonnull attribute using a function: > ... > template > const T *volatile > ignore_nonnull (const T *ptr) > { > return ptr; > } > ... > such that we can do: > ... > gdb_assert (ignore_nonnull (filename) != NULL); > ... > > Build on x86_64-linux using "gcc version 12.0.0 20210727 (experimental) (GCC)" > build from gcc commit 7ffba77d01a. > > Reported-By: Jan-Benedict Glaw > > gdb/ChangeLog: > > 2021-07-27 Andrew Burgess > Tom de Vries > > * gdbsupport/gdb_assert.h (ignore_nonnull): New function. > * gdb/gdb_regex.c (compiled_regex::compiled_regex): Use ignore_nonnull > to ignore nonnull attribute on function parameter. > * gdbsupport/gdb_unlinker.h (unlinker::unlinker): Same. > > --- > gdb/gdb_regex.c | 4 ++-- > gdbsupport/gdb_assert.h | 6 ++++++ > gdbsupport/gdb_unlinker.h | 2 +- > 3 files changed, 9 insertions(+), 3 deletions(-) > > diff --git a/gdb/gdb_regex.c b/gdb/gdb_regex.c > index 17fbfd28ee8..22473f57e26 100644 > --- a/gdb/gdb_regex.c > +++ b/gdb/gdb_regex.c > @@ -22,8 +22,8 @@ > compiled_regex::compiled_regex (const char *regex, int cflags, > const char *message) > { > - gdb_assert (regex != NULL); > - gdb_assert (message != NULL); > + gdb_assert (ignore_nonnull (regex) != NULL); > + gdb_assert (ignore_nonnull (message) != NULL); > > int code = regcomp (&m_pattern, regex, cflags); > if (code != 0) > diff --git a/gdbsupport/gdb_assert.h b/gdbsupport/gdb_assert.h > index 00553a78613..26a9594e7f8 100644 > --- a/gdbsupport/gdb_assert.h > +++ b/gdbsupport/gdb_assert.h > @@ -58,4 +58,10 @@ > internal_error (__FILE__, __LINE__, _(message)) > #endif > > +template > +const T *volatile > +ignore_nonnull (const T *ptr) > +{ > + return ptr; > +} Sorry, I missed that the thread had moved to the patches list. Using trunk GCC I see a warning like this: error: 'volatile'-qualified return type is deprecated [-Werror=volatile] 21 | const T * volatile | ^~~~~ cc1plus: all warnings being treated as errors Compiler returned: 1 See: https://godbolt.org/z/nfhq6zb7q Thanks, Andrew > #endif /* COMMON_GDB_ASSERT_H */ > diff --git a/gdbsupport/gdb_unlinker.h b/gdbsupport/gdb_unlinker.h > index bda6fe7ab54..4aa4f3fc3e9 100644 > --- a/gdbsupport/gdb_unlinker.h > +++ b/gdbsupport/gdb_unlinker.h > @@ -35,7 +35,7 @@ class unlinker > unlinker (const char *filename) ATTRIBUTE_NONNULL (2) > : m_filename (filename) > { > - gdb_assert (filename != NULL); > + gdb_assert (ignore_nonnull (filename) != NULL); > } > > ~unlinker ()