From 26442d786cc65211f0176e803dfa269e9e93c8bd Mon Sep 17 00:00:00 2001
From: David Rowley <dgrowley@gmail.com>
Date: Thu, 17 Jul 2025 15:49:03 +1200
Subject: [PATCH v2] Detect elog(ERROR) can't return in MSVC when using C11

---
 meson.build                            | 24 ++++++++++++++++++++++++
 src/backend/backup/basebackup_target.c |  4 ++--
 src/include/c.h                        | 17 +++++++++++++++++
 src/include/utils/elog.h               |  6 +++---
 4 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/meson.build b/meson.build
index 5365aaf95e6..e23a99c7b1d 100644
--- a/meson.build
+++ b/meson.build
@@ -1704,6 +1704,18 @@ endif
 # Compiler tests
 ###############################################################
 
+# Test to see if the compiler supports C11
+c11_test = '''
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
+#error "C11 not supported"
+#endif
+
+int main(int argc, char **argv)
+{
+  return 0;
+}
+'''
+
 # Do we need -std=c99 to compile C99 code? We don't want to add -std=c99
 # unnecessarily, because we optionally rely on newer features.
 c99_test = '''
@@ -1737,6 +1749,18 @@ int main(int argc, char **argv)
 }
 '''
 
+# The current minimum version of MSVC we currently support supports at least
+# C11, so lets try to compile with C11.  Check if we need to actually pass the
+# /std:c11 flag for that to work.  If this test ends up adding the C11 flag,
+# then the C99 test below should always pass and never add the C99 flag.
+if cc.get_id() == 'msvc' and not cc.compiles(c11_test, name: 'c11', args: test_c_args)
+  if cc.compiles(c11_test, name: 'c11 with /std:c11',
+        args: test_c_args + ['/std:c11'])
+    test_c_args += '/std:c11'
+    cflags += '/std:c11'
+  endif
+endif
+
 if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
   if cc.compiles(c99_test, name: 'c99 with -std=c99',
         args: test_c_args + ['-std=c99'])
diff --git a/src/backend/backup/basebackup_target.c b/src/backend/backup/basebackup_target.c
index 84b1309d3bd..01705368950 100644
--- a/src/backend/backup/basebackup_target.c
+++ b/src/backend/backup/basebackup_target.c
@@ -145,8 +145,8 @@ BaseBackupGetTargetHandle(char *target, char *target_detail)
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("unrecognized target: \"%s\"", target)));
 
-	/* keep compiler quiet */
-	return NULL;
+	/* comment out for testing. Not for commit. */
+	/* return NULL; */
 }
 
 /*
diff --git a/src/include/c.h b/src/include/c.h
index 6d4495bdd9f..48a8cedec2d 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -332,6 +332,23 @@
 #define pg_unreachable() abort()
 #endif
 
+/*
+ * Define a compiler-independent macro for determining if an expression is a
+ * compile-time const.  With MSVC using C11 and above, we can use a trick with
+ * _Generic to make this work.  We don't define this macro to return 0 when
+ * unsupported due to the risk of users of the macro misbehaving if we return
+ * 0 when the expression is a built-in constant.  Callers may check if this
+ * macro is defined by checking if HAVE_PG_BUILTIN_CONSTANT is defined.
+ */
+#if defined(HAVE__BUILTIN_CONSTANT_P)
+#define pg_builtin_constant(x) __builtin_constant_p(x)
+#define HAVE_PG_BUILTIN_CONSTANT
+#elif defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define pg_builtin_constant(x) \
+	_Generic((1 ? ((void *) ((x) * (uintptr_t) 0)) : &(int) {1}), int *: 1, void *: 0)
+#define HAVE_PG_BUILTIN_CONSTANT
+#endif
+
 /*
  * pg_assume(expr) states that we assume `expr` to evaluate to true. In assert
  * enabled builds pg_assume() is turned into an assertion, in optimized builds
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 675f4f5f469..7b575b59ed3 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -137,15 +137,15 @@ struct Node;
  * prevents gcc from making the unreachability deduction at optlevel -O0.
  *----------
  */
-#ifdef HAVE__BUILTIN_CONSTANT_P
+#ifdef HAVE_PG_BUILTIN_CONSTANT
 #define ereport_domain(elevel, domain, ...)	\
 	do { \
 		pg_prevent_errno_in_scope(); \
-		if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \
+		if (pg_builtin_constant(elevel) && (elevel) >= ERROR ? \
 			errstart_cold(elevel, domain) : \
 			errstart(elevel, domain)) \
 			__VA_ARGS__, errfinish(__FILE__, __LINE__, __func__); \
-		if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
+		if (pg_builtin_constant(elevel) && (elevel) >= ERROR) \
 			pg_unreachable(); \
 	} while(0)
 #else							/* !HAVE__BUILTIN_CONSTANT_P */
-- 
2.40.1.windows.1

