From 67a035869c6f3512ba943ae197b407f182a4506d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 24 May 2010 12:32:59 +0930 Subject: [PATCH 1/1] 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. --- .../test/compile_fail-cast_if_type.c | 2 +- .../test/compile_ok-typesafe_cb-const.c | 4 +- .../test/compile_ok-typesafe_cb-undefined.c | 4 +- .../test/compile_ok-typesafe_cb-volatile.c | 5 +- ccan/typesafe_cb/test/run.c | 12 ++++- ccan/typesafe_cb/typesafe_cb.h | 49 +++++++++---------- 6 files changed, 40 insertions(+), 36 deletions(-) diff --git a/ccan/typesafe_cb/test/compile_fail-cast_if_type.c b/ccan/typesafe_cb/test/compile_fail-cast_if_type.c index f5a02e41..61079351 100644 --- a/ccan/typesafe_cb/test/compile_fail-cast_if_type.c +++ b/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[]) { diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-const.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb-const.c index f8d0ae0f..5017928a 100644 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-const.c +++ b/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) { } diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c index d4ae4ca3..62867e7e 100644 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c +++ b/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) { } diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-volatile.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb-volatile.c index bc87ae8d..ecb0c58b 100644 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-volatile.c +++ b/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) { } diff --git a/ccan/typesafe_cb/test/run.c b/ccan/typesafe_cb/test/run.c index 2068785e..ef10d44b 100644 --- a/ccan/typesafe_cb/test/run.c +++ b/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(); } diff --git a/ccan/typesafe_cb/typesafe_cb.h b/ccan/typesafe_cb/typesafe_cb.h index 98d0d4f0..f5e416de 100644 --- a/ccan/typesafe_cb/typesafe_cb.h +++ b/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, -- 2.39.2