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)						\
 #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[])
 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)						\
 #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)
 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);
 	ok1(strcmp(p, "hello world") == 0);
 }
 }
 
 
+#if 0 /* FIXME */
 static void my_callback_preargs_const(int a, int b, const char *p)
 static void my_callback_preargs_const(int a, int b, const char *p)
 {
 {
 	ok1(a == 1);
 	ok1(a == 1);
@@ -72,6 +73,7 @@ static void my_callback_preargs_volatile(int a, int b, volatile char *p)
 	ok1(b == 2);
 	ok1(b == 2);
 	ok1(strcmp((char *)p, "hello world") == 0);
 	ok1(strcmp((char *)p, "hello world") == 0);
 }
 }
+#endif
 
 
 static void my_callback_postargs(char *p, int a, int b)
 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);
 	ok1(strcmp(p, "hello world") == 0);
 }
 }
 
 
+#if 0 /* FIXME */
 static void my_callback_postargs_const(const char *p, int a, int b)
 static void my_callback_postargs_const(const char *p, int a, int b)
 {
 {
 	ok1(a == 1);
 	ok1(a == 1);
@@ -93,6 +96,7 @@ static void my_callback_postargs_volatile(volatile char *p, int a, int b)
 	ok1(b == 2);
 	ok1(b == 2);
 	ok1(strcmp((char *)p, "hello world") == 0);
 	ok1(strcmp((char *)p, "hello world") == 0);
 }
 }
+#endif
 
 
 /* This is simply a compile test; we promised cast_if_type can be in a
 /* This is simply a compile test; we promised cast_if_type can be in a
  * static initializer. */
  * static initializer. */
@@ -128,7 +132,7 @@ int main(int argc, char *argv[])
 	void *p = &dummy;
 	void *p = &dummy;
 	unsigned long l = (unsigned long)p;
 	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(p);
 	set_some_value(l);
 	set_some_value(l);
 
 
@@ -137,12 +141,16 @@ int main(int argc, char *argv[])
 	callback_onearg(my_callback_onearg_volatile, "hello world");
 	callback_onearg(my_callback_onearg_volatile, "hello world");
 
 
 	callback_preargs(my_callback_preargs, "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_const, "hello world");
 	callback_preargs(my_callback_preargs_volatile, "hello world");
 	callback_preargs(my_callback_preargs_volatile, "hello world");
+#endif
 
 
 	callback_postargs(my_callback_postargs, "hello world");
 	callback_postargs(my_callback_postargs, "hello world");
+#if 0 /* FIXME */
 	callback_postargs(my_callback_postargs_const, "hello world");
 	callback_postargs(my_callback_postargs_const, "hello world");
 	callback_postargs(my_callback_postargs_volatile, "hello world");
 	callback_postargs(my_callback_postargs_volatile, "hello world");
+#endif
 
 
 	return exit_status();
 	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
 #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
  * @desttype: the type to cast to
  * @expr: the expression to cast
  * @expr: the expression to cast
+ * @test: the expression to test
  * @oktype: the type we allow
  * @oktype: the type we allow
  *
  *
  * This macro is used to create functions which allow multiple types.
  * 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
  * This is merely useful for warnings: if the compiler does not
  * support the primitives required for cast_if_type(), it becomes an
  * 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
  * particular, this means that @oktype can be a type which uses
  * the "typeof": it will not be evaluated if typeof is not supported.
  * the "typeof": it will not be evaluated if typeof is not supported.
  *
  *
  * Example:
  * Example:
  *	// We can take either an unsigned long or a void *.
  *	// We can take either an unsigned long or a void *.
  *	void _set_some_value(void *val);
  *	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))
 			(desttype)(expr), (expr))
 #else
 #else
-#define cast_if_type(desttype, expr, oktype) ((desttype)(expr))
+#define cast_if_type(desttype, expr, test, oktype) ((desttype)(expr))
 #endif
 #endif
 
 
 /**
 /**
  * cast_if_any - only cast an expression if it is one of the three given types
  * cast_if_any - only cast an expression if it is one of the three given types
  * @desttype: the type to cast to
  * @desttype: the type to cast to
  * @expr: the expression to cast
  * @expr: the expression to cast
+ * @test: the expression to test
  * @ok1: the first type we allow
  * @ok1: the first type we allow
  * @ok2: the second type we allow
  * @ok2: the second type we allow
  * @ok3: the third 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 *.
  *	// We can take either a long, unsigned long, void * or a const void *.
  *	void _set_some_value(void *val);
  *	void _set_some_value(void *val);
  *	#define set_some_value(expr)					\
  *	#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 *))
  *					    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,				\
 		     cast_if_type(desttype,				\
-				  cast_if_type(desttype, (expr), ok1),	\
+				  cast_if_type(desttype, (expr), (test), ok1), \
 				  ok2),					\
 				  ok2),					\
 		     ok3)
 		     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))
  *		_register_callback(typesafe_cb(void, (fn), (arg)), (arg))
  */
  */
 #define typesafe_cb(rtype, fn, 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
  * 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))
  *		_register_callback(typesafe_cb_const(void, (fn), (arg)), (arg))
  */
  */
 #define typesafe_cb_const(rtype, fn, 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
  * 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))
  *				   (arg))
  */
  */
 #define typesafe_cb_preargs(rtype, fn, 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
  * typesafe_cb_postargs - cast a callback function if it matches the arg
  * @rtype: the return type of the callback function
  * @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))
  *				   (arg))
  */
  */
 #define typesafe_cb_postargs(rtype, fn, 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
  * typesafe_cb_cmp - cast a compare function if it matches the arg
  * @rtype: the return type of the callback function
  * @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.
  * the callback provided takes two a const pointers to @arg.
  *
  *
  * It is assumed that @arg is of pointer type: usually @arg is passed
  * 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:
  * Example:
  *	void _my_qsort(void *base, size_t nmemb, size_t size,
  *	void _my_qsort(void *base, size_t nmemb, size_t size,