bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: clang++ 11 compilation issues


From: Bruno Haible
Subject: Re: clang++ 11 compilation issues
Date: Tue, 12 Jan 2021 21:19:24 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-197-generic; KDE/5.18.0; x86_64; ; )

Hi Alexandre,

> I'm upgrading a project that used a 8-month-old copy of gnulib to
> today's version

Since then, gnulib has improved its support for clang.

> I compile with -Werror.

Gnulib generally does not support -Werror on arbitrary platforms.

We try to make for a warning-free compilation on glibc systems with GCC,
as far as it is reasonable (but it does not work always, due to GCC bugs).

> Testing the result with clang++ 11.0.1-2 (Debian unstable)

Now, using clang with -Wall and -Werror is a recipe for failures, for sure.

This is because clang has _many_ warnings, and

  - Some of the warnings are of the kind "tell me when you did a certain
    optimization". Most of the warnings in this category are not helpful.

  - Some of the warnings merely enforce certain coding styles. You can
    try to enforce your preferred coding style on your code, but enforcing
    it on Gnulib code is a non-starter.

  - Some of the warnings are contradictory.

You are supposed to choose the warnings that are reasonable for your
project. For some project of mine, I had to disable 20-40 warning options
before I could get reasonable output.

> > ../lib/gettext.h:234:22: error: zero as null pointer constant 
> > [-Werror,-Wzero-as-null-pointer-constant]
> >   if (msg_ctxt_id != NULL)
> >                      ^~~~

This will not be changed. NULL is the preferred way to denote a null pointer.

> Just replacing these two tests with "if (msg_ctxt_id)" gets rid of the issue.

... but makes the code harder to understand.

> (2) ARGMATCH_VERIFY ends up using _Static_assert which is a C11 keyword
>     that does not exist in C++.  However static_assert exists in C++11
>     with two args, and since C++17 with one arg.

We prefer to use _Static_assert with 2 arguments, since it causes the compiler
to give the diagnostic specified by the programmer. A macro or built-in
that accepts only 1 argument is an inferior solution for this case.

> > clang++ -DHAVE_CONFIG_H -I. -I..  -I.. -I.. -I../buddy/src -I../lib 
> > -I../lib  -W -Wall -Werror -Wint-to-void-pointer-cast 
> > -Wzero-as-null-pointer-constant -Wcast-align -Wpointer-arith 
> > -Wwrite-strings -Wcast-qual -DXTSTRINGDEFINES -Wdocumentation 
> > -Wmissing-declarations -Woverloaded-virtual -Wmisleading-indentation 
> > -Wimplicit-fallthrough -Wnull-dereference -Wsuggest-override -Wpedantic 
> > -fvisibility=hidden -fvisibility-inlines-hidden -DSPOT_BUILD -std=c++17 -g 
> > -O -MT common_aoutput.o -MD -MP -MF .deps/common_aoutput.Tpo -c -o 
> > common_aoutput.o common_aoutput.cc
> > common_aoutput.cc:85:1: error: '_Static_assert' is a C11 extension 
> > [-Werror,-Wc11-extensions]
> > ARGMATCH_VERIFY(check_args, check_types);
> > ^
> > ../lib/argmatch.h:45:5: note: expanded from macro 'ARGMATCH_VERIFY'
> >     verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1)
> >     ^
> > ../lib/verify.h:289:20: note: expanded from macro 'verify'
> > # define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)
> >                    ^
> > ../lib/verify.h:229:41: note: expanded from macro '_GL_VERIFY'
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
> >                                         ^
> > common_aoutput.cc:397:7: error: '_Static_assert' is a C11 extension 
> > [-Werror,-Wc11-extensions]
> >       ARGMATCH_VERIFY(args, format);
> >       ^
> > ../lib/argmatch.h:45:5: note: expanded from macro 'ARGMATCH_VERIFY'
> >     verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1)
> >     ^
> > ../lib/verify.h:289:20: note: expanded from macro 'verify'
> > # define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)
> >                    ^
> > ../lib/verify.h:229:41: note: expanded from macro '_GL_VERIFY'
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
> >                                         ^
> > 2 errors generated.
> 
> to work around this, I've just changed the definition of _GL_VERIFY in
> lib/verify.h from
> 
> > #if defined _GL_HAVE__STATIC_ASSERT
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
> > #else
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \
> >     extern int (*_GL_GENSYM (_gl_verify_function) (void))          \
> >       [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
> > #endif
> 
> to
> 
> > #if defined __cpp_static_assert
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...) static_assert (R, DIAGNOSTIC)
> > #elif defined _GL_HAVE__STATIC_ASSERT
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
> > #else
> > # define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \
> >     extern int (*_GL_GENSYM (_gl_verify_function) (void))          \
> >       [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
> > #endif

Thanks for the suggestion. Committed through the patch below.

> However there are a few __cplusplus tests at the top of the file that
> attempt to tell when _Static_assert can be used (and failed here), and I
> do not really follow that logic.

These lines define our own witnesses whether a certain feature is available,
rather than merely relying on __cpp_static_assert. This allows us to
cater with compilers which lie about their features (e.g. HP compilers
are frequently broken in this way) or consider GCC's -pedantic option.

> Those macros check for
> __cpp_static_assert to assume something about _Static_assert, which
> seems dubious.

Paul can tell more about this one.


2021-01-12  Bruno Haible  <bruno@clisp.org>

        verify: Use C++11 static_assert when available.
        Reported by Alexandre Duret-Lutz <adl@lrde.epita.fr> in
        <https://lists.gnu.org/archive/html/bug-gnulib/2021-01/msg00177.html>.
        * lib/verify.h (_GL_HAVE_STATIC_ASSERT_CXX11): New macro.
        (_GL_HAVE_STATIC_ASSERT_CXX17): Renamed from _GL_HAVE_STATIC_ASSERT1.
        (_GL_VERIFY): Use static_assert when available with C++11 syntax.

diff --git a/lib/verify.h b/lib/verify.h
index 3cdcdca..a9e7589 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -29,7 +29,11 @@
    per C2X.  This is supported by GCC 9.1 and later, and by clang in
    C++1z mode.
 
-   Define _GL_HAVE_STATIC_ASSERT1 if static_assert (R) works as per
+   Define _GL_HAVE_STATIC_ASSERT_CXX11 if static_assert (R, DIAGNOSTIC)
+   works as per C++11.  This is supported by GCC 6.1 and later, and by
+   clang in C++11 mode.
+
+   Define _GL_HAVE_STATIC_ASSERT_CXX17 if static_assert (R) works as per
    C++17.  This is supported by GCC 9.1 and later, and by clang in
    C++1z mode.
 
@@ -54,10 +58,15 @@
 # if 4 <= __clang_major__ && 201411 <= __cpp_static_assert
 #  define _GL_HAVE__STATIC_ASSERT1 1
 # endif
+# if 201103L <= __cplusplus \
+     || 6 <= __GNUC__ \
+     || (4 <= __clang_major__ && 200410 <= __cpp_static_assert)
+#  define _GL_HAVE_STATIC_ASSERT_CXX11 1
+# endif
 # if 201703L <= __cplusplus \
      || 9 <= __GNUC__ \
      || (4 <= __clang_major__ && 201411 <= __cpp_static_assert)
-#  define _GL_HAVE_STATIC_ASSERT1 1
+#  define _GL_HAVE_STATIC_ASSERT_CXX17 1
 # endif
 #endif
 
@@ -225,7 +234,9 @@ template <int w>
    Unfortunately, unlike C11, this implementation must appear as an
    ordinary declaration, and cannot appear inside struct { ... }.  */
 
-#if defined _GL_HAVE__STATIC_ASSERT
+#if defined _GL_HAVE_STATIC_ASSERT_CXX11
+# define _GL_VERIFY(R, DIAGNOSTIC, ...) static_assert (R, DIAGNOSTIC)
+#elif defined _GL_HAVE__STATIC_ASSERT
 # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
 #else
 # define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \
@@ -239,7 +250,7 @@ template <int w>
 #  define _Static_assert(...) \
      _GL_VERIFY (__VA_ARGS__, "static assertion failed", -)
 # endif
-# if !defined _GL_HAVE_STATIC_ASSERT1 && !defined static_assert
+# if !defined _GL_HAVE_STATIC_ASSERT_CXX17 && !defined static_assert
 #  define static_assert _Static_assert /* C11 requires this #define.  */
 # endif
 #endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]