]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
C Compiler Attribute Cleanup Test
authorMaria Matejka <mq@ucw.cz>
Thu, 26 Oct 2023 21:09:20 +0000 (23:09 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 9 Nov 2023 22:08:21 +0000 (23:08 +0100)
There is a long-known CC attribute cleanup which allows to call a custom
cleanup function when an auto-storage variable ceases to exist. We're
gonna use it for end-of-loop and leave-locked-block macros.

This commit adds a static unit test for this compiler feature to be sure
that it really does what we want. We're looking forward to the next ISO
C norm where this may finally get a nice syntax and standardization.

lib/Makefile
lib/attribute_cleanup_test.c [new file with mode: 0644]
lib/birdlib.h

index 812f721cc844f4c8fcd325b9c66089122010b566..5a90e6b46916a66211aa114ff8d65c532eb9612a 100644 (file)
@@ -2,6 +2,6 @@ src := bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c flowspec.c idm.c
 obj := $(src-o-files)
 $(all-daemon)
 
-tests_src := bitmap_test.c heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c checksum_test.c lists_test.c mac_test.c ip_test.c hash_test.c printf_test.c slab_test.c
+tests_src := attribute_cleanup_test.c bitmap_test.c heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c checksum_test.c lists_test.c mac_test.c ip_test.c hash_test.c printf_test.c slab_test.c
 tests_targets := $(tests_targets) $(tests-target-files)
 tests_objs := $(tests_objs) $(src-o-files)
diff --git a/lib/attribute_cleanup_test.c b/lib/attribute_cleanup_test.c
new file mode 100644 (file)
index 0000000..9d1caa0
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *     BIRD Library -- Auto storage attribute cleanup test
+ *
+ *     (c) 2023 Maria Matejka <mq@jmq.cz>
+ *     (c) 2023 CZ.NIC z.s.p.o.
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "test/birdtest.h"
+
+static int order_pos;
+#define CHECK(n) bt_assert(order_pos++ == (n))
+
+static void
+tacd_cleanup(int *val)
+{
+  CHECK(*val);
+}
+
+static void
+tacd_aux(int pos)
+{
+  CHECK(pos + 0);
+
+  UNUSED CLEANUP(tacd_cleanup) int upmost = pos + 18;
+
+  if (order_pos > 0)
+  {
+    CHECK(pos + 1);
+    UNUSED CLEANUP(tacd_cleanup) int inner_if = pos + 3;
+    CHECK(pos + 2);
+  }
+
+  for (int i=0; i<3; i++)
+  {
+    CHECK(pos + 4 + 3*i);
+    UNUSED CLEANUP(tacd_cleanup) int inner_for = pos + 6 + 3*i;
+    CHECK(pos + 5 + 3*i);
+  }
+
+  for (
+      CLEANUP(tacd_cleanup) int i = pos + 15;
+      i < pos + 16; i++)
+  {
+    CHECK(pos + 13);
+    UNUSED CLEANUP(tacd_cleanup) int inner_for = pos + 15;
+    CHECK(pos + 14);
+  }
+
+  CHECK(pos + 17);
+}
+
+#define CHECKCNT 19
+
+static int
+t_attribute_cleanup(void)
+{
+  order_pos = 0;
+  CHECK(0);
+
+  for (int i=0; i<3; i++)
+  {
+    CHECK(i*(CHECKCNT+3) + 1);
+    UNUSED CLEANUP(tacd_cleanup) int inner_for = (i+1) * (CHECKCNT+3);
+    tacd_aux(i*(CHECKCNT+3) + 2);
+    CHECK((i+1) * (CHECKCNT+3) - 1);
+  }
+
+  CHECK(3 * (CHECKCNT+3) + 1);
+
+  return 1;
+}
+
+int main(int argc, char **argv)
+{
+  bt_init(argc, argv);
+
+  bt_test_suite(t_attribute_cleanup, "Basic usability of the cleanup attribute");
+
+  return bt_exit_value();
+}
index b722641116cf4b55406b3bd3dfbbc8359fa0567b..bebefcdacf1d21b99b2454797692979a824dcdbf 100644 (file)
@@ -76,6 +76,7 @@ static inline int u64_cmp(u64 i1, u64 i2)
 #define UNUSED __attribute__((unused))
 #define PACKED __attribute__((packed))
 #define NONNULL(...) __attribute__((nonnull((__VA_ARGS__))))
+#define CLEANUP(fun) __attribute__((cleanup(fun)))
 
 #define STATIC_ASSERT(EXP) _Static_assert(EXP, #EXP)
 #define STATIC_ASSERT_MSG(EXP,MSG) _Static_assert(EXP, MSG)