diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 3eab0da9cb6..f05b744667c 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -267,25 +267,6 @@ fi])# PGAC_CXX_TYPEOF_UNQUAL -# PGAC_C_TYPES_COMPATIBLE -# ----------------------- -# Check if the C compiler understands __builtin_types_compatible_p, -# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so. -# -# We check usage with __typeof__, though it's unlikely any compiler would -# have the former and not the latter. -AC_DEFUN([PGAC_C_TYPES_COMPATIBLE], -[AC_CACHE_CHECK(for __builtin_types_compatible_p, pgac_cv__types_compatible, -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], -[[ int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)]; ]])], -[pgac_cv__types_compatible=yes], -[pgac_cv__types_compatible=no])]) -if test x"$pgac_cv__types_compatible" = xyes ; then -AC_DEFINE(HAVE__BUILTIN_TYPES_COMPATIBLE_P, 1, - [Define to 1 if your compiler understands __builtin_types_compatible_p.]) -fi])# PGAC_C_TYPES_COMPATIBLE - - # PGAC_C_BUILTIN_CONSTANT_P # ------------------------- # Check if the C compiler understands __builtin_constant_p(), diff --git a/configure b/configure index 35b0b72f0a7..5fc85a24519 100755 --- a/configure +++ b/configure @@ -15181,36 +15181,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5 -$as_echo_n "checking for __builtin_types_compatible_p... " >&6; } -if ${pgac_cv__types_compatible+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)]; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv__types_compatible=yes -else - pgac_cv__types_compatible=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__types_compatible" >&5 -$as_echo "$pgac_cv__types_compatible" >&6; } -if test x"$pgac_cv__types_compatible" = xyes ; then - -$as_echo "#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1" >>confdefs.h - fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_constant_p" >&5 $as_echo_n "checking for __builtin_constant_p... " >&6; } diff --git a/configure.ac b/configure.ac index 0e624fe36b9..dc4532126cb 100644 --- a/configure.ac +++ b/configure.ac @@ -1727,7 +1727,6 @@ PGAC_C_TYPEOF PGAC_CXX_TYPEOF PGAC_C_TYPEOF_UNQUAL PGAC_CXX_TYPEOF_UNQUAL -PGAC_C_TYPES_COMPATIBLE PGAC_C_BUILTIN_CONSTANT_P PGAC_C_BUILTIN_OP_OVERFLOW PGAC_C_BUILTIN_UNREACHABLE diff --git a/meson.build b/meson.build index d88a7a70308..8dea31e62df 100644 --- a/meson.build +++ b/meson.build @@ -2062,21 +2062,6 @@ foreach builtin : builtins endforeach -# Check if the C compiler understands __builtin_types_compatible_p, -# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so. -# -# We check usage with __typeof__, though it's unlikely any compiler would -# have the former and not the latter. -if cc.compiles(''' - static int x; - static int y[__builtin_types_compatible_p(__typeof__(x), int)]; - ''', - name: '__builtin_types_compatible_p', - args: test_c_args) - cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1) -endif - - # Check if the C compiler understands __builtin_$op_overflow(), # and define HAVE__BUILTIN_OP_OVERFLOW if so. # diff --git a/src/include/c.h b/src/include/c.h index 0e8053d1fe3..8d1aa4b639d 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -1108,29 +1108,24 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName, /* * Compile-time checks that a variable (or expression) has the specified type. * + * The type must not have top-level qualifiers (const, volatile) and must not + * be an array (use pointer instead). (This wouldn't work because _Generic + * does lvalue conversion on the controlling expression, which drops + * qualifiers and converts arrays to pointers.) Qualifiers inside pointers + * are allowed. + * * StaticAssertVariableIsOfType() can be used as a declaration. * StaticAssertVariableIsOfTypeMacro() is intended for use in macros, eg * #define foo(x) (StaticAssertVariableIsOfTypeMacro(x, int), bar(x)) * - * If we don't have __builtin_types_compatible_p, we can still assert that - * the types have the same size. This is far from ideal (especially on 32-bit - * platforms) but it provides at least some coverage. + * Note that these do not work in C++. */ -#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P #define StaticAssertVariableIsOfType(varname, typename) \ - StaticAssertDecl(__builtin_types_compatible_p(typeof(varname), typename), \ + StaticAssertDecl(_Generic((varname), typename: 1, default: 0), \ CppAsString(varname) " does not have type " CppAsString(typename)) #define StaticAssertVariableIsOfTypeMacro(varname, typename) \ - (StaticAssertExpr(__builtin_types_compatible_p(typeof(varname), typename), \ + (StaticAssertExpr(_Generic((varname), typename: 1, default: 0), \ CppAsString(varname) " does not have type " CppAsString(typename))) -#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */ -#define StaticAssertVariableIsOfType(varname, typename) \ - StaticAssertDecl(sizeof(varname) == sizeof(typename), \ - CppAsString(varname) " does not have type " CppAsString(typename)) -#define StaticAssertVariableIsOfTypeMacro(varname, typename) \ - (StaticAssertExpr(sizeof(varname) == sizeof(typename), \ - CppAsString(varname) " does not have type " CppAsString(typename))) -#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ /* ---------------------------------------------------------------- @@ -1367,8 +1362,13 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock; /* * Macro that allows to cast constness and volatile away from an expression, but doesn't - * allow changing the underlying type. Enforcement of the latter - * currently only works for gcc like compilers. + * allow changing the underlying type. + * + * This is only meant to work for qualifiers behind at least one level of + * pointer. (In the C implementation, the StaticAssertVariableIsOfTypeMacro + * will drop top-level qualifiers, so with a non-pointer, the static assertion + * will fail. In the C++ implementation, const_cast will error for + * non-pointers.) * * Please note IT IS NOT SAFE to cast constness away if the result will ever * be modified (it would be undefined behaviour). Doing so anyway can cause diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 4f8113c144b..661c4a9b168 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -544,9 +544,6 @@ /* Define to 1 if your compiler understands __builtin_$op_overflow. */ #undef HAVE__BUILTIN_OP_OVERFLOW -/* Define to 1 if your compiler understands __builtin_types_compatible_p. */ -#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P - /* Define to 1 if your compiler understands __builtin_unreachable. */ #undef HAVE__BUILTIN_UNREACHABLE