On Sun, 15 Mar 2026 at 23:13, Tom Lane <[email protected]> wrote:
"Jelte Fennema-Nio" <[email protected]> writes: > If not, then I'm starting to think that actually checking support for > this feature for CLANG is probably easier to understand (and less > fragile) than combining all of these tricks together. Attached is a > patch to do so. +1 for concept, but don't you need to fix meson.build too?
I believe that we don't have fully working bc compilation for meson[1], so I'm not entirely sure how to test out if it actually works. But the attached now does *something* for meson too at least. [1]: https://www.postgresql.org/message-id/flat/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
From 2058a59b52b17ce15752b7f488082929967429c3 Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio <[email protected]> Date: Sun, 15 Mar 2026 22:39:45 +0100 Subject: [PATCH v2] Check CLANG for typeof_unqual Turns out that CLANG on the buildfarm is sometimes significantly older than the CC compiler, and thus supports different features. This explicitly checks typeof_unqual support for CLANG, because that's the feature that sometimes seems to be lacking in practice. --- config/c-compiler.m4 | 45 ++++++++++++++++++---- config/test_typeof_unqual.c | 20 ++++++++++ configure | 65 ++++++++++++++++++++++++++++---- configure.ac | 6 +++ meson.build | 32 +++++++++++++--- src/backend/jit/llvm/meson.build | 2 +- src/include/c.h | 16 ++++++++ src/include/pg_config.h.in | 7 ++++ 8 files changed, 170 insertions(+), 23 deletions(-) create mode 100644 config/test_typeof_unqual.c diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 88333ef301d..6ae57199b1c 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -181,16 +181,12 @@ fi])# PGAC_C_TYPEOF # Check if the C compiler understands typeof_unqual or a variant. Define # HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word. # +# Test with a void pointer, because MSVC doesn't handle that, and we +# need that for copyObject(). AC_DEFUN([PGAC_C_TYPEOF_UNQUAL], [AC_CACHE_CHECK(for typeof_unqual, pgac_cv_c_typeof_unqual, [pgac_cv_c_typeof_unqual=no -# Test the underscore variant first so that there is a higher chance -# that clang used for bitcode also supports it, since we don't test -# that separately. -# -# Test with a void pointer, because MSVC doesn't handle that, and we -# need that for copyObject(). -for pgac_kw in __typeof_unqual__ typeof_unqual; do +for pgac_kw in typeof_unqual __typeof_unqual__; do AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [int x = 0; $pgac_kw(x) y; @@ -248,7 +244,7 @@ AC_DEFUN([PGAC_CXX_TYPEOF_UNQUAL], [AC_CACHE_CHECK(for C++ typeof_unqual, pgac_cv_cxx_typeof_unqual, [pgac_cv_cxx_typeof_unqual=no AC_LANG_PUSH(C++) -for pgac_kw in __typeof_unqual__ typeof_unqual; do +for pgac_kw in typeof_unqual __typeof_unqual__; do AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [int x = 0; $pgac_kw(x) y; @@ -270,6 +266,39 @@ if test "$pgac_cv_cxx_typeof_unqual" != no; then fi])# PGAC_CXX_TYPEOF_UNQUAL +# PGAC_CLANG_TYPEOF_UNQUAL +# ------------------------ +# Check if CLANG (used for LLVM bitcode compilation) understands +# typeof_unqual or a variant. Define HAVE_CLANG_TYPEOF_UNQUAL if so, and +# define 'pg_clang_typeof_unqual' to the actual key word. +# +AC_DEFUN([PGAC_CLANG_TYPEOF_UNQUAL], +[AC_CACHE_CHECK(for CLANG typeof_unqual, pgac_cv_clang_typeof_unqual, +[pgac_cv_clang_typeof_unqual=no +pgac_save_CC=$CC +CC="$CLANG" +for pgac_kw in typeof_unqual __typeof_unqual__; do + _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], +[int x = 0; +$pgac_kw(x) y; +const void *a; +void *b; +y = x; +b = ($pgac_kw(*a) *) a; +return y;])], +[pgac_cv_clang_typeof_unqual=$pgac_kw]) + test "$pgac_cv_clang_typeof_unqual" != no && break +done +CC="$pgac_save_CC"]) +if test "$pgac_cv_clang_typeof_unqual" != no; then + AC_DEFINE(HAVE_CLANG_TYPEOF_UNQUAL, 1, + [Define to 1 if CLANG for bitcode understands `typeof_unqual' or something similar.]) + if test "$pgac_cv_clang_typeof_unqual" != typeof_unqual; then + AC_DEFINE_UNQUOTED(pg_clang_typeof_unqual, $pgac_cv_clang_typeof_unqual, [Define to how CLANG for bitcode spells `typeof_unqual'.]) + fi +fi])# PGAC_CLANG_TYPEOF_UNQUAL + + # PGAC_C_TYPES_COMPATIBLE # ----------------------- diff --git a/config/test_typeof_unqual.c b/config/test_typeof_unqual.c new file mode 100644 index 00000000000..108c8f5468b --- /dev/null +++ b/config/test_typeof_unqual.c @@ -0,0 +1,20 @@ +/* + * Test program for typeof_unqual detection. + * + * Used by meson.build to check whether clang used for LLVM bitcode + * compilation supports typeof_unqual or a variant. Pass -DKW=<keyword> + * to test a specific spelling. + */ +int +main(void) +{ + int x = 0; + + KW(x) y; + const void *a; + void *b; + + y = x; + b = (KW(*a) *) a; + return y; +} diff --git a/configure b/configure index 4c789bd9289..80e29ff3ead 100755 --- a/configure +++ b/configure @@ -7077,6 +7077,9 @@ fi if test "$with_llvm" = yes ; then CLANGXX="$CLANG -xc++" + BITCODE_CFLAGS="$BITCODE_CFLAGS -DPG_COMPILING_BITCODE" + BITCODE_CXXFLAGS="$BITCODE_CXXFLAGS -DPG_COMPILING_BITCODE" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -fno-strict-aliasing, for BITCODE_CFLAGS" >&5 $as_echo_n "checking whether ${CLANG} supports -fno-strict-aliasing, for BITCODE_CFLAGS... " >&6; } if ${pgac_cv_prog_CLANG_cflags__fno_strict_aliasing+:} false; then : @@ -15107,13 +15110,7 @@ if ${pgac_cv_c_typeof_unqual+:} false; then : $as_echo_n "(cached) " >&6 else pgac_cv_c_typeof_unqual=no -# Test the underscore variant first so that there is a higher chance -# that clang used for bitcode also supports it, since we don't test -# that separately. -# -# Test with a void pointer, because MSVC doesn't handle that, and we -# need that for copyObject(). -for pgac_kw in __typeof_unqual__ typeof_unqual; do +for pgac_kw in typeof_unqual __typeof_unqual__; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15164,7 +15161,7 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -for pgac_kw in __typeof_unqual__ typeof_unqual; do +for pgac_kw in typeof_unqual __typeof_unqual__; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15208,6 +15205,58 @@ cat >>confdefs.h <<_ACEOF _ACEOF fi +fi +if test "$with_llvm" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLANG typeof_unqual" >&5 +$as_echo_n "checking for CLANG typeof_unqual... " >&6; } +if ${pgac_cv_clang_typeof_unqual+:} false; then : + $as_echo_n "(cached) " >&6 +else + pgac_cv_clang_typeof_unqual=no +pgac_save_CC=$CC +CC="$CLANG" +for pgac_kw in typeof_unqual __typeof_unqual__; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int x = 0; +$pgac_kw(x) y; +const void *a; +void *b; +y = x; +b = ($pgac_kw(*a) *) a; +return y; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + pgac_cv_clang_typeof_unqual=$pgac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$pgac_cv_clang_typeof_unqual" != no && break +done +CC="$pgac_save_CC" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_clang_typeof_unqual" >&5 +$as_echo "$pgac_cv_clang_typeof_unqual" >&6; } +if test "$pgac_cv_clang_typeof_unqual" != no; then + +$as_echo "#define HAVE_CLANG_TYPEOF_UNQUAL 1" >>confdefs.h + + if test "$pgac_cv_clang_typeof_unqual" != typeof_unqual; then + +cat >>confdefs.h <<_ACEOF +#define pg_clang_typeof_unqual $pgac_cv_clang_typeof_unqual +_ACEOF + + fi +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; } diff --git a/configure.ac b/configure.ac index 9edffe481a6..69ad014238f 100644 --- a/configure.ac +++ b/configure.ac @@ -686,6 +686,9 @@ AC_SUBST(CXXFLAGS_SL_MODULE) if test "$with_llvm" = yes ; then CLANGXX="$CLANG -xc++" + BITCODE_CFLAGS="$BITCODE_CFLAGS -DPG_COMPILING_BITCODE" + BITCODE_CXXFLAGS="$BITCODE_CXXFLAGS -DPG_COMPILING_BITCODE" + PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-fno-strict-aliasing]) PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANGXX, BITCODE_CXXFLAGS, [-fno-strict-aliasing]) PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-fwrapv]) @@ -1734,6 +1737,9 @@ PGAC_C_TYPEOF PGAC_CXX_TYPEOF PGAC_C_TYPEOF_UNQUAL PGAC_CXX_TYPEOF_UNQUAL +AS_IF([test "$with_llvm" = yes], [ + PGAC_CLANG_TYPEOF_UNQUAL +]) PGAC_C_TYPES_COMPATIBLE PGAC_C_BUILTIN_CONSTANT_P PGAC_C_BUILTIN_OP_OVERFLOW diff --git a/meson.build b/meson.build index f7a87edcc94..f17970f1ae2 100644 --- a/meson.build +++ b/meson.build @@ -2969,13 +2969,9 @@ endif # Check if the C compiler understands typeof_unqual or a variant. Define # HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word. # -# Test the underscore variant first so that there is a higher chance -# that clang used for bitcode also supports it, since we don't test -# that separately. -# # Test with a void pointer, because MSVC doesn't handle that, and we # need that for copyObject(). -foreach kw : ['__typeof_unqual__', 'typeof_unqual'] +foreach kw : ['typeof_unqual', '__typeof_unqual__'] if cc.compiles(''' int main(void) { @@ -3002,7 +2998,7 @@ endforeach # Check if the C++ compiler understands typeof_unqual or a variant. if have_cxx - foreach kw : ['__typeof_unqual__', 'typeof_unqual'] + foreach kw : ['typeof_unqual', '__typeof_unqual__'] if cxx.compiles(''' int main(void) { @@ -3028,6 +3024,30 @@ int main(void) endforeach endif +# Check if CLANG (used for LLVM bitcode compilation) understands +# typeof_unqual or a variant. We use run_command with a test file +# because clang is a program, not a meson compiler object, so +# cc.compiles() cannot be used. +if llvm.found() + clang_typeof_unqual_found = false + foreach kw : ['typeof_unqual', '__typeof_unqual__'] + if not clang_typeof_unqual_found + r = run_command(clang, '-fsyntax-only', '-DKW=' + kw, + files('config/test_typeof_unqual.c'), check: false) + if r.returncode() == 0 + message('CLANG supports ' + kw) + clang_typeof_unqual_found = true + cdata.set('HAVE_CLANG_TYPEOF_UNQUAL', 1) + if kw != 'typeof_unqual' + cdata.set('pg_clang_typeof_unqual', kw) + endif + else + message('CLANG does not support ' + kw) + endif + endif + endforeach +endif + # MSVC doesn't cope well with defining restrict to __restrict, the # spelling it understands, because it conflicts with diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build index 7df8453ad6f..7270143771e 100644 --- a/src/backend/jit/llvm/meson.build +++ b/src/backend/jit/llvm/meson.build @@ -60,7 +60,7 @@ endif # XXX: Need to determine proper version of the function cflags for clang -bitcode_cflags = ['-fno-strict-aliasing', '-fwrapv'] +bitcode_cflags = ['-DPG_COMPILING_BITCODE', '-fno-strict-aliasing', '-fwrapv'] bitcode_cflags += get_option('c_args') bitcode_cflags += cppflags diff --git a/src/include/c.h b/src/include/c.h index 29fef2f54e1..e0dfb897529 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -466,6 +466,22 @@ extern "C++" #endif #endif /* __cplusplus */ +/* + * Override typeof_unqual for LLVM bitcode compilation when CLANG doesn't + * support the same keyword as CC. Analogous to the C++ override above. + * PG_COMPILING_BITCODE is defined in BITCODE_CFLAGS. + */ +#if defined(PG_COMPILING_BITCODE) && !defined(__cplusplus) +#undef HAVE_TYPEOF_UNQUAL +#undef typeof_unqual +#ifdef pg_clang_typeof_unqual +#define typeof_unqual(x) pg_clang_typeof_unqual(x) +#define HAVE_TYPEOF_UNQUAL 1 +#elif defined(HAVE_CLANG_TYPEOF_UNQUAL) +#define HAVE_TYPEOF_UNQUAL 1 +#endif +#endif /* PG_COMPILING_BITCODE && !__cplusplus */ + /* * CppAsString * Convert the argument to a string, using the C preprocessor. diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 79379a4d125..b1c20ce754a 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,6 +54,10 @@ /* Define to 1 if you have the `backtrace_symbols' function. */ #undef HAVE_BACKTRACE_SYMBOLS +/* Define to 1 if CLANG for bitcode understands `typeof_unqual' or something + similar. */ +#undef HAVE_CLANG_TYPEOF_UNQUAL + /* Define to 1 if your compiler handles computed gotos. */ #undef HAVE_COMPUTED_GOTO @@ -789,6 +793,9 @@ /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES +/* Define to how CLANG for bitcode spells `typeof_unqual'. */ +#undef pg_clang_typeof_unqual + /* Define to how the C++ compiler spells `typeof'. */ #undef pg_cxx_typeof base-commit: a793677e57bc27c674cb94b230164b2c28f4cbae -- 2.53.0
