On Fri, 13 Mar 2026 at 11:43, Peter Eisentraut <[email protected]> wrote:
There is a failure on buildfarm member taipan because it uses an unusual
combination of gcc and clang (the gcc is much newer than clang). The
only sensible workaround I could think of is a hardcoded override based
on the clang version, as in the attached patch.
If we can then start prefering typeof_unqual over __typeof_unqual__ in
the configure check for CC, then I think I like this as a workaround.
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.
This only does it for CLANG, not for CLANG compiling C++ files.
Theoretically that could be necessary, but I couldn't find a C++
compiler that supports any spelling of typeof_unqual. So I'm not even
sure we need the current CXX check for typeof_unqual, I think we could
remove that too and always use the fallback.
And alternative is that
we decide that we don't want to support this combination, meaning that
we would effectively require that clang is approximately as-old-or-newer
than gcc.
Given that Tom seems to have reproduced this on Fedora 40, it sounds
like we should fix it.
From 377b3b68c073c1b62bc0e5c357eed50624022cb5 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Sun, 15 Mar 2026 22:39:45 +0100
Subject: [PATCH v1] 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 +++++++++++++++++++++-----
configure | 65 +++++++++++++++++++++++++++++++++-----
configure.ac | 6 ++++
src/include/c.h | 16 ++++++++++
src/include/pg_config.h.in | 7 ++++
5 files changed, 123 insertions(+), 16 deletions(-)
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/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/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