Browse Source

typesafe_cb: handle pointers to undefined struct types.

To do this, we have to lose the ability for preargs and postargs to allow const and volatile argument signatures.
Rusty Russell 16 years ago
parent
commit
67a035869c

+ 1 - 1
ccan/typesafe_cb/test/compile_fail-cast_if_type.c

@@ -7,7 +7,7 @@ void _set_some_value(void *val)
 }
 
 #define set_some_value(expr)						\
-	_set_some_value(cast_if_type(void *, (expr), unsigned long))
+	_set_some_value(cast_if_type(void *, (expr), (expr), unsigned long))
 
 int main(int argc, char *argv[])
 {

+ 2 - 2
ccan/typesafe_cb/test/compile_ok-typesafe_cb-const.c

@@ -28,11 +28,11 @@ static void my_callback(const char *p)
 {
 }
 
-static void my_callback_pre(int x, const char *p)
+static void my_callback_pre(int x, /*const*/ char *p)
 {
 }
 
-static void my_callback_post(const char *p, int x)
+static void my_callback_post(/*const*/ char *p, int x)
 {
 }
 

+ 2 - 2
ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c

@@ -30,11 +30,11 @@ static void my_callback(const struct undefined *undef)
 {
 }
 
-static void my_callback_pre(int x, const struct undefined *undef)
+static void my_callback_pre(int x, struct undefined *undef)
 {
 }
 
-static void my_callback_post(const struct undefined *undef, int x)
+static void my_callback_post(struct undefined *undef, int x)
 {
 }
 

+ 3 - 2
ccan/typesafe_cb/test/compile_ok-typesafe_cb-volatile.c

@@ -28,11 +28,12 @@ static void my_callback(volatile char *p)
 {
 }
 
-static void my_callback_pre(int x, volatile char *p)
+/* FIXME: Can't handle volatile for these */
+static void my_callback_pre(int x, /* volatile */ char *p)
 {
 }
 
-static void my_callback_post(volatile char *p, int x)
+static void my_callback_post(/* volatile */ char *p, int x)
 {
 }
 

+ 10 - 2
ccan/typesafe_cb/test/run.c

@@ -11,7 +11,7 @@ static void _set_some_value(void *val)
 }
 
 #define set_some_value(expr)						\
-	_set_some_value(cast_if_type(void *, (expr), unsigned long))
+	_set_some_value(cast_if_type(void *, (expr), (expr), unsigned long))
 
 static void _callback_onearg(void (*fn)(void *arg), void *arg)
 {
@@ -59,6 +59,7 @@ static void my_callback_preargs(int a, int b, char *p)
 	ok1(strcmp(p, "hello world") == 0);
 }
 
+#if 0 /* FIXME */
 static void my_callback_preargs_const(int a, int b, const char *p)
 {
 	ok1(a == 1);
@@ -72,6 +73,7 @@ static void my_callback_preargs_volatile(int a, int b, volatile char *p)
 	ok1(b == 2);
 	ok1(strcmp((char *)p, "hello world") == 0);
 }
+#endif
 
 static void my_callback_postargs(char *p, int a, int b)
 {
@@ -80,6 +82,7 @@ static void my_callback_postargs(char *p, int a, int b)
 	ok1(strcmp(p, "hello world") == 0);
 }
 
+#if 0 /* FIXME */
 static void my_callback_postargs_const(const char *p, int a, int b)
 {
 	ok1(a == 1);
@@ -93,6 +96,7 @@ static void my_callback_postargs_volatile(volatile char *p, int a, int b)
 	ok1(b == 2);
 	ok1(strcmp((char *)p, "hello world") == 0);
 }
+#endif
 
 /* This is simply a compile test; we promised cast_if_type can be in a
  * static initializer. */
@@ -128,7 +132,7 @@ int main(int argc, char *argv[])
 	void *p = &dummy;
 	unsigned long l = (unsigned long)p;
 
-	plan_tests(2 + 3 + 9 + 9);
+	plan_tests(2 + 3 + 3 + 3);
 	set_some_value(p);
 	set_some_value(l);
 
@@ -137,12 +141,16 @@ int main(int argc, char *argv[])
 	callback_onearg(my_callback_onearg_volatile, "hello world");
 
 	callback_preargs(my_callback_preargs, "hello world");
+#if 0 /* FIXME */
 	callback_preargs(my_callback_preargs_const, "hello world");
 	callback_preargs(my_callback_preargs_volatile, "hello world");
+#endif
 
 	callback_postargs(my_callback_postargs, "hello world");
+#if 0 /* FIXME */
 	callback_postargs(my_callback_postargs_const, "hello world");
 	callback_postargs(my_callback_postargs_volatile, "hello world");
+#endif
 
 	return exit_status();
 }

+ 22 - 27
ccan/typesafe_cb/typesafe_cb.h

@@ -4,9 +4,10 @@
 
 #if HAVE_TYPEOF && HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P
 /**
- * cast_if_type - only cast an expression if it is of a given type
+ * cast_if_type - only cast an expression if test matches a given type
  * @desttype: the type to cast to
  * @expr: the expression to cast
+ * @test: the expression to test
  * @oktype: the type we allow
  *
  * This macro is used to create functions which allow multiple types.
@@ -19,27 +20,28 @@
  *
  * This is merely useful for warnings: if the compiler does not
  * support the primitives required for cast_if_type(), it becomes an
- * unconditional cast, and the @oktype argument is not used.  In
+ * unconditional cast, and the @test and @oktype argument is not used.  In
  * particular, this means that @oktype can be a type which uses
  * the "typeof": it will not be evaluated if typeof is not supported.
  *
  * Example:
  *	// We can take either an unsigned long or a void *.
  *	void _set_some_value(void *val);
- *	#define set_some_value(expr)			\
- *		_set_some_value(cast_if_type(void *, (expr), unsigned long))
+ *	#define set_some_value(e)			\
+ *		_set_some_value(cast_if_type(void *, (e), (e), unsigned long))
  */
-#define cast_if_type(desttype, expr, oktype)				\
-__builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype), \
+#define cast_if_type(desttype, expr, test, oktype)			\
+__builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(test):0), oktype), \
 			(desttype)(expr), (expr))
 #else
-#define cast_if_type(desttype, expr, oktype) ((desttype)(expr))
+#define cast_if_type(desttype, expr, test, oktype) ((desttype)(expr))
 #endif
 
 /**
  * cast_if_any - only cast an expression if it is one of the three given types
  * @desttype: the type to cast to
  * @expr: the expression to cast
+ * @test: the expression to test
  * @ok1: the first type we allow
  * @ok2: the second type we allow
  * @ok3: the third type we allow
@@ -52,13 +54,13 @@ __builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype),
  *	// We can take either a long, unsigned long, void * or a const void *.
  *	void _set_some_value(void *val);
  *	#define set_some_value(expr)					\
- *		_set_some_value(cast_if_any(void *, (expr),		\
+ *		_set_some_value(cast_if_any(void *, (expr), (expr),	\
  *					    long, unsigned long, const void *))
  */
-#define cast_if_any(desttype, expr, ok1, ok2, ok3)			\
+#define cast_if_any(desttype, expr, test, ok1, ok2, ok3)		\
 	cast_if_type(desttype,						\
 		     cast_if_type(desttype,				\
-				  cast_if_type(desttype, (expr), ok1),	\
+				  cast_if_type(desttype, (expr), (test), ok1), \
 				  ok2),					\
 		     ok3)
 
@@ -81,10 +83,7 @@ __builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype),
  *		_register_callback(typesafe_cb(void, (fn), (arg)), (arg))
  */
 #define typesafe_cb(rtype, fn, arg)			\
-	cast_if_any(rtype (*)(void *), (fn),		\
-		    rtype (*)(typeof(*arg)*),		\
-		    rtype (*)(const typeof(*arg)*),	\
-		    rtype (*)(volatile typeof(*arg)*))
+	cast_if_type(rtype (*)(void *), (fn), (fn)(arg), rtype)
 
 /**
  * typesafe_cb_const - cast a const callback function if it matches the arg
@@ -105,8 +104,9 @@ __builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype),
  *		_register_callback(typesafe_cb_const(void, (fn), (arg)), (arg))
  */
 #define typesafe_cb_const(rtype, fn, arg)				\
-	cast_if_type(rtype (*)(const void *), (fn),			\
-		     rtype (*)(const typeof(*arg)*))
+	sizeof((fn)((const void *)0)),					\
+		cast_if_type(rtype (*)(const void *),			\
+			     (fn), (fn)(arg), rtype (*)(typeof(arg)))
 
 /**
  * typesafe_cb_preargs - cast a callback function if it matches the arg
@@ -124,11 +124,8 @@ __builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype),
  *				   (arg))
  */
 #define typesafe_cb_preargs(rtype, fn, arg, ...)			\
-	cast_if_any(rtype (*)(__VA_ARGS__, void *), (fn),		\
-		    rtype (*)(__VA_ARGS__, typeof(arg)),		\
-		    rtype (*)(__VA_ARGS__, const typeof(*arg) *),	\
-		    rtype (*)(__VA_ARGS__, volatile typeof(*arg) *))
-
+	cast_if_type(rtype (*)(__VA_ARGS__, void *), (fn), (fn),	\
+		     rtype (*)(__VA_ARGS__, typeof(arg)))
 /**
  * typesafe_cb_postargs - cast a callback function if it matches the arg
  * @rtype: the return type of the callback function
@@ -145,11 +142,8 @@ __builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype),
  *				   (arg))
  */
 #define typesafe_cb_postargs(rtype, fn, arg, ...)			\
-	cast_if_any(rtype (*)(void *, __VA_ARGS__), (fn),		\
-		    rtype (*)(typeof(arg), __VA_ARGS__),		\
-		    rtype (*)(const typeof(*arg) *, __VA_ARGS__),	\
-		    rtype (*)(volatile typeof(*arg) *, __VA_ARGS__))
-
+	cast_if_type(rtype (*)(void *, __VA_ARGS__), (fn), (fn),	\
+		     rtype (*)(typeof(arg), __VA_ARGS__))
 /**
  * typesafe_cb_cmp - cast a compare function if it matches the arg
  * @rtype: the return type of the callback function
@@ -161,7 +155,8 @@ __builtin_choose_expr(__builtin_types_compatible_p(typeof(1?(expr):0), oktype),
  * the callback provided takes two a const pointers to @arg.
  *
  * It is assumed that @arg is of pointer type: usually @arg is passed
- * or assigned to a void * elsewhere anyway.
+ * or assigned to a void * elsewhere anyway.  Note also that the type
+ * arg points to must be defined.
  *
  * Example:
  *	void _my_qsort(void *base, size_t nmemb, size_t size,