[clang] [analyzer] Match dangling subobjects by their base region in DanglingPtrDeref (PR #211552)

Benedek Kaibas via cfe-commits cfe-commits at lists.llvm.org
Sun Jul 26 03:37:26 PDT 2026


================
@@ -112,3 +112,162 @@ void inlined_callee_single_report() {
   // expected-note at -1 {{Calling 'deref_param'}}
   (void)r;
 }
+
+struct MyBuffer {
+  char buffer[8];
+};
+struct MyStruct { int x; };
+
+struct Inner { int x; };
+
+struct Outer { struct Inner inner; };
+
+struct A {
+  struct B { int x; };
+  B b;
+};
+
+
+char member_subregion_dangling_deref() {
+  const char *p = nullptr;
+  {
+    MyBuffer tmp_buffer = {};
+    p = tmp_buffer.buffer;
+  }
+  // expected-note at -1 {{'tmp_buffer.buffer[0]' is destroyed here}}
+  return *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 opaque(const char *);
+void opaque_pp(const char **);
+
+void passing_dangling_to_call() {
+  const char *p = nullptr;
+  {
+    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}}
+}
+
+char member_subregion_alive_deref() {
+  {
+    MyBuffer tmp_buffer = {};
+    const char *p = tmp_buffer.buffer;
+    opaque(p); // no-warning
+    return *p; // no-warning
+  }
+}
+
+char member_subregion_alive_deref_pp() {
+  const char *ptr = nullptr;
+  const char **pp = &ptr;
+  {
+    MyBuffer tmp_buffer = {};
+    ptr = tmp_buffer.buffer;
+  }
+  opaque_pp(pp);
+  return **pp; // no-warning  
+}
+
+void arr_elem_subreg_dangling_deref() {
+  int *ptr = nullptr;
+  {
+    int local_arr[4];
+    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}}
+}
+
+char member_array_elem_dangling_deref() {
+  const char *p = nullptr;
+  {
+    MyBuffer tmp_buffer = {};
+    p = tmp_buffer.buffer + 3;
+  }
+  // expected-note at -1 {{'tmp_buffer.buffer[3]' is destroyed here}}
+  return *p;
+  // expected-warning at -1 {{Use of 'tmp_buffer.buffer[3]' after its lifetime ended}}
+  // expected-note at -2    {{Use of 'tmp_buffer.buffer[3]' after its lifetime ended}}
+}
+
+char member_array_out_of_bounds_dangling_deref() {
+  const char *p = nullptr;
+  {
+    MyBuffer tmp_buffer = {};
+    p = tmp_buffer.buffer + 10;
+  }
+  // expected-note at -1 {{'tmp_buffer.buffer[10]' is destroyed here}}
----------------
benedekaibas wrote:

Sounds good to me!

https://github.com/llvm/llvm-project/pull/211552


More information about the cfe-commits mailing list