https://github.com/benedekaibas updated 
https://github.com/llvm/llvm-project/pull/211818

>From 1025b0c91d2bf411a5fa27357ee61cd2e6c7b31e Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Fri, 24 Jul 2026 16:53:31 +0200
Subject: [PATCH 1/2] [analyzer] Improve dangling value tracking in
 DanglingPtrDeref

---
 .../Checkers/DanglingPtrDeref.cpp              | 11 ++++++-----
 clang/test/Analysis/dangling-ptr-deref.cpp     | 18 +++++++++---------
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
index 9b4b1056c8ee6..51a1cb891f6cc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
@@ -15,8 +15,8 @@ class DanglingPtrDeref : public Checker<check::Location, 
check::PostCall> {
   void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
                      CheckerContext &C) const;
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
-  void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
-                           CheckerContext &C) const;
+  void reportUseAfterScope(const MemRegion *Region, const Stmt *S,
+                           ExplodedNode *N, CheckerContext &C) const;
   const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
 };
 
@@ -45,7 +45,7 @@ void DanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, 
const Stmt *S,
   if (const MemRegion *LocRegion = Loc.getAsRegion()) {
     if (lifetime_modeling::isDeallocated(State, LocRegion)) {
       if (ExplodedNode *N = C.generateNonFatalErrorNode(State))
-        reportUseAfterScope(LocRegion, N, C);
+        reportUseAfterScope(LocRegion, S, N, C);
     }
   }
 }
@@ -62,7 +62,7 @@ void DanglingPtrDeref::checkPostCall(const CallEvent &Call,
     if (const MemRegion *ArgRegion = Call.getArgSVal(Idx).getAsRegion())
       if (lifetime_modeling::isDeallocated(State, ArgRegion))
         if (ExplodedNode *N = C.generateNonFatalErrorNode())
-          reportUseAfterScope(ArgRegion, N, C);
+          reportUseAfterScope(ArgRegion, Call.getArgExpr(Idx), N, C);
   }
 }
 
@@ -75,7 +75,7 @@ static std::string getRegionName(const MemRegion *Reg) {
 }
 
 void DanglingPtrDeref::reportUseAfterScope(const MemRegion *Region,
-                                           ExplodedNode *N,
+                                           const Stmt *S, ExplodedNode *N,
                                            CheckerContext &C) const {
   auto BR = std::make_unique<PathSensitiveBugReport>(
       BugMsg,
@@ -83,6 +83,7 @@ void DanglingPtrDeref::reportUseAfterScope(const MemRegion 
*Region,
        " after its lifetime ended."),
       N);
   BR->addVisitor<DanglingPtrDerefBRVisitor>(Region);
+  bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *BR);
   C.emitReport(std::move(BR));
 }
 
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index fa9dae41421bc..652accd1f359a 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -4,8 +4,8 @@
 void test_case_one() {
   int *ptr = nullptr;
   {
-    int num = 5;
-    ptr = &num;
+    int num = 5; // expected-note {{'num' initialized to 5}}
+    ptr = &num; // expected-note  {{Value assigned to 'ptr'}}
   }
   // expected-note@-1 {{'num' is destroyed here}}
   *ptr = 6;
@@ -17,10 +17,10 @@ void test_case_two() {
   int *ptr_one = nullptr;
   int *ptr_two = nullptr;
   {
-    int n = 1;
-    int m = 2;
-    ptr_one = &n;
-    ptr_two = &m;
+    int n = 1; // expected-note {{'n' initialized to 1}}
+    int m = 2; // expected-note {{'m' initialized to 2}}
+    ptr_one = &n; // expected-note {{Value assigned to 'ptr_one'}}
+    ptr_two = &m; // expected-note {{Value assigned to 'ptr_two'}}
   }
   // expected-note@-1 {{'n' is destroyed here}}
   // expected-note@-2 {{'m' is destroyed here}}
@@ -45,7 +45,7 @@ void test_case_three() {
 void test_case_four() {
   int *ptr = nullptr;
   {
-    int num = 5;
+    int num = 5; // expected-note {{'num' initialized to 5}}
     ptr = &num;
   }
   // expected-note@-1 {{'num' is destroyed here}}
@@ -75,8 +75,8 @@ void test_case_seven() {
   // expected-note@+3 {{Loop condition is true.  Entering loop body}}
   // expected-note@+2 {{Assuming 'i' is >= 10}}
   // expected-note@+1 {{Loop condition is false. Execution continues on line}}
-  for (int i = 0; i < 10; ++i) {
-    ptr = &i;
+  for (int i = 0; i < 10; ++i) { // expected-note {{'i' initialized to 0}}
+    ptr = &i; // expected-note {{Value assigned to 'ptr'}}
     escape(ptr);
   }
   // expected-note@-1 {{'i' is destroyed here}}

>From 415befa8f27112f0152f0adf4340d1cd6fd1a321 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Sun, 26 Jul 2026 18:36:34 +0200
Subject: [PATCH 2/2] Add notes to the test suite.

---
 clang/test/Analysis/dangling-ptr-deref.cpp | 28 +++++++++++-----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index 652accd1f359a..d7cdae75a1d95 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -88,8 +88,8 @@ void test_case_seven() {
 void passing_dangling_ptr_to_opaque_func() {
   int *ptr = nullptr;
   {
-    int num = 5;
-    ptr = &num;
+    int num = 5; // expected-note {{'num' initialized to 5}}
+    ptr = &num; // expected-note  {{Value assigned to 'ptr'}}
   }
   // expected-note@-1 {{'num' is destroyed here}}
   escape(ptr);
@@ -104,7 +104,7 @@ int deref_param(int *p) { return *p; }
 void inlined_callee_single_report() {
   int *ptr = nullptr;
   {
-    int num = 5;
+    int num = 5; // expected-note {{'num' initialized to 5}}
     ptr = &num;
   }
   // expected-note@-1 {{'num' is destroyed here}}
@@ -131,7 +131,7 @@ struct A {
 char member_subregion_dangling_deref() {
   const char *p = nullptr;
   {
-    MyBuffer tmp_buffer = {};
+    MyBuffer tmp_buffer = {}; // expected-note {{Initializing to 0}}
     p = tmp_buffer.buffer;
   }
   // expected-note@-1 {{'tmp_buffer.buffer[0]' is destroyed here}}
@@ -147,7 +147,7 @@ void passing_dangling_to_call() {
   const char *p = nullptr;
   {
     MyBuffer tmp_buffer = {};
-    p = tmp_buffer.buffer;
+    p = tmp_buffer.buffer; // expected-note {{Value assigned to 'p'}}
   }
   // expected-note@-1 {{'tmp_buffer.buffer[0]' is destroyed here}}
   opaque(p);
@@ -178,8 +178,8 @@ char member_subregion_alive_deref_pp() {
 void arr_elem_subreg_dangling_deref() {
   int *ptr = nullptr;
   {
-    int local_arr[4];
-    ptr = &local_arr[1];
+    int local_arr[4]; // expected-note    {{'local_arr' declared without an 
initial value}}
+    ptr = &local_arr[1]; // expected-note {{Value assigned to 'ptr'}}
   }
   // expected-note@-1 {{'local_arr[1]' is destroyed here}}
   *ptr = 7;
@@ -190,7 +190,7 @@ void arr_elem_subreg_dangling_deref() {
 char member_array_elem_dangling_deref() {
   const char *p = nullptr;
   {
-    MyBuffer tmp_buffer = {};
+    MyBuffer tmp_buffer = {}; // expected-note {{Initializing to 0}}
     p = tmp_buffer.buffer + 3;
   }
   // expected-note@-1 {{'tmp_buffer.buffer[3]' is destroyed here}}
@@ -202,7 +202,7 @@ char member_array_elem_dangling_deref() {
 char member_array_out_of_bounds_dangling_deref() {
   const char *p = nullptr;
   {
-    MyBuffer tmp_buffer = {};
+    MyBuffer tmp_buffer = {}; // expected-note {{Initializing to 0}}
     p = tmp_buffer.buffer + 10;
   }
   // expected-note@-1 {{'tmp_buffer.buffer[10]' is destroyed here}}
@@ -214,7 +214,7 @@ char member_array_out_of_bounds_dangling_deref() {
 int struct_field_dangling_deref() {
   int *p = nullptr;
   {
-    MyStruct s = {};
+    MyStruct s = {}; // expected-note {{'s.x' initialized to 0}}
     p = &s.x;
   }
   // expected-note@-1 {{'s.x' is destroyed here}}
@@ -226,7 +226,7 @@ int struct_field_dangling_deref() {
 int struct_array_element_dangling_deref() {
   int *p = nullptr;
   {
-    MyStruct arr[4] = {};
+    MyStruct arr[4] = {}; // expected-note {{field 'x' initialized to 0}}
     p = &arr[2].x;
   }
   // expected-note@-1 {{'arr[2].x' is destroyed here}}
@@ -238,7 +238,7 @@ int struct_array_element_dangling_deref() {
 int nested_field_dangling_deref() {
   int *p = nullptr;
   {
-    Outer o = {};
+    Outer o = {}; // expected-note {{'o.inner.x' initialized to 0}}
     p = &o.inner.x;
   }
   // expected-note@-1 {{'o.inner.x' is destroyed here}}
@@ -250,7 +250,7 @@ int nested_field_dangling_deref() {
 int nested_type_field_dangling_deref() {
   int *p = nullptr;
   {
-    A a = {};
+    A a = {}; // expected-note {{'a.b.x' initialized to 0}}
     p = &a.b.x;
   }
   // expected-note@-1 {{'a.b.x' is destroyed here}}
@@ -262,7 +262,7 @@ int nested_type_field_dangling_deref() {
 char member_subregion_dangling_deref_increment() {
   const char *p = nullptr;
   {
-    MyBuffer tmp_buffer = {};
+    MyBuffer tmp_buffer = {}; // expected-note {{Initializing to 0}}
     p = tmp_buffer.buffer;
   }
   // expected-note@-1 {{'tmp_buffer.buffer[1]' is destroyed here}}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to