================
@@ -149,3 +150,93 @@ int early_return_shape(void) {
return 1;
return 0;
} // no leak on either path: the cleanup frees *p at the return.
+
+//===----------------------------------------------------------------------===//
+// Scope-exit shapes: goto, cleanup ordering and nesting.
+//===----------------------------------------------------------------------===//
+
+// The cleanup runs on every exit from the scope, including jumps.
+
+static void goto_cleanup(int *p) {
+ clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+ (void)p;
+}
+
+void goto_out_of_block_scope(void) {
+ {
+ int x __attribute__((cleanup(goto_cleanup)));
+ x = 1;
+ goto out;
+ }
+out:;
+}
+
+static void goto_cleanup_at_function_scope(int *p) {
+ clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+ (void)p;
+}
+
+void goto_at_function_scope(void) {
+ int x __attribute__((cleanup(goto_cleanup_at_function_scope)));
+ x = 1;
+ goto out;
+out:;
+}
+
+// Two cleanup handlers in the same scope run in reverse declaration order,
+// as in GCC.
+
+static int order_probe_global;
+
+static void order_probe(int *p) {
+ clang_analyzer_dump_int(order_probe_global); // expected-warning {{2 S32b}}
+ (void)p;
+}
+
+static void order_side_effect(int *p) {
+ order_probe_global = 2;
+ (void)p;
+}
+
+void cleanup_runs_in_reverse_declaration_order(void) {
+ int x __attribute__((cleanup(order_probe)));
+ int y __attribute__((cleanup(order_side_effect)));
+ x = 1;
+ y = 2;
+} // order_side_effect (declared last) runs first, so the dump above prints 2.
+
+// A cleanup handler can declare cleanup-attributed variables of its own:
+// the nested cleanup runs when the inlined handler exits.
+
+static void nested_cleanup(int *p) {
+ clang_analyzer_dump_int(*p); // expected-warning {{3 S32b}}
+}
+
+static void nested_handler(int *p) {
+ int z __attribute__((cleanup(nested_cleanup)));
+ z = 3;
+ (void)p;
+}
+
+void cleanup_nested_in_cleanup(void) {
+ int x __attribute__((cleanup(nested_handler)));
+ x = 42;
+}
----------------
necto wrote:
Here, it is not clear whether `nested_cleanup` was invoked when
`nested_handler` was taken as an entry point or `cleanup_nested_in_cleanup`.
You can set and print the value of a global to prove that it is a chain of all
3 functions.
https://github.com/llvm/llvm-project/pull/221110
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits