From 5fbc7dc89d309f7094a81e77703ec0b5339be7f7 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Sat, 3 Jan 2026 00:43:59 +0100
Subject: [PATCH v5 3/4] Revert "Replace pg_restrict by standard restrict"

This reverts commit f0f2c0c1aef95757c4e7f144d5577e2b0d814279.

It turns out that this completely broke compiling C++ extensions on
MSVC. The restrict replacement with __restrict would break usages of
__decltype(restrict) in standard library headers, resulting in errors
like this:

C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt\corecrt_malloc.h(58): error C2485: '__restrict': unrecognized extended attribute
---
 configure                                 | 18 ++++++++++++++----
 configure.ac                              | 16 ++++++++++++----
 meson.build                               | 13 +++++++------
 src/bin/pg_verifybackup/pg_verifybackup.c |  4 ++--
 src/bin/pg_verifybackup/pg_verifybackup.h |  4 ++--
 src/common/logging.c                      |  4 ++--
 src/common/string.c                       |  2 +-
 src/include/c.h                           |  6 ------
 src/include/common/logging.h              |  4 ++--
 src/include/common/string.h               |  2 +-
 src/include/libpq/pqformat.h              | 12 ++++++------
 src/include/pg_config.h.in                |  4 ++++
 12 files changed, 53 insertions(+), 36 deletions(-)

diff --git a/configure b/configure
index 045c913865d..575f4f05245 100755
--- a/configure
+++ b/configure
@@ -15131,10 +15131,10 @@ _ACEOF
 fi
 
 
-# Even though restrict is in C99 and should be supported by all
-# supported compilers, this test is useful because it will prefer a
-# spelling that also works in C++ (often __restrict).  (restrict is
-# not part of the C++ standard.)
+# MSVC doesn't cope well with defining restrict to __restrict, the
+# spelling it understands, because it conflicts with
+# __declspec(restrict). Therefore we define pg_restrict to the
+# appropriate definition, which presumably won't conflict.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
 $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
 if ${ac_cv_c_restrict+:} false; then :
@@ -15181,6 +15181,16 @@ _ACEOF
  ;;
  esac
 
+if test "$ac_cv_c_restrict" = "no"; then
+  pg_restrict=""
+else
+  pg_restrict="$ac_cv_c_restrict"
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define pg_restrict $pg_restrict
+_ACEOF
+
 
 ac_fn_c_check_type "$LINENO" "struct option" "ac_cv_type_struct_option" "#ifdef HAVE_GETOPT_H
 #include <getopt.h>
diff --git a/configure.ac b/configure.ac
index 145197e6bd6..c77c2639ec1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1687,11 +1687,19 @@ PGAC_UNION_SEMUN
 AC_CHECK_TYPES(socklen_t, [], [], [#include <sys/socket.h>])
 PGAC_STRUCT_SOCKADDR_SA_LEN
 
-# Even though restrict is in C99 and should be supported by all
-# supported compilers, this test is useful because it will prefer a
-# spelling that also works in C++ (often __restrict).  (restrict is
-# not part of the C++ standard.)
+# MSVC doesn't cope well with defining restrict to __restrict, the
+# spelling it understands, because it conflicts with
+# __declspec(restrict). Therefore we define pg_restrict to the
+# appropriate definition, which presumably won't conflict.
 AC_C_RESTRICT
+if test "$ac_cv_c_restrict" = "no"; then
+  pg_restrict=""
+else
+  pg_restrict="$ac_cv_c_restrict"
+fi
+AC_DEFINE_UNQUOTED([pg_restrict], [$pg_restrict],
+[Define to keyword to use for C99 restrict support, or to nothing if not
+supported])
 
 AC_CHECK_TYPES([struct option], [], [],
 [#ifdef HAVE_GETOPT_H
diff --git a/meson.build b/meson.build
index 555c94796c6..55df1dd3797 100644
--- a/meson.build
+++ b/meson.build
@@ -2833,12 +2833,13 @@ int main(void)
 endforeach
 
 
-# Even though restrict is in C99 and should be supported by all
-# supported compilers, this indirection is useful because __restrict
-# also works in C++ in all supported compilers.  (If not, then we
-# might have to write a real test.)  (restrict is not part of the C++
-# standard.)
-cdata.set('restrict', '__restrict')
+# MSVC doesn't cope well with defining restrict to __restrict, the spelling it
+# understands, because it conflicts with __declspec(restrict). Therefore we
+# define pg_restrict to the appropriate definition, which presumably won't
+# conflict.
+#
+# We assume C99 support, so we don't need to make this conditional.
+cdata.set('pg_restrict', '__restrict')
 
 
 # Most libraries are included only if they demonstrably provide a function we
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index 456e0375e13..f9f2d457f2f 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -1228,7 +1228,7 @@ parse_required_wal(verifier_context *context, char *pg_waldump_path,
  * context says we should.
  */
 void
-report_backup_error(verifier_context *context, const char *restrict fmt,...)
+report_backup_error(verifier_context *context, const char *pg_restrict fmt,...)
 {
 	va_list		ap;
 
@@ -1245,7 +1245,7 @@ report_backup_error(verifier_context *context, const char *restrict fmt,...)
  * Report a fatal error and exit
  */
 void
-report_fatal_error(const char *restrict fmt,...)
+report_fatal_error(const char *pg_restrict fmt,...)
 {
 	va_list		ap;
 
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.h b/src/bin/pg_verifybackup/pg_verifybackup.h
index 1cd76a8826b..a99d9bfd581 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.h
+++ b/src/bin/pg_verifybackup/pg_verifybackup.h
@@ -96,9 +96,9 @@ typedef struct verifier_context
 } verifier_context;
 
 extern void report_backup_error(verifier_context *context,
-								const char *restrict fmt,...)
+								const char *pg_restrict fmt,...)
 			pg_attribute_printf(2, 3);
-pg_noreturn extern void report_fatal_error(const char *restrict fmt,...)
+pg_noreturn extern void report_fatal_error(const char *pg_restrict fmt,...)
 			pg_attribute_printf(1, 2);
 extern bool should_ignore_relpath(verifier_context *context,
 								  const char *relpath);
diff --git a/src/common/logging.c b/src/common/logging.c
index 214a87f2189..5206949e5d8 100644
--- a/src/common/logging.c
+++ b/src/common/logging.c
@@ -206,7 +206,7 @@ pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno)
 
 void
 pg_log_generic(enum pg_log_level level, enum pg_log_part part,
-			   const char *restrict fmt,...)
+			   const char *pg_restrict fmt,...)
 {
 	va_list		ap;
 
@@ -217,7 +217,7 @@ pg_log_generic(enum pg_log_level level, enum pg_log_part part,
 
 void
 pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
-				 const char *restrict fmt, va_list ap)
+				 const char *pg_restrict fmt, va_list ap)
 {
 	int			save_errno = errno;
 	const char *filename = NULL;
diff --git a/src/common/string.c b/src/common/string.c
index fff14d3facf..41c74a1502d 100644
--- a/src/common/string.c
+++ b/src/common/string.c
@@ -47,7 +47,7 @@ pg_str_endswith(const char *str, const char *end)
  * strtoint --- just like strtol, but returns int not long
  */
 int
-strtoint(const char *restrict str, char **restrict endptr, int base)
+strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
 {
 	long		val;
 
diff --git a/src/include/c.h b/src/include/c.h
index 39105671e6c..65173b9d9fd 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -108,12 +108,6 @@
 #define inline
 #endif
 
-/*
- * Previously used PostgreSQL-specific spelling, for backward compatibility
- * for extensions.
- */
-#define pg_restrict restrict
-
 /*
  * Attribute macros
  *
diff --git a/src/include/common/logging.h b/src/include/common/logging.h
index b5caec0bff1..bccba4ac07b 100644
--- a/src/include/common/logging.h
+++ b/src/include/common/logging.h
@@ -93,10 +93,10 @@ void		pg_logging_set_pre_callback(void (*cb) (void));
 void		pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno));
 
 void		pg_log_generic(enum pg_log_level level, enum pg_log_part part,
-						   const char *restrict fmt,...)
+						   const char *pg_restrict fmt,...)
 			pg_attribute_printf(3, 4);
 void		pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
-							 const char *restrict fmt, va_list ap)
+							 const char *pg_restrict fmt, va_list ap)
 			pg_attribute_printf(3, 0);
 
 /*
diff --git a/src/include/common/string.h b/src/include/common/string.h
index 5e1bd61c710..2a7c31ea74e 100644
--- a/src/include/common/string.h
+++ b/src/include/common/string.h
@@ -25,7 +25,7 @@ typedef struct PromptInterruptContext
 
 /* functions in src/common/string.c */
 extern bool pg_str_endswith(const char *str, const char *end);
-extern int	strtoint(const char *restrict str, char **restrict endptr,
+extern int	strtoint(const char *pg_restrict str, char **pg_restrict endptr,
 					 int base);
 extern char *pg_clean_ascii(const char *str, int alloc_flags);
 extern int	pg_strip_crlf(char *str);
diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h
index 911d9397f5e..bc4ab1381a9 100644
--- a/src/include/libpq/pqformat.h
+++ b/src/include/libpq/pqformat.h
@@ -34,7 +34,7 @@ extern void pq_sendfloat8(StringInfo buf, float8 f);
  * Append a [u]int8 to a StringInfo buffer, which already has enough space
  * preallocated.
  *
- * The use of restrict allows the compiler to optimize the code based on
+ * The use of pg_restrict allows the compiler to optimize the code based on
  * the assumption that buf, buf->len, buf->data and *buf->data don't
  * overlap. Without the annotation buf->len etc cannot be kept in a register
  * over subsequent pq_writeintN calls.
@@ -43,7 +43,7 @@ extern void pq_sendfloat8(StringInfo buf, float8 f);
  * overly picky and demanding a * before a restrict.
  */
 static inline void
-pq_writeint8(StringInfoData *restrict buf, uint8 i)
+pq_writeint8(StringInfoData *pg_restrict buf, uint8 i)
 {
 	uint8		ni = i;
 
@@ -57,7 +57,7 @@ pq_writeint8(StringInfoData *restrict buf, uint8 i)
  * preallocated.
  */
 static inline void
-pq_writeint16(StringInfoData *restrict buf, uint16 i)
+pq_writeint16(StringInfoData *pg_restrict buf, uint16 i)
 {
 	uint16		ni = pg_hton16(i);
 
@@ -71,7 +71,7 @@ pq_writeint16(StringInfoData *restrict buf, uint16 i)
  * preallocated.
  */
 static inline void
-pq_writeint32(StringInfoData *restrict buf, uint32 i)
+pq_writeint32(StringInfoData *pg_restrict buf, uint32 i)
 {
 	uint32		ni = pg_hton32(i);
 
@@ -85,7 +85,7 @@ pq_writeint32(StringInfoData *restrict buf, uint32 i)
  * preallocated.
  */
 static inline void
-pq_writeint64(StringInfoData *restrict buf, uint64 i)
+pq_writeint64(StringInfoData *pg_restrict buf, uint64 i)
 {
 	uint64		ni = pg_hton64(i);
 
@@ -105,7 +105,7 @@ pq_writeint64(StringInfoData *restrict buf, uint64 i)
  * sent to the frontend.
  */
 static inline void
-pq_writestring(StringInfoData *restrict buf, const char *restrict str)
+pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str)
 {
 	int			slen = strlen(str);
 	char	   *p;
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 10fa85e78c2..339268dc8ef 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -786,6 +786,10 @@
 #undef inline
 #endif
 
+/* Define to keyword to use for C99 restrict support, or to nothing if not
+   supported */
+#undef pg_restrict
+
 /* Define to the equivalent of the C99 'restrict' keyword, or to
    nothing if this is not supported.  Do not define if restrict is
    supported directly.  */
-- 
2.52.0

