From 361f3ea9ee577c5a3e2fed687a0b417b257c31de Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 22 Feb 2012 14:59:32 +1030 Subject: lib/ccan: import failtest and required ccan modules for TDB2 unit tests. New modules: failtest, list, time, read_write_all and tlist. Signed-off-by: Rusty Russell --- lib/ccan/check_type/_info | 33 ++++++++++++ lib/ccan/check_type/check_type.h | 63 ++++++++++++++++++++++ lib/ccan/check_type/test/compile_fail-check_type.c | 9 ++++ .../test/compile_fail-check_type_unsigned.c | 14 +++++ .../test/compile_fail-check_types_match.c | 10 ++++ lib/ccan/check_type/test/run.c | 22 ++++++++ 6 files changed, 151 insertions(+) create mode 100644 lib/ccan/check_type/_info create mode 100644 lib/ccan/check_type/check_type.h create mode 100644 lib/ccan/check_type/test/compile_fail-check_type.c create mode 100644 lib/ccan/check_type/test/compile_fail-check_type_unsigned.c create mode 100644 lib/ccan/check_type/test/compile_fail-check_types_match.c create mode 100644 lib/ccan/check_type/test/run.c (limited to 'lib/ccan/check_type') diff --git a/lib/ccan/check_type/_info b/lib/ccan/check_type/_info new file mode 100644 index 0000000000..33448b4f1f --- /dev/null +++ b/lib/ccan/check_type/_info @@ -0,0 +1,33 @@ +#include +#include +#include "config.h" + +/** + * check_type - routines for compile time type checking + * + * C has fairly weak typing: ints get automatically converted to longs, signed + * to unsigned, etc. There are some cases where this is best avoided, and + * these macros provide methods for evoking warnings (or build errors) when + * a precise type isn't used. + * + * On compilers which don't support typeof() these routines are less effective, + * since they have to use sizeof() which can only distiguish between types of + * different size. + * + * License: Public domain + * Author: Rusty Russell + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { +#if !HAVE_TYPEOF + printf("ccan/build_assert\n"); +#endif + return 0; + } + + return 1; +} diff --git a/lib/ccan/check_type/check_type.h b/lib/ccan/check_type/check_type.h new file mode 100644 index 0000000000..b199347116 --- /dev/null +++ b/lib/ccan/check_type/check_type.h @@ -0,0 +1,63 @@ +#ifndef CCAN_CHECK_TYPE_H +#define CCAN_CHECK_TYPE_H +#include "config.h" + +/** + * check_type - issue a warning or build failure if type is not correct. + * @expr: the expression whose type we should check (not evaluated). + * @type: the exact type we expect the expression to be. + * + * This macro is usually used within other macros to try to ensure that a macro + * argument is of the expected type. No type promotion of the expression is + * done: an unsigned int is not the same as an int! + * + * check_type() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // They should always pass a 64-bit value to _set_some_value! + * #define set_some_value(expr) \ + * _set_some_value((check_type((expr), uint64_t), (expr))) + */ + +/** + * check_types_match - issue a warning or build failure if types are not same. + * @expr1: the first expression (not evaluated). + * @expr2: the second expression (not evaluated). + * + * This macro is usually used within other macros to try to ensure that + * arguments are of identical types. No type promotion of the expressions is + * done: an unsigned int is not the same as an int! + * + * check_types_match() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // Do subtraction to get to enclosing type, but make sure that + * // pointer is of correct type for that member. + * #define container_of(mbr_ptr, encl_type, mbr) \ + * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \ + * ((encl_type *) \ + * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr)))) + */ +#if HAVE_TYPEOF +#define check_type(expr, type) \ + ((typeof(expr) *)0 != (type *)0) + +#define check_types_match(expr1, expr2) \ + ((typeof(expr1) *)0 != (typeof(expr2) *)0) +#else +#include +/* Without typeof, we can only test the sizes. */ +#define check_type(expr, type) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type)) + +#define check_types_match(expr1, expr2) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2)) +#endif /* HAVE_TYPEOF */ + +#endif /* CCAN_CHECK_TYPE_H */ diff --git a/lib/ccan/check_type/test/compile_fail-check_type.c b/lib/ccan/check_type/test/compile_fail-check_type.c new file mode 100644 index 0000000000..fe7d6a235c --- /dev/null +++ b/lib/ccan/check_type/test/compile_fail-check_type.c @@ -0,0 +1,9 @@ +#include + +int main(int argc, char *argv[]) +{ +#ifdef FAIL + check_type(argc, char); +#endif + return 0; +} diff --git a/lib/ccan/check_type/test/compile_fail-check_type_unsigned.c b/lib/ccan/check_type/test/compile_fail-check_type_unsigned.c new file mode 100644 index 0000000000..574d4aeb24 --- /dev/null +++ b/lib/ccan/check_type/test/compile_fail-check_type_unsigned.c @@ -0,0 +1,14 @@ +#include + +int main(int argc, char *argv[]) +{ +#ifdef FAIL +#if HAVE_TYPEOF + check_type(argc, unsigned int); +#else + /* This doesn't work without typeof, so just fail */ +#error "Fail without typeof" +#endif +#endif + return 0; +} diff --git a/lib/ccan/check_type/test/compile_fail-check_types_match.c b/lib/ccan/check_type/test/compile_fail-check_types_match.c new file mode 100644 index 0000000000..cbd6e9bc5b --- /dev/null +++ b/lib/ccan/check_type/test/compile_fail-check_types_match.c @@ -0,0 +1,10 @@ +#include + +int main(int argc, char *argv[]) +{ + unsigned char x = argc; +#ifdef FAIL + check_types_match(argc, x); +#endif + return x; +} diff --git a/lib/ccan/check_type/test/run.c b/lib/ccan/check_type/test/run.c new file mode 100644 index 0000000000..83b903c0b1 --- /dev/null +++ b/lib/ccan/check_type/test/run.c @@ -0,0 +1,22 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + int x = 0, y = 0; + + plan_tests(9); + + ok1(check_type(argc, int) == 0); + ok1(check_type(&argc, int *) == 0); + ok1(check_types_match(argc, argc) == 0); + ok1(check_types_match(argc, x) == 0); + ok1(check_types_match(&argc, &x) == 0); + + ok1(check_type(x++, int) == 0); + ok(x == 0, "check_type does not evaluate expression"); + ok1(check_types_match(x++, y++) == 0); + ok(x == 0 && y == 0, "check_types_match does not evaluate expressions"); + + return exit_status(); +} -- cgit