hashtable: fix traverse typesafety.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 7 Jun 2010 04:30:22 +0000 (14:00 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 7 Jun 2010 04:30:22 +0000 (14:00 +0930)
ccan/hashtable/hashtable.h
ccan/hashtable/test/compile_fail-traverse-arg1.c [new file with mode: 0644]
ccan/hashtable/test/compile_fail-traverse-arg2.c [new file with mode: 0644]
ccan/hashtable/test/compile_ok-traverse.c [new file with mode: 0644]

index 155ad3fc8dc98c928b3e41deefa2215bf6abc841..7aa27fb30f36587babd15bce8482ecbb8d9e3ffa 100644 (file)
@@ -73,17 +73,18 @@ bool hashtable_del(struct hashtable *ht, unsigned long hash, const void *p);
  */
 #define hashtable_traverse(ht, type, cb, cbarg)                                \
        _hashtable_traverse(ht, cast_if_type(bool (*)(void *, void *),  \
-                            cast_if_any(bool (*)(void *,               \
-                                                 void *), (cb),        \
-                                        bool (*)(const type *,         \
-                                                 const typeof(*cbarg) *), \
-                                        bool (*)(type *,               \
-                                                 const typeof(*cbarg) *), \
-                                        bool (*)(const type *,         \
-                                                 typeof(*cbarg) *)),   \
-                                            bool (*)(type *,           \
-                                                     typeof(*cbarg) *)), \
-                           cbarg)
+                                            cast_if_any(bool (*)(void *, \
+                                                                 void *), \
+                                                        (cb), (cb),    \
+                                                        bool (*)(const type *, \
+                                                                 const typeof(*cbarg) *), \
+                                                        bool (*)(type *, \
+                                                                 const typeof(*cbarg) *), \
+                                                        bool (*)(const type *, \
+                                                                 typeof(*cbarg) *)), \
+                                            (cb),              \
+                                            bool (*)(type *, typeof(*cbarg) *)), \
+                           (cbarg))
 
 void _hashtable_traverse(struct hashtable *ht,
                         bool (*cb)(void *p, void *cbarg), void *cbarg);
diff --git a/ccan/hashtable/test/compile_fail-traverse-arg1.c b/ccan/hashtable/test/compile_fail-traverse-arg1.c
new file mode 100644 (file)
index 0000000..470d425
--- /dev/null
@@ -0,0 +1,32 @@
+#include <ccan/hashtable/hashtable.h>
+#include <ccan/hashtable/hashtable.c>
+#include <stdlib.h>
+
+struct foo {
+       int i;
+};
+
+struct bar {
+       int i;
+};
+
+static bool fn_bar_bar(
+#ifdef FAIL
+       struct bar *
+#else
+       struct foo *
+#endif
+                      foo,
+                      struct bar *bar)
+{
+       return true;
+}
+
+int main(void)
+{
+       struct hashtable *ht = NULL;
+       struct bar *bar = NULL;
+
+       hashtable_traverse(ht, struct foo, fn_bar_bar, bar);
+       return 0;
+}
diff --git a/ccan/hashtable/test/compile_fail-traverse-arg2.c b/ccan/hashtable/test/compile_fail-traverse-arg2.c
new file mode 100644 (file)
index 0000000..5f6ea36
--- /dev/null
@@ -0,0 +1,31 @@
+#include <ccan/hashtable/hashtable.h>
+#include <ccan/hashtable/hashtable.c>
+#include <stdlib.h>
+
+struct foo {
+       int i;
+};
+
+struct bar {
+       int i;
+};
+
+static bool fn_foo_foo(struct foo *foo, 
+#ifdef FAIL
+                      struct foo *
+#else
+                      struct bar *
+#endif
+                      bar)
+{
+       return true;
+}
+
+int main(void)
+{
+       struct hashtable *ht = NULL;
+       struct bar *bar = NULL;
+
+       hashtable_traverse(ht, struct foo, fn_foo_foo, bar);
+       return 0;
+}
diff --git a/ccan/hashtable/test/compile_ok-traverse.c b/ccan/hashtable/test/compile_ok-traverse.c
new file mode 100644 (file)
index 0000000..365180d
--- /dev/null
@@ -0,0 +1,49 @@
+#include <ccan/hashtable/hashtable.h>
+#include <ccan/hashtable/hashtable.c>
+
+struct foo {
+       int i;
+};
+
+struct bar {
+       int i;
+};
+
+static bool fn_foo_bar(struct foo *foo, struct bar *bar)
+{
+       return true;
+}
+
+static bool fn_const_foo_bar(const struct foo *foo, struct bar *bar)
+{
+       return true;
+}
+
+static bool fn_foo_const_bar(struct foo *foo, const struct bar *bar)
+{
+       return true;
+}
+
+static bool fn_const_foo_const_bar(const struct foo *foo,
+                                  const struct bar *bar)
+{
+       return true;
+}
+
+static bool fn_void_void(void *foo, void *bar)
+{
+       return true;
+}
+
+int main(void)
+{
+       struct hashtable *ht = NULL;
+       struct bar *bar = NULL;
+
+       hashtable_traverse(ht, struct foo, fn_foo_bar, bar);
+       hashtable_traverse(ht, struct foo, fn_const_foo_bar, bar);
+       hashtable_traverse(ht, struct foo, fn_foo_const_bar, bar);
+       hashtable_traverse(ht, struct foo, fn_const_foo_const_bar, bar);
+       hashtable_traverse(ht, struct foo, fn_void_void, bar);
+       return 0;
+}