]> granicus.if.org Git - postgresql/commitdiff
Add macro to cast away const without allowing changes to underlying type.
authorAndres Freund <andres@anarazel.de>
Tue, 16 Oct 2018 19:05:50 +0000 (12:05 -0700)
committerAndres Freund <andres@anarazel.de>
Tue, 16 Oct 2018 19:05:50 +0000 (12:05 -0700)
The new unconsitify(underlying_type, var) macro allows to cast
constness away from a variable, but doesn't allow changing the
underlying type.  Enforcement of the latter currently only works for
gcc like compilers.

Please note IT IS NOT SAFE to cast constness away if the variable will ever
be modified (it would be undefined behaviour). Doing so anyway can cause
compiler misoptimizations or runtime crashes (modifying readonly memory).
It is only safe to use when the the variable will not be modified, but API
design or language restrictions prevent you from declaring that
(e.g. because a function returns both const and non-const variables).

This'll be used in an upcoming change, but seems like it's independent
infrastructure.

Author: Andres Freund
Discussion: https://postgr.es/m/20181015200754.7y7zfuzsoux2c4ya@alap3.anarazel.de

src/include/c.h

index 86fbb630d4a4f4fea696f6145aff23324e5decb9..4a757bc8ea188f2ca0b5cc7c1771c81328be59f7 100644 (file)
@@ -1121,6 +1121,30 @@ typedef union PGAlignedXLogBlock
 #define PG_TEXTDOMAIN(domain) (domain "-" PG_MAJORVERSION)
 #endif
 
+/*
+ * Macro that allows to cast constness away from a variable, but doesn't
+ * allow changing the underlying type.  Enforcement of the latter
+ * currently only works for gcc like compilers.
+ *
+ * Please note IT IS NOT SAFE to cast constness away if the variable will ever
+ * be modified (it would be undefined behaviour). Doing so anyway can cause
+ * compiler misoptimizations or runtime crashes (modifying readonly memory).
+ * It is only safe to use when the the variable will not be modified, but API
+ * 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).
+ */
+#if defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
+#define unconstify(underlying_type, var) \
+       (StaticAssertExpr(__builtin_types_compatible_p(__typeof(var), const underlying_type), \
+                                         "wrong cast"), \
+        (underlying_type) (var))
+#else
+#define unconstify(underlying_type, var) \
+       ((underlying_type) (var))
+#endif
 
 /* ----------------------------------------------------------------
  *                             Section 9: system-specific hacks