From 403a8c76293bdef17bf5ee8af6be92ee4eba6bb1 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 26 Mar 2022 14:29:29 -0400
Subject: [PATCH] Suppress compiler warning in relptr_store().

clang 13 with -Wextra warns that "performing pointer subtraction with
a null pointer has undefined behavior" in the places where freepage.c
tries to set a relptr variable to constant NULL.  This appears to be
a compiler bug, but it's unlikely to get fixed instantly.  Fortunately,
we can work around it by introducing an inline support function, which
seems like a good change anyway because it removes the macro's existing
double-evaluation hazard.

Backpatch to v10 where this code was introduced.

Patch by me, based on an idea of Andres Freund's.

Discussion: https://postgr.es/m/48826.1648310694@sss.pgh.pa.us
---
 src/include/utils/relptr.h | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
index 06e592e0c64..6d49d58ca6c 100644
--- a/src/include/utils/relptr.h
+++ b/src/include/utils/relptr.h
@@ -56,11 +56,24 @@
 #define relptr_is_null(rp) \
 	((rp).relptr_off == 0)
 
+/* We use this inline to avoid double eval of "val" in relptr_store */
+static inline Size
+relptr_store_eval(char *base, char *val)
+{
+	if (val == NULL)
+		return 0;
+	else
+	{
+		Assert(val > base);
+		return val - base;
+	}
+}
+
 #ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
 #define relptr_store(base, rp, val) \
 	(AssertVariableIsOfTypeMacro(base, char *), \
 	 AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
-	 (rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
+	 (rp).relptr_off = relptr_store_eval(base, (char *) (val)))
 #else
 /*
  * If we don't have __builtin_types_compatible_p, assume we might not have
@@ -68,7 +81,7 @@
  */
 #define relptr_store(base, rp, val) \
 	(AssertVariableIsOfTypeMacro(base, char *), \
-	 (rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
+	 (rp).relptr_off = relptr_store_eval(base, (char *) (val)))
 #endif
 
 #define relptr_copy(rp1, rp2) \
-- 
2.39.5