diff options
| author | Peter Eisentraut | 2025-12-15 10:43:11 +0000 |
|---|---|---|
| committer | Peter Eisentraut | 2025-12-15 10:54:23 +0000 |
| commit | 17f446784d54da827f74c2acc0fa772a41b92354 (patch) | |
| tree | 8b64f93bee8292d5af65d2ad7d4ce91370b21436 /src/include/c.h | |
| parent | 366dcdaf5779792f522d1d18a8e558244850afdf (diff) | |
Refactor static_assert() support.
HAVE__STATIC_ASSERT was really a test for GCC statement expressions,
as needed for StaticAssertExpr() now that _Static_assert could be
assumed to be available through our C11 requirement. This
artificially prevented Visual Studio from being able to use
static_assert() in other contexts.
Instead, make a new test for HAVE_STATEMENT_EXPRESSIONS, and use that
to control only whether StaticAssertExpr() uses fallback code, not the
other variants. This improves the quality of failure messages in the
(much more common) other variants under Visual Studio.
Also get rid of the two separate implementations for C++, since the C
implementation is also also valid as C++11. While it is a stretch to
apply HAVE_STATEMENT_EXPRESSIONS tested with $CC to a C++ compiler,
the previous C++ coding assumed that the C++ compiler had them
unconditionally, so it isn't a new stretch. In practice, the C and
C++ compilers are very likely to agree, and if a combination is ever
reported that falsifies this assumption we can always reconsider that.
Author: Thomas Munro <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CA%2BhUKGKvr0x_oGmQTUkx%3DODgSksT2EtgCA6LmGx_jQFG%3DsDUpg%40mail.gmail.com
Diffstat (limited to 'src/include/c.h')
| -rw-r--r-- | src/include/c.h | 45 |
1 files changed, 12 insertions, 33 deletions
diff --git a/src/include/c.h b/src/include/c.h index d2cdc76644c..811d6d0110c 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -923,52 +923,31 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName, * If the "condition" (a compile-time-constant expression) evaluates to false, * throw a compile error using the "errmessage" (a string literal). * - * C11 has _Static_assert(), and most C99 compilers already support that. For - * portability, we wrap it into StaticAssertDecl(). _Static_assert() is a - * "declaration", and so it must be placed where for example a variable + * We require C11 and C++11, so static_assert() is expected to be there. + * StaticAssertDecl() was previously used for portability, but it's now just a + * plain wrapper and doesn't need to be used in new code. static_assert() is + * a "declaration", and so it must be placed where for example a variable * declaration would be valid. As long as we compile with * -Wno-declaration-after-statement, that also means it cannot be placed after * statements in a function. Macros StaticAssertStmt() and StaticAssertExpr() * make it safe to use as a statement or in an expression, respectively. * - * For compilers without _Static_assert(), we fall back on a kluge that - * assumes the compiler will complain about a negative width for a struct + * For compilers without GCC statement expressions, we fall back on a kluge + * that assumes the compiler will complain about a negative width for a struct * bit-field. This will not include a helpful error message, but it beats not * getting an error at all. */ -#ifndef __cplusplus -#ifdef HAVE__STATIC_ASSERT -#define StaticAssertDecl(condition, errmessage) \ - _Static_assert(condition, errmessage) -#define StaticAssertStmt(condition, errmessage) \ - do { _Static_assert(condition, errmessage); } while(0) -#define StaticAssertExpr(condition, errmessage) \ - ((void) ({ StaticAssertStmt(condition, errmessage); true; })) -#else /* !HAVE__STATIC_ASSERT */ -#define StaticAssertDecl(condition, errmessage) \ - extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1]) -#define StaticAssertStmt(condition, errmessage) \ - ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) -#define StaticAssertExpr(condition, errmessage) \ - StaticAssertStmt(condition, errmessage) -#endif /* HAVE__STATIC_ASSERT */ -#else /* C++ */ -#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410 #define StaticAssertDecl(condition, errmessage) \ static_assert(condition, errmessage) #define StaticAssertStmt(condition, errmessage) \ - static_assert(condition, errmessage) + do { static_assert(condition, errmessage); } while(0) +#ifdef HAVE_STATEMENT_EXPRESSIONS #define StaticAssertExpr(condition, errmessage) \ - ({ static_assert(condition, errmessage); }) -#else /* !__cpp_static_assert */ -#define StaticAssertDecl(condition, errmessage) \ - extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1]) -#define StaticAssertStmt(condition, errmessage) \ - do { struct static_assert_struct { int static_assert_failure : (condition) ? 1 : -1; }; } while(0) + ((void) ({ static_assert(condition, errmessage); true; })) +#else #define StaticAssertExpr(condition, errmessage) \ - ((void) ({ StaticAssertStmt(condition, errmessage); })) -#endif /* __cpp_static_assert */ -#endif /* C++ */ + ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) +#endif /* HAVE_STATEMENT_EXPRESSIONS */ /* |
