[PATCH/RFC] More strict __DECONST, __DEVOLATILE and __DEQUALIFY implementation.

Pavel Pisa ppisa4lists@pikron.com
Sun Sep 14 14:45:00 GMT 2014

From: Pavel Pisa <ppisa@pikron.com>

This implementation is able to catch cast to type
which differs not only in qualifiers. It suppresses
warning about incompatible pointer assignment only for
case where pointer types differs in volatile and const
in the first indirection level. If pointers differs
other way, the standard waning is reported.

The actual implementation does not distinguish between
volatile and const removal which is equivalent
to the C++ const_cast which is used for C++ code
too. This can be implemented but there would be
much more lines.

Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
 newlib/libc/include/sys/cdefs.h | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

This patch tries to restore some safety in pointers manipulation.
The __DECONST, __DEVOLATILE and __DEQUALIFY macros supress
false warning but original implementation hides more serious
errors when pointers for different types are mixed.

The proposed solution has been tested in some of our projects
and proposed even for RTEMS but discussion with people more
aware of GCC internals is welcomed. I am not sure why cast
to __uintptr_t is used in original code - for warnings
suppression it is not necessary for C/GCC mode. Use of const_cast
for C++ is more straightforward too. Do I miss some alliasing
optimization problems or some other miscompile risk there?

The proposal for newlib is little more optimized and simplified
than previous attempt and was tested only by inclusion in simple test.
It has not been tested in full Newlib based toolchain test yet.

diff --git a/newlib/libc/include/sys/cdefs.h b/newlib/libc/include/sys/cdefs.h
index a5e613c..d1b98fd 100644
--- a/newlib/libc/include/sys/cdefs.h
+++ b/newlib/libc/include/sys/cdefs.h
@@ -571,16 +571,52 @@
 #define	__COPYRIGHT(s)	struct __hack
+#ifndef __TYPEOF_REFX
+/* The cast idea based on libHX by Jan Engelhardt */
+#define __TYPEOF_REFX(ptr_level, ptr_type) \
+  typeof(ptr_level(union { int z; typeof(ptr_type) x; }){0}.x)
+#ifdef __cplusplus
+#define __DEQUALIFY_DEPTHX(ptr_level, type, var) \
+            (const_cast<type>(var))
+#else /* Standard C code */
+#ifdef __GNUC__
+#define __DEQUALIFY_DEPTHX(ptr_level, type, var) ( \
+  __builtin_choose_expr(__builtin_types_compatible_p \
+    (__TYPEOF_REFX(ptr_level, var), \
+     __TYPEOF_REFX(ptr_level, type)), \
+    (type)(var), \
+    var \
+  ) \
+#endif /*__GNUC__*/
+#endif /*__cplusplus*/
+#endif /*__DEQUALIFY_DEPTHX*/
 #ifndef	__DECONST
 #define	__DECONST(type, var)	((type)(__uintptr_t)(const void *)(var))
+#define	__DECONST(type, var)	__DEQUALIFY_DEPTHX(*, type, var)
 #ifndef	__DEVOLATILE
 #define	__DEVOLATILE(type, var)	((type)(__uintptr_t)(volatile void *)(var))
+#define	__DEVOLATILE(type, var)	__DEQUALIFY_DEPTHX(*, type, var)
 #ifndef	__DEQUALIFY
 #define	__DEQUALIFY(type, var)	((type)(__uintptr_t)(const volatile void *)(var))
+#define	__DEQUALIFY(type, var)	__DEQUALIFY_DEPTHX(*, type, var)

More information about the Newlib mailing list