diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2022-01-08 11:53:52 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2022-01-08 11:53:52 +0100 | 
| commit | fa838e76139763f902c7d27cb9e1d393ed6a15e4 (patch) | |
| tree | 7d0ae09775ea950056193eaa2ca93844299d46f1 /lib/verify.h | |
| parent | c78359d9542c86b972aac373efcf7bc7a8a560e5 (diff) | |
| parent | 2959e59fab3bab834368adefd90bd4b1b094366b (diff) | |
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'lib/verify.h')
| -rw-r--r-- | lib/verify.h | 162 | 
1 files changed, 92 insertions, 70 deletions
| diff --git a/lib/verify.h b/lib/verify.h index a3b2a2d6..07b2f486 100644 --- a/lib/verify.h +++ b/lib/verify.h @@ -1,27 +1,18 @@  /* Compile-time assert-like macros. -   Copyright (C) 2005-2006, 2009-2018 Free Software Foundation, Inc. +   Copyright (C) 2005-2006, 2009-2022 Free Software Foundation, Inc. -   This program is free software: you can redistribute it and/or -   modify it under the terms of either: +   This file is free software: you can redistribute it and/or modify +   it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. -     * the GNU Lesser General Public License as published by the Free -       Software Foundation; either version 3 of the License, or (at your -       option) any later version. - -   or - -     * the GNU General Public License as published by the Free -       Software Foundation; either version 2 of the License, or (at your -       option) any later version. - -   or both in parallel, as here. -   This program is distributed in the hope that it will be useful, +   This file is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -   GNU General Public License for more details. +   GNU Lesser General Public License for more details. -   You should have received a copy of the GNU General Public License +   You should have received a copy of the GNU Lesser General Public License     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */  /* Written by Paul Eggert, Bruno Haible, and Jim Meyering.  */ @@ -30,31 +21,32 @@  #define _GL_VERIFY_H -/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11. -   This is supported by GCC 4.6.0 and later, in C mode, and its use -   here generates easier-to-read diagnostics when verify (R) fails. +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC) +   works as per C11.  This is supported by GCC 4.6.0+ and by clang 4+. -   Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11. -   This will likely be supported by future GCC versions, in C++ mode. +   Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as +   per C2x.  This is supported by GCC 9.1+. -   Use this only with GCC.  If we were willing to slow 'configure' -   down we could also use it with other compilers, but since this -   affects only the quality of diagnostics, why bother?  */ -#if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \ -     && (201112L <= __STDC_VERSION__  || !defined __STRICT_ANSI__) \ -     && !defined __cplusplus) -# define _GL_HAVE__STATIC_ASSERT 1 -#endif -/* The condition (99 < __GNUC__) is temporary, until we know about the -   first G++ release that supports static_assert.  */ -#if (99 < __GNUC__) && defined __cplusplus -# define _GL_HAVE_STATIC_ASSERT 1 +   Support compilers claiming conformance to the relevant standard, +   and also support GCC when not pedantic.  If we were willing to slow +   'configure' down we could also use it with other compilers, but +   since this affects only the quality of diagnostics, why bother?  */ +#ifndef __cplusplus +# if (201112L <= __STDC_VERSION__ \ +      || (!defined __STRICT_ANSI__ \ +          && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 4 <= __clang_major__))) +#  define _GL_HAVE__STATIC_ASSERT 1 +# endif +# if (202000L <= __STDC_VERSION__ \ +      || (!defined __STRICT_ANSI__ && 9 <= __GNUC__)) +#  define _GL_HAVE__STATIC_ASSERT1 1 +# endif  #endif  /* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other     system headers, defines a conflicting _Static_assert that is no     better than ours; override it.  */ -#ifndef _GL_HAVE_STATIC_ASSERT +#ifndef _GL_HAVE__STATIC_ASSERT  # include <stddef.h>  # undef _Static_assert  #endif @@ -152,9 +144,9 @@       which do not support _Static_assert, also do not warn about the       last declaration mentioned above. -   * GCC warns if -Wnested-externs is enabled and verify() is used +   * GCC warns if -Wnested-externs is enabled and 'verify' is used       within a function body; but inside a function, you can always -     arrange to use verify_expr() instead. +     arrange to use verify_expr instead.     * In C++, any struct definition inside sizeof is invalid.       Use a template type to work around the problem.  */ @@ -206,48 +198,63 @@ template <int w>  #endif  /* Verify requirement R at compile-time, as a declaration without a -   trailing ';'.  If R is false, fail at compile-time, preferably -   with a diagnostic that includes the string-literal DIAGNOSTIC. +   trailing ';'.  If R is false, fail at compile-time. + +   This macro requires three or more arguments but uses at most the first +   two, so that the _Static_assert macro optionally defined below supports +   both the C11 two-argument syntax and the C2x one-argument syntax.     Unfortunately, unlike C11, this implementation must appear as an     ordinary declaration, and cannot appear inside struct { ... }.  */ -#ifdef _GL_HAVE__STATIC_ASSERT -# define _GL_VERIFY _Static_assert +#if 200410 <= __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)				       \ +# define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \      extern int (*_GL_GENSYM (_gl_verify_function) (void))	       \        [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]  #endif  /* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h.  */  #ifdef _GL_STATIC_ASSERT_H -# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert -#  define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC) +# if !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert +#  define _Static_assert(...) \ +     _GL_VERIFY (__VA_ARGS__, "static assertion failed", -)  # endif -# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert +# if __cpp_static_assert < 201411 && !defined static_assert  #  define static_assert _Static_assert /* C11 requires this #define.  */  # endif  #endif  /* @assert.h omit start@  */ +#if 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)) +# define _GL_HAS_BUILTIN_TRAP 1 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_TRAP __has_builtin (__builtin_trap) +#else +# define _GL_HAS_BUILTIN_TRAP 0 +#endif + +#if 4 < __GNUC__ + (5 <= __GNUC_MINOR__) +# define _GL_HAS_BUILTIN_UNREACHABLE 1 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable) +#else +# define _GL_HAS_BUILTIN_UNREACHABLE 0 +#endif +  /* Each of these macros verifies that its argument R is nonzero.  To     be portable, R should be an integer constant expression.  Unlike     assert (R), there is no run-time overhead.     There are two macros, since no single macro can be used in all -   contexts in C.  verify_true (R) is for scalar contexts, including +   contexts in C.  verify_expr (R, E) is for scalar contexts, including     integer constant expression contexts.  verify (R) is for declaration     contexts, e.g., the top level.  */ -/* Verify requirement R at compile-time, as an integer constant expression. -   Return 1.  This is equivalent to verify_expr (R, 1). - -   verify_true is obsolescent; please use verify_expr instead.  */ - -#define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")") -  /* Verify requirement R at compile-time.  Return the value of the     expression E.  */ @@ -255,37 +262,52 @@ template <int w>     (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E))  /* Verify requirement R at compile-time, as a declaration without a -   trailing ';'.  */ +   trailing ';'.  verify (R) acts like static_assert (R) except that +   it is portable to C11/C++14 and earlier, it can issue better +   diagnostics, and its name is shorter and may be more convenient.  */ -#ifdef __GNUC__ -# define verify(R) _GL_VERIFY (R, "verify (" #R ")") +#ifdef __PGI +/* PGI barfs if R is long.  */ +# define verify(R) _GL_VERIFY (R, "verify (...)", -)  #else -/* PGI barfs if R is long.  Play it safe.  */ -# define verify(R) _GL_VERIFY (R, "verify (...)") +# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)  #endif -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif +/* Assume that R always holds.  Behavior is undefined if R is false, +   fails to evaluate, or has side effects. + +   'assume (R)' is a directive from the programmer telling the +   compiler that R is true so the compiler needn't generate code to +   test R.  This is why 'assume' is in verify.h: it's related to +   static checking (in this case, static checking done by the +   programmer), not dynamic checking. + +   'assume (R)' can affect compilation of all the code, not just code +   that happens to be executed after the assume (R) is "executed". +   For example, if the code mistakenly does 'assert (R); assume (R);' +   the compiler is entitled to optimize away the 'assert (R)'. + +   Although assuming R can help a compiler generate better code or +   diagnostics, performance can suffer if R uses hard-to-optimize +   features such as function calls not inlined by the compiler. -/* Assume that R always holds.  This lets the compiler optimize -   accordingly.  R should not have side-effects; it may or may not be -   evaluated.  Behavior is undefined if R is false.  */ +   Avoid Clang's __builtin_assume, as it breaks GNU Emacs master +   as of 2020-08-23T21:09:49Z!eggert@cs.ucla.edu; see +   <https://bugs.gnu.org/43152#71>.  It's not known whether this breakage +   is a Clang bug or an Emacs bug; play it safe for now.  */ -#if (__has_builtin (__builtin_unreachable) \ -     || 4 < __GNUC__ + (5 <= __GNUC_MINOR__)) +#if _GL_HAS_BUILTIN_UNREACHABLE  # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())  #elif 1200 <= _MSC_VER  # define assume(R) __assume (R) -#elif ((defined GCC_LINT || defined lint) \ -       && (__has_builtin (__builtin_trap) \ -           || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)))) +#elif (defined GCC_LINT || defined lint) && _GL_HAS_BUILTIN_TRAP    /* Doing it this way helps various packages when configured with       --enable-gcc-warnings, which compiles with -Dlint.  It's nicer       when 'assume' silences warnings even with older GCCs.  */  # define assume(R) ((R) ? (void) 0 : __builtin_trap ())  #else -# define assume(R) ((void) (0 && (R))) +  /* Some tools grok NOTREACHED, e.g., Oracle Studio 12.6.  */ +# define assume(R) ((R) ? (void) 0 : /*NOTREACHED*/ (void) 0)  #endif  /* @assert.h omit end@  */ | 
