Browse Source

cast: make sure suncc sees a constant.

cast_const() et. al. are supposed to be a constant expression, so you can do things like:
	static char *p = cast_const(char *, (const char *)"hello");

Unfortunately, a cast to intptr_t and arithmetic makes suncc reject it as
a constant expression.  We need the cast, because (1) the expression could be
a void *, so we can't just add to it, and (2) gcc complains with -Wcast-qual
without it.

So instead of adding BUILD_BUG_OR_ZERO, we use a ? :, which keeps everyone happy.
Rusty Russell 14 years ago
parent
commit
74859ab18b
2 changed files with 22 additions and 8 deletions
  1. 12 8
      ccan/cast/cast.h
  2. 10 0
      ccan/cast/test/compile_ok-static.c

+ 12 - 8
ccan/cast/cast.h

@@ -15,8 +15,8 @@
  * only differs in signed/unsigned, not in type or const-ness.
  * only differs in signed/unsigned, not in type or const-ness.
  */
  */
 #define cast_signed(type, expr)						\
 #define cast_signed(type, expr)						\
-	((type)(expr)							\
-	 + BUILD_ASSERT_OR_ZERO(cast_sign_compatible(type, (expr))))
+	(0 ? BUILD_ASSERT_OR_ZERO(cast_sign_compatible(type, (expr))) :	\
+	 (type)(expr))
 
 
 /**
 /**
  * cast_const - remove a const qualifier from a pointer.
  * cast_const - remove a const qualifier from a pointer.
@@ -26,6 +26,10 @@
  * This ensures that you are only removing the const qualifier from an
  * This ensures that you are only removing the const qualifier from an
  * expression.  The expression must otherwise match @type.
  * expression.  The expression must otherwise match @type.
  *
  *
+ * We cast via intptr_t to suppress gcc's -Wcast-qual (which SAMBA
+ * uses), and via the ? : so Sun CC doesn't complain about the result
+ * not being constant.
+ *
  * If @type is a pointer to a pointer, you must use cast_const2 (etc).
  * If @type is a pointer to a pointer, you must use cast_const2 (etc).
  *
  *
  * Example:
  * Example:
@@ -40,8 +44,8 @@
  *	}
  *	}
  */
  */
 #define cast_const(type, expr)						\
 #define cast_const(type, expr)						\
-	((type)((intptr_t)(expr)					\
-		+ BUILD_ASSERT_OR_ZERO(cast_const_compat1((expr), type))))
+        (0 ? BUILD_ASSERT_OR_ZERO(cast_const_compat1((expr), type)) :   \
+         (type)(intptr_t)(expr))
 
 
 /**
 /**
  * cast_const2 - remove a const qualifier from a pointer to a pointer.
  * cast_const2 - remove a const qualifier from a pointer to a pointer.
@@ -52,8 +56,8 @@
  * expression.  The expression must otherwise match @type.
  * expression.  The expression must otherwise match @type.
  */
  */
 #define cast_const2(type, expr)						\
 #define cast_const2(type, expr)						\
-	((type)((intptr_t)(expr)					\
-		+ BUILD_ASSERT_OR_ZERO(cast_const_compat2((expr), type))))
+        (0 ? BUILD_ASSERT_OR_ZERO(cast_const_compat2((expr), type)) :   \
+	 (type)(intptr_t)(expr))
 
 
 /**
 /**
  * cast_const3 - remove a const from a pointer to a pointer to a pointer..
  * cast_const3 - remove a const from a pointer to a pointer to a pointer..
@@ -64,8 +68,8 @@
  * expression.  The expression must otherwise match @type.
  * expression.  The expression must otherwise match @type.
  */
  */
 #define cast_const3(type, expr)						\
 #define cast_const3(type, expr)						\
-	((type)((intptr_t)(expr)					\
-		+ BUILD_ASSERT_OR_ZERO(cast_const_compat3((expr), type))))
+        (0 ? BUILD_ASSERT_OR_ZERO(cast_const_compat3((expr), type)) :   \
+	 (type)(intptr_t)(expr))
 
 
 
 
 /**
 /**

+ 10 - 0
ccan/cast/test/compile_ok-static.c

@@ -0,0 +1,10 @@
+/* OpenIndiana's CC (aka suncc) has issues with constants: make sure
+ * we are one! */
+#include <ccan/cast/cast.h>
+
+static char *p = cast_const(char *, (const char *)"hello");
+
+int main(int argc, char *argv[])
+{
+	return p[0] == argv[0][0];
+}