From d396cb7e22b3e25060cbb80e5c857ea655bc500b Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 7 Oct 2026 08:21:37 +0200 Subject: [PATCH] Add unconstify_constexpr unconstify_constexpr is like unconstify but for contexts where a constant expression is required, such as for initializing global variables. It provides the same level of checking as unconstify, but the checking only works on GCC, otherwise it lets anything through. Also, if the check fails, it gives a less clear error message. So it should only be used when necessary. (An unvolatize_constexpr doesn't seem necessary, but it could be added if required.) Reviewed-by: Rui Zhao Discussion: https://www.postgresql.org/message-id/c76b72dd-5736-453a-b698-6968d42e4768%40eisentraut.org --- src/include/c.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/include/c.h b/src/include/c.h index 95e71d7e612..367b32c5b6f 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -1412,20 +1412,37 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock; * design or language restrictions prevent you from declaring that * (e.g. because a function returns both const and non-const variables). * - * Note that this only works in function scope, not for global variables (it'd - * be nice, but not trivial, to improve that). + * unconstify_constexpr is for contexts where a constant expression is + * required, such as for initializing global variables. It provides the same + * level of checking as unconstify, but the checking only works on GCC, + * otherwise it lets anything through. Also, if the check fails, it gives a + * less clear error message. So it should only be used when necessary. + * + * (An unvolatize_constexpr doesn't seem necessary, but it could be added if + * required.) */ #if defined(__cplusplus) #define unconstify(underlying_type, expr) const_cast(expr) +#define unconstify_constexpr(underlying_type, expr) const_cast(expr) #define unvolatize(underlying_type, expr) const_cast(expr) -#else +#else /* !__cplusplus */ #define unconstify(underlying_type, expr) \ (StaticAssertVariableIsOfTypeMacro(expr, const underlying_type), \ (underlying_type) (expr)) #define unvolatize(underlying_type, expr) \ (StaticAssertVariableIsOfTypeMacro(expr, volatile underlying_type), \ (underlying_type) (expr)) -#endif +#ifdef __GNUC__ +#define unconstify_constexpr(underlying_type, expr) \ + __builtin_choose_expr( \ + _Generic((expr), const underlying_type: 1, default: 0), \ + (underlying_type) (expr), \ + (void) 0) +#else /* !__GNUC_ */ +#define unconstify_constexpr(underlying_type, expr) \ + ((underlying_type) (expr)) +#endif /* !__GNUC_ */ +#endif /* !__cplusplus */ /* * SSE2 instructions are part of the spec for the 64-bit x86 ISA. We assume