[clang] [analyzer] Match dangling subobjects by their base region in DanglingPtrDeref (PR #211552)
Balázs Benics via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 23 06:55:43 PDT 2026
================
@@ -112,3 +112,56 @@ void inlined_callee_single_report() {
// expected-note at -1 {{Calling 'deref_param'}}
(void)r;
}
+
+struct MyBuffer {
+ char buffer[8];
+};
+
+void member_subregion_dangling_deref() {
+ const char *p = nullptr;
+ {
+ struct MyBuffer tmp_buffer = {};
+ p = tmp_buffer.buffer;
+ }
+ // expected-note at -1 {{'tmp_buffer.buffer[0]' is destroyed here}}
+ char c = *p;
+ // expected-warning at -1 {{Use of 'tmp_buffer.buffer[0]' after its lifetime ended}}
+ // expected-note at -2 {{Use of 'tmp_buffer.buffer[0]' after its lifetime ended}}
+ (void)c;
+}
+
+void opaque(const char *);
+
+void passing_dangling_to_call() {
+ const char *p = nullptr;
+ {
+ struct MyBuffer tmp_buffer = {};
+ p = tmp_buffer.buffer;
+ }
+ // expected-note at -1 {{'tmp_buffer.buffer[0]' is destroyed here}}
+ opaque(p);
+ // expected-warning at -1 {{Use of 'tmp_buffer.buffer[0]' after its lifetime ended}}
+ // expected-note at -2 {{Use of 'tmp_buffer.buffer[0]' after its lifetime ended}}
+}
+
+void member_subregion_alive_deref() {
+ {
+ struct MyBuffer tmp_buffer = {};
+ const char *p = tmp_buffer.buffer;
+ opaque(p); // no-warning
+ char c = *p; // no-warning
+ (void)c;
+ }
+}
+
+void arr_elem_subreg_dangling_deref() {
+ int *ptr = nullptr;
+ {
+ int local_arr[5];
+ ptr = &local_arr[1];
+ }
+ // expected-note at -1 {{'local_arr[1]' is destroyed here}}
+ *ptr = 7;
+ // expected-warning at -1 {{Use of 'local_arr[1]' after its lifetime ended}}
+ // expected-note at -2 {{Use of 'local_arr[1]' after its lifetime ended}}
----------------
steakhal wrote:
This is just a note for improving the diagnostic messages. I'm not sure if it was tracked somewhere.
In the message we spell "local_arr[1]" but neither "local_arr" or "1" is present otherwise at the line where we report this. This is confusing for the users.
We would need to phrase this as: `ptr` refers to some dead object. It was assigned (bound) at some place... I think the last time we discussed the `trackExpressionValue` and that is what should explain the dataflow answering: how did this pointer value came about?
https://github.com/llvm/llvm-project/pull/211552
More information about the cfe-commits
mailing list