Hi,

On 2017-10-12 11:03:34 -0700, Andres Freund wrote:
> On 2017-10-12 13:55:07 -0400, Tom Lane wrote:
> > Or, if you insist on having it, we're going to have to go the pg_restrict
> > route.  I don't see why that means duplicating any configure logic: on
> > non-Windows we can use the autoconf probe and then write
> > "#define pg_restrict restrict".
> 
> Yea, that should work. I'll try to come up with a patch.

We can't do so unconditionally in c.h or such, because that'd again
cause conflicts with __declspec(restrict) on MSVC versions that don't
support restrict, because it'd require restrict to be defined empty.

But it's easy to do so in configure, and then have a separate definition
in pg_config.h.win32. Done so in the attached commit. It's slightly ugly
to have two definitions of restrict in pg_config.h.in, but whatever.

Greetings,

Andres Freund
>From 0ddc96424119682cf3b68c6d8d95ea894a60817a Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Thu, 12 Oct 2017 15:25:38 -0700
Subject: [PATCH] Use C99 restrict via pg_restrict, rather than restrict
 directly.

Unfortunately using 'restrict' plainly causes problems with MSVC,
which supports restrict only as '__restrict'. Defining 'restrict' to
'__restrict' unfortunately causes a conflict with MSVC's usage of
__declspec(restrict) in headers.

Therefore define pg_restrict to the appropriate keyword instead, and
replace existing usages.

This replaces the temporary workaround introduced in 36b4b91ba078.

Author: Andres Freund
Discussion: https://postgr.es/m/2656.1507830...@sss.pgh.pa.us
---
 configure                     | 107 ++++++++++++++++++++++++------------------
 configure.in                  |  15 +++++-
 src/include/libpq/pqformat.h  |  24 +++++-----
 src/include/pg_config.h.in    |   4 ++
 src/include/pg_config.h.win32 |  22 ++++-----
 5 files changed, 101 insertions(+), 71 deletions(-)

diff --git a/configure b/configure
index 910f0fc3736..cdcb3ceb0c8 100755
--- a/configure
+++ b/configure
@@ -11545,52 +11545,6 @@ _ACEOF
     ;;
 esac
 
-{ $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 :
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_c_restrict=no
-   # The order here caters to the fact that C++ does not require restrict.
-   for ac_kw in __restrict __restrict__ _Restrict restrict; do
-     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef int * int_ptr;
-	int foo (int_ptr $ac_kw ip) {
-	return ip[0];
-       }
-int
-main ()
-{
-int s[1];
-	int * $ac_kw t = s;
-	t[0] = 0;
-	return foo(t)
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_c_restrict=$ac_kw
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-     test "$ac_cv_c_restrict" != no && break
-   done
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
-$as_echo "$ac_cv_c_restrict" >&6; }
-
- case $ac_cv_c_restrict in
-   restrict) ;;
-   no) $as_echo "#define restrict /**/" >>confdefs.h
- ;;
-   *)  cat >>confdefs.h <<_ACEOF
-#define restrict $ac_cv_c_restrict
-_ACEOF
- ;;
- esac
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for printf format archetype" >&5
 $as_echo_n "checking for printf format archetype... " >&6; }
 if ${pgac_cv_printf_archetype+:} false; then :
@@ -12508,6 +12462,67 @@ $as_echo "#define LOCALE_T_IN_XLOCALE 1" >>confdefs.h
 
 fi
 
+# 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 :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_restrict=no
+   # The order here caters to the fact that C++ does not require restrict.
+   for ac_kw in __restrict __restrict__ _Restrict restrict; do
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+typedef int * int_ptr;
+	int foo (int_ptr $ac_kw ip) {
+	return ip[0];
+       }
+int
+main ()
+{
+int s[1];
+	int * $ac_kw t = s;
+	t[0] = 0;
+	return foo(t)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_restrict=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     test "$ac_cv_c_restrict" != no && break
+   done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
+$as_echo "$ac_cv_c_restrict" >&6; }
+
+ case $ac_cv_c_restrict in
+   restrict) ;;
+   no) $as_echo "#define restrict /**/" >>confdefs.h
+ ;;
+   *)  cat >>confdefs.h <<_ACEOF
+#define restrict $ac_cv_c_restrict
+_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 cmsgcred" "ac_cv_type_struct_cmsgcred" "#include <sys/socket.h>
 #include <sys/param.h>
 #ifdef HAVE_SYS_UCRED_H
diff --git a/configure.in b/configure.in
index ab990d69f4c..32bb7bf940d 100644
--- a/configure.in
+++ b/configure.in
@@ -1299,7 +1299,6 @@ fi
 m4_defun([AC_PROG_CC_STDC], []) dnl We don't want that.
 AC_C_BIGENDIAN
 AC_C_INLINE
-AC_C_RESTRICT
 PGAC_PRINTF_ARCHETYPE
 AC_C_FLEXIBLE_ARRAY_MEMBER
 PGAC_C_SIGNED
@@ -1326,6 +1325,20 @@ AC_TYPE_LONG_LONG_INT
 
 PGAC_TYPE_LOCALE_T
 
+# 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 cmsgcred], [], [],
 [#include <sys/socket.h>
 #include <sys/param.h>
diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h
index 2329669b085..35cdee7b76f 100644
--- a/src/include/libpq/pqformat.h
+++ b/src/include/libpq/pqformat.h
@@ -38,8 +38,8 @@ extern void pq_sendfloat8(StringInfo buf, float8 f);
  * Append a 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
- * assumption that buf, buf->len, buf->data and *buf->data don't
+ * 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_writeint* calls.
  *
@@ -47,12 +47,12 @@ extern void pq_sendfloat8(StringInfo buf, float8 f);
  * overly picky and demanding a * before a restrict.
  */
 static inline void
-pq_writeint8(StringInfoData * restrict buf, int8 i)
+pq_writeint8(StringInfoData *pg_restrict buf, int8 i)
 {
 	int8		ni = i;
 
 	Assert(buf->len + sizeof(i) <= buf->maxlen);
-	memcpy((char *restrict) (buf->data + buf->len), &ni, sizeof(ni));
+	memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(ni));
 	buf->len += sizeof(i);
 }
 
@@ -61,12 +61,12 @@ pq_writeint8(StringInfoData * restrict buf, int8 i)
  * preallocated.
  */
 static inline void
-pq_writeint16(StringInfoData * restrict buf, int16 i)
+pq_writeint16(StringInfoData *pg_restrict buf, int16 i)
 {
 	int16		ni = pg_hton16(i);
 
 	Assert(buf->len + sizeof(ni) <= buf->maxlen);
-	memcpy((char *restrict) (buf->data + buf->len), &ni, sizeof(i));
+	memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(i));
 	buf->len += sizeof(i);
 }
 
@@ -75,12 +75,12 @@ pq_writeint16(StringInfoData * restrict buf, int16 i)
  * preallocated.
  */
 static inline void
-pq_writeint32(StringInfoData * restrict buf, int32 i)
+pq_writeint32(StringInfoData *pg_restrict buf, int32 i)
 {
 	int32		ni = pg_hton32(i);
 
 	Assert(buf->len + sizeof(i) <= buf->maxlen);
-	memcpy((char *restrict) (buf->data + buf->len), &ni, sizeof(i));
+	memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(i));
 	buf->len += sizeof(i);
 }
 
@@ -89,12 +89,12 @@ pq_writeint32(StringInfoData * restrict buf, int32 i)
  * preallocated.
  */
 static inline void
-pq_writeint64(StringInfoData * restrict buf, int64 i)
+pq_writeint64(StringInfoData *pg_restrict buf, int64 i)
 {
 	int64		ni = pg_hton64(i);
 
 	Assert(buf->len + sizeof(i) <= buf->maxlen);
-	memcpy((char *restrict) (buf->data + buf->len), &ni, sizeof(i));
+	memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(i));
 	buf->len += sizeof(i);
 }
 
@@ -109,7 +109,7 @@ pq_writeint64(StringInfoData * restrict buf, int64 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;
@@ -120,7 +120,7 @@ pq_writestring(StringInfoData * restrict buf, const char *restrict str)
 
 	Assert(buf->len + slen + 1 <= buf->maxlen);
 
-	memcpy(((char *restrict) buf->data + buf->len), p, slen + 1);
+	memcpy(((char *pg_restrict) buf->data + buf->len), p, slen + 1);
 	buf->len += slen + 1;
 
 	if (p != str)
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 80ee37dd622..cfdcc5ac62f 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -923,6 +923,10 @@
    if such a type exists, and if the system does not define it. */
 #undef intptr_t
 
+/* 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.  */
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index 81604de7f92..ab9b941e89d 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -681,21 +681,19 @@
 #define inline __inline
 #endif
 
+/* Define to keyword to use for C99 restrict support, or to nothing if this is
+   not supported */
+/* Works for C and C++ in Visual Studio 2008 and upwards */
+#if (_MSC_VER >= 1500)
+#define pg_restrict __restrict
+#else
+#define pg_restrict
+#endif
+
 /* 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.  */
-/* Visual Studio 2008 and upwards */
-#if (_MSC_VER >= 1500)
-/* works for C and C++ in msvc */
-/*
- * Temporary attempt at a workaround for stdlib.h's use of
- * declspec(restrict), conflicting with below define.
- */
-#include <stdlib.h>
-#define restrict __restrict
-#else
-#define restrict
-#endif
+/* not defined, because it'd conflict with __declspec(restrict) */
 
 /* Define to empty if the C compiler does not understand signed types. */
 /* #undef signed */
-- 
2.14.1.536.g6867272d5b.dirty

-- 
Sent via pgsql-committers mailing list (pgsql-committers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers

Reply via email to