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

>From f296e044437ae6cbb0ba0d3e33c4a00ac1b82295 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 29 Jun 2026 10:19:38 +0200
Subject: [PATCH 01/15] Start implementing the reportDanglingPtrDeref checker.

---
 clang/include/clang/StaticAnalyzer/Checkers/Checkers.td | 5 +++++
 clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt        | 1 +
 2 files changed, 6 insertions(+)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 0f8b3bb1e1d18..d3b042a7d510f 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -806,6 +806,11 @@ def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">,
   Dependencies<[LifetimeModeling]>,
   Documentation<NotDocumented>;
 
+def ReportDanglingPtrDeref : Checker<"ReportDanglingPtrDeref">,
+  HelpText<"Check for dereferences of a dangling pointer">,
+  Dependencies<[LifetimeModeling]>,
+  Documentation<NotDocumented>;
+
 } // end: "alpha.cplusplus"
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 8f61b7d88e8d2..4ec6e368c8fc3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -93,6 +93,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   PointerSubChecker.cpp
   PthreadLockChecker.cpp
   PutenvStackArrayChecker.cpp
+  ReportDanglingPtrDeref.cpp
   RetainCountChecker/RetainCountChecker.cpp
   RetainCountChecker/RetainCountDiagnostics.cpp
   ReturnPointerRangeChecker.cpp

>From 4d1e43906b26f74ef91d263b7252ef44e26c5fae Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Fri, 26 Jun 2026 01:09:44 +0200
Subject: [PATCH 02/15] Implemented the Modeling checker.

---
 .../StaticAnalyzer/Checkers/LifetimeModeling.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 
clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h 
b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
new file mode 100644
index 0000000000000..671d5ce1ec5da
--- /dev/null
+++ b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
@@ -0,0 +1,18 @@
+#ifndef LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H
+#define LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include <vector>
+
+namespace clang {
+namespace ento {
+namespace lifetimemodeling {
+
+std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef, SVal);
+
+} // namespace lifetimemodeling
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H

>From 830b218c18f2edc518b41d593667bd78c88ffbc7 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 29 Jun 2026 10:54:21 +0200
Subject: [PATCH 03/15] Add isDeallocated API to the modeling checker.

---
 clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h 
b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
index 671d5ce1ec5da..e9eb4979e05d2 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
@@ -10,6 +10,7 @@ namespace ento {
 namespace lifetimemodeling {
 
 std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef, SVal);
+bool isDeallocated(ProgramStateRef, const MemRegion *);
 
 } // namespace lifetimemodeling
 } // namespace ento

>From 6e92cd9ca5424b44e5095a0713fe88f60000f69a Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 29 Jun 2026 12:57:19 +0200
Subject: [PATCH 04/15] Added ReportDanglingPtrDeref checker.

---
 .../Checkers/ReportDanglingPtrDeref.cpp       | 46 +++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
new file mode 100644
index 0000000000000..24620d369b80d
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -0,0 +1,46 @@
+#include "clang/StaticAnalyzer/Checkers/LifetimeModeling.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ReportDanglingPtrDeref : public Checker<check::Location> {
+public:
+  void checkLocation(SVal Loc, bool IsLoad, const Stmt *S, CheckerContext &C) 
const;
+  void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N, 
CheckerContext &C) const;
+  const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
+};
+} // namespace
+
+void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt 
*S, CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+
+  if (const MemRegion *LocRegion = Loc.getAsRegion()) {
+    if (lifetimemodeling::isDeallocated(State, LocRegion)) {
+      if (ExplodedNode *N = C.generateNonFatalErrorNode())
+        reportUseAfterScope(LocRegion, N, C);
+    }
+  }
+}
+
+void ReportDanglingPtrDeref::reportUseAfterScope(const MemRegion *Region, 
ExplodedNode *N, CheckerContext &C) const {
+  auto BR = std::make_unique<PathSensitiveBugReport>(
+      BugMsg,
+      (llvm::Twine("Use of '") + Region->getString() +
+       "' after its lifetime ended.")
+          .str(),
+      N);
+  C.emitReport(std::move(BR));
+}
+
+void ento::registerReportDanglingPtrDeref(CheckerManager &Mgr) {
+  Mgr.registerChecker<ReportDanglingPtrDeref>();
+}
+
+bool ento::shouldRegisterReportDanglingPtrDeref(const CheckerManager &Mgr) {
+  return true;
+}

>From 21d1ba323d183bc0c982f3c5c642acf6da89afe7 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 29 Jun 2026 17:47:21 +0200
Subject: [PATCH 05/15] Implemented reportDanglingPtrDeref checker and added
 test suites for the checker.

---
 .../Checkers/ReportDanglingPtrDeref.cpp       | 17 ++++---
 clang/test/Analysis/dangling-ptr-deref.cpp    | 45 +++++++++++++++++++
 2 files changed, 56 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Analysis/dangling-ptr-deref.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index 24620d369b80d..309468b1736f6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -1,8 +1,8 @@
-#include "clang/StaticAnalyzer/Checkers/LifetimeModeling.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Checkers/LifetimeModeling.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 
 using namespace clang;
 using namespace ento;
@@ -10,13 +10,16 @@ using namespace ento;
 namespace {
 class ReportDanglingPtrDeref : public Checker<check::Location> {
 public:
-  void checkLocation(SVal Loc, bool IsLoad, const Stmt *S, CheckerContext &C) 
const;
-  void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N, 
CheckerContext &C) const;
+  void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
+                     CheckerContext &C) const;
+  void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
+                           CheckerContext &C) const;
   const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
 };
 } // namespace
 
-void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt 
*S, CheckerContext &C) const {
+void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt 
*S,
+                                           CheckerContext &C) const {
   ProgramStateRef State = C.getState();
 
   if (const MemRegion *LocRegion = Loc.getAsRegion()) {
@@ -27,7 +30,9 @@ void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool 
IsLoad, const Stmt *S,
   }
 }
 
-void ReportDanglingPtrDeref::reportUseAfterScope(const MemRegion *Region, 
ExplodedNode *N, CheckerContext &C) const {
+void ReportDanglingPtrDeref::reportUseAfterScope(const MemRegion *Region,
+                                                 ExplodedNode *N,
+                                                 CheckerContext &C) const {
   auto BR = std::make_unique<PathSensitiveBugReport>(
       BugMsg,
       (llvm::Twine("Use of '") + Region->getString() +
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
new file mode 100644
index 0000000000000..05755f09c0e57
--- /dev/null
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.ReportDanglingPtrDeref \
+// RUN:   -analyzer-config cfg-lifetime=true -verify %s
+// RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.ReportDanglingPtrDeref \
+// RUN:   -analyzer-config c++-container-inlining=false -analyzer-config 
cfg-lifetime=true -verify %s
+
+void test_case_one() {
+  int *ptr = nullptr;
+  {
+    int num = 5;
+    ptr = &num;
+  }
+  *ptr = 6; // expected-warning {{Use of 'num' after its lifetime ended}}
+}
+
+void test_case_two() {
+  int *ptr_one = nullptr;
+  int *ptr_two = nullptr;
+  {
+    int n = 1;
+    int m = 2;
+    ptr_one = &n;
+    ptr_two = &m;
+  }
+  *ptr_one = 6; // expected-warning {{Use of 'n' after its lifetime ended}}
+  *ptr_two = 7; // expected-warning {{Use of 'm' after its lifetime ended}}
+}
+
+void test_case_three() {
+  int num = 5;
+  int *ptr = &num;
+  {
+    *ptr = 6; // no-warning
+  }
+}
+
+void test_case_four() {
+  int *ptr = nullptr;
+  {
+    int num = 5;
+    ptr = &num;
+  }
+  int i = *ptr; // expected-warning {{Use of 'num' after its lifetime ended}}
+  i += i;
+}
+

>From e2b903a11cfec1406594f707aa3043bb95b87ad3 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Thu, 9 Jul 2026 12:59:16 +0200
Subject: [PATCH 06/15] [analyzer] Implemented VisitNode for
 BugReporterVisitor.

---
 .../Checkers/ReportDanglingPtrDeref.cpp       | 49 ++++++++++++++++++-
 clang/test/Analysis/dangling-ptr-deref.cpp    | 20 +++++---
 2 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index 309468b1736f6..52438dbd2a330 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -1,6 +1,7 @@
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Checkers/LifetimeModeling.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 
@@ -10,12 +11,33 @@ using namespace ento;
 namespace {
 class ReportDanglingPtrDeref : public Checker<check::Location> {
 public:
+  class ReportDanglingPtrDerefBRVisitor : public BugReporterVisitor {
+    SVal BoundRegion;
+    const MemRegion *SourceRegion;
+
+  public:
+    ReportDanglingPtrDerefBRVisitor(SVal Region, const MemRegion *Source)
+        : BoundRegion(Region), SourceRegion(Source) {}
+
+    void Profile(llvm::FoldingSetNodeID &ID) const override {
+      static int X = 0;
+      ID.AddPointer(&X);
+      BoundRegion.Profile(ID);
+      SourceRegion->Profile(ID);
+    }
+
+    PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+                                     BugReporterContext &BRC,
+                                     PathSensitiveBugReport &BR) override;
+  };
+
   void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
                      CheckerContext &C) const;
   void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
                            CheckerContext &C) const;
   const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
 };
+
 } // namespace
 
 void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt 
*S,
@@ -23,8 +45,9 @@ void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool 
IsLoad, const Stmt *S,
   ProgramStateRef State = C.getState();
 
   if (const MemRegion *LocRegion = Loc.getAsRegion()) {
-    if (lifetimemodeling::isDeallocated(State, LocRegion)) {
-      if (ExplodedNode *N = C.generateNonFatalErrorNode())
+    if (lifetime_modeling::isDeallocated(State, LocRegion)) {
+      if (ExplodedNode *N =
+              C.generateNonFatalErrorNode(C.getState(), C.getPredecessor()))
         reportUseAfterScope(LocRegion, N, C);
     }
   }
@@ -42,6 +65,28 @@ void ReportDanglingPtrDeref::reportUseAfterScope(const 
MemRegion *Region,
   C.emitReport(std::move(BR));
 }
 
+PathDiagnosticPieceRef
+ReportDanglingPtrDeref::ReportDanglingPtrDerefBRVisitor::VisitNode(
+    const ExplodedNode *N, BugReporterContext &BRC,
+    PathSensitiveBugReport &BR) {
+  if (!lifetime_modeling::isBoundToLifetimeSourceSet(N->getState(),
+                                                     BoundRegion) ||
+      lifetime_modeling::isBoundToLifetimeSourceSet(
+          N->getFirstPred()->getState(), BoundRegion))
+    return nullptr;
+
+  const Stmt *S = N->getStmtForDiagnostics();
+  if (!S)
+    return nullptr;
+
+  PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
+  return std::make_shared<PathDiagnosticEventPiece>(
+      Pos,
+      (llvm::Twine("'") + SourceRegion->getString() + "' is destroyed here")
+          .str(),
+      true);
+}
+
 void ento::registerReportDanglingPtrDeref(CheckerManager &Mgr) {
   Mgr.registerChecker<ReportDanglingPtrDeref>();
 }
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index 05755f09c0e57..2cbbadcd24313 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.ReportDanglingPtrDeref \
-// RUN:   -analyzer-config cfg-lifetime=true -verify %s
+// RUN:   -analyzer-config cfg-lifetime=true -analyzer-output=text -verify %s
 // RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.ReportDanglingPtrDeref \
-// RUN:   -analyzer-config c++-container-inlining=false -analyzer-config 
cfg-lifetime=true -verify %s
+// RUN:   -analyzer-config c++-container-inlining=false -analyzer-config 
cfg-lifetime=true -analyzer-output=text -verify %s
 
 void test_case_one() {
   int *ptr = nullptr;
@@ -9,7 +9,9 @@ void test_case_one() {
     int num = 5;
     ptr = &num;
   }
-  *ptr = 6; // expected-warning {{Use of 'num' after its lifetime ended}}
+  *ptr = 6;
+  // expected-warning@-1 {{Use of 'num' after its lifetime ended}}
+  // expected-note@-2 {{Use of 'num' after its lifetime ended}}
 }
 
 void test_case_two() {
@@ -21,8 +23,12 @@ void test_case_two() {
     ptr_one = &n;
     ptr_two = &m;
   }
-  *ptr_one = 6; // expected-warning {{Use of 'n' after its lifetime ended}}
-  *ptr_two = 7; // expected-warning {{Use of 'm' after its lifetime ended}}
+  *ptr_one = 6;
+  *ptr_two = 7; 
+  // expected-warning@-2 {{Use of 'n' after its lifetime ended}}
+  // expected-warning@-2 {{Use of 'm' after its lifetime ended}}
+  // expected-note@-4 {{Use of 'n' after its lifetime ended}}
+  // expected-note@-4 {{Use of 'm' after its lifetime ended}}
 }
 
 void test_case_three() {
@@ -39,7 +45,9 @@ void test_case_four() {
     int num = 5;
     ptr = &num;
   }
-  int i = *ptr; // expected-warning {{Use of 'num' after its lifetime ended}}
+  int i = *ptr;
+  // expected-warning@-1 {{Use of 'num' after its lifetime ended}}
+  // expected-note@-2 {{Use of 'num' after its lifetime ended}}
   i += i;
 }
 

>From 3b3e42522257fb11bab1dd4c92d757fa91a83231 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Thu, 9 Jul 2026 13:11:43 +0200
Subject: [PATCH 07/15] [analyzer] Updated the modeling checker.

---
 .../StaticAnalyzer/Checkers/LifetimeModeling.h    | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h 
b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
index e9eb4979e05d2..b39735c09d63a 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
@@ -5,15 +5,16 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include <vector>
 
-namespace clang {
-namespace ento {
-namespace lifetimemodeling {
-
+namespace clang::ento::lifetime_modeling {
+// FIXME: Once #205951 lands this function might needs to be removed.
 std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef, SVal);
+
+/// Returns true if the SVal key is present in the map.
+bool isBoundToLifetimeSourceSet(ProgramStateRef State, SVal Val);
+
+// FIXME: Once PR #205951 lands this function might needs to be removed.
 bool isDeallocated(ProgramStateRef, const MemRegion *);
 
-} // namespace lifetimemodeling
-} // namespace ento
-} // namespace clang
+} // namespace clang::ento::lifetime_modeling
 
 #endif // LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H

>From bfa4b69e071512f8d132c6832e2097111c96b050 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Sun, 12 Jul 2026 22:48:24 +0200
Subject: [PATCH 08/15] Resolved nits.

---
 .../Checkers/ReportDanglingPtrDeref.cpp       | 67 +++++++++----------
 clang/test/Analysis/dangling-ptr-deref.cpp    |  2 -
 2 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index 52438dbd2a330..e25e49be7f9ef 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -7,37 +7,38 @@
 
 using namespace clang;
 using namespace ento;
+using lifetime_modeling::isBoundToLifetimeSourceSet;
 
 namespace {
 class ReportDanglingPtrDeref : public Checker<check::Location> {
 public:
-  class ReportDanglingPtrDerefBRVisitor : public BugReporterVisitor {
-    SVal BoundRegion;
-    const MemRegion *SourceRegion;
-
-  public:
-    ReportDanglingPtrDerefBRVisitor(SVal Region, const MemRegion *Source)
-        : BoundRegion(Region), SourceRegion(Source) {}
-
-    void Profile(llvm::FoldingSetNodeID &ID) const override {
-      static int X = 0;
-      ID.AddPointer(&X);
-      BoundRegion.Profile(ID);
-      SourceRegion->Profile(ID);
-    }
-
-    PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
-                                     BugReporterContext &BRC,
-                                     PathSensitiveBugReport &BR) override;
-  };
-
   void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
                      CheckerContext &C) const;
-  void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
+  void reportUseAfterScope(const MemRegion *Region, SVal Val, ExplodedNode *N,
                            CheckerContext &C) const;
   const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
 };
 
+class ReportDanglingPtrDerefBRVisitor : public BugReporterVisitor {
+  SVal BoundRegion;
+  const MemRegion *SourceRegion;
+
+public:
+  ReportDanglingPtrDerefBRVisitor(SVal Region, const MemRegion *Source)
+      : BoundRegion(Region), SourceRegion(Source) {}
+
+  void Profile(llvm::FoldingSetNodeID &ID) const override {
+    static int X = 0;
+    ID.AddPointer(&X);
+    BoundRegion.Profile(ID);
+    SourceRegion->Profile(ID);
+  }
+
+  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+                                   BugReporterContext &BRC,
+                                   PathSensitiveBugReport &BR) override;
+};
+
 } // namespace
 
 void ReportDanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt 
*S,
@@ -46,33 +47,31 @@ void ReportDanglingPtrDeref::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(C.getState(), C.getPredecessor()))
-        reportUseAfterScope(LocRegion, N, C);
+      if (ExplodedNode *N = C.generateNonFatalErrorNode(State))
+        reportUseAfterScope(LocRegion, Loc, N, C);
     }
   }
 }
 
 void ReportDanglingPtrDeref::reportUseAfterScope(const MemRegion *Region,
-                                                 ExplodedNode *N,
+                                                 SVal Val, ExplodedNode *N,
                                                  CheckerContext &C) const {
   auto BR = std::make_unique<PathSensitiveBugReport>(
       BugMsg,
       (llvm::Twine("Use of '") + Region->getString() +
-       "' after its lifetime ended.")
-          .str(),
+       "' after its lifetime ended."),
       N);
+  BR->addVisitor(
+      std::make_unique<ReportDanglingPtrDerefBRVisitor>(Val, Region));
   C.emitReport(std::move(BR));
 }
 
 PathDiagnosticPieceRef
-ReportDanglingPtrDeref::ReportDanglingPtrDerefBRVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC,
-    PathSensitiveBugReport &BR) {
-  if (!lifetime_modeling::isBoundToLifetimeSourceSet(N->getState(),
-                                                     BoundRegion) ||
-      lifetime_modeling::isBoundToLifetimeSourceSet(
-          N->getFirstPred()->getState(), BoundRegion))
+ReportDanglingPtrDerefBRVisitor::VisitNode(const ExplodedNode *N,
+                                           BugReporterContext &BRC,
+                                           PathSensitiveBugReport &BR) {
+  if (!isBoundToLifetimeSourceSet(N->getState(), BoundRegion) ||
+      isBoundToLifetimeSourceSet(N->getFirstPred()->getState(), BoundRegion))
     return nullptr;
 
   const Stmt *S = N->getStmtForDiagnostics();
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index 2cbbadcd24313..e00307afc4dab 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -1,7 +1,5 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.ReportDanglingPtrDeref \
 // RUN:   -analyzer-config cfg-lifetime=true -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.ReportDanglingPtrDeref \
-// RUN:   -analyzer-config c++-container-inlining=false -analyzer-config 
cfg-lifetime=true -analyzer-output=text -verify %s
 
 void test_case_one() {
   int *ptr = nullptr;

>From d16ccde645e5c679e0451bdaec388af9a1d0ee1b Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Sun, 12 Jul 2026 23:51:30 +0200
Subject: [PATCH 09/15] Check if the root node has pred and apply nits.

---
 .../Checkers/ReportDanglingPtrDeref.cpp               | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index e25e49be7f9ef..932f8b6fceade 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -7,7 +7,6 @@
 
 using namespace clang;
 using namespace ento;
-using lifetime_modeling::isBoundToLifetimeSourceSet;
 
 namespace {
 class ReportDanglingPtrDeref : public Checker<check::Location> {
@@ -61,8 +60,7 @@ void ReportDanglingPtrDeref::reportUseAfterScope(const 
MemRegion *Region,
       (llvm::Twine("Use of '") + Region->getString() +
        "' after its lifetime ended."),
       N);
-  BR->addVisitor(
-      std::make_unique<ReportDanglingPtrDerefBRVisitor>(Val, Region));
+  BR->addVisitor<ReportDanglingPtrDerefBRVisitor>(Val, Region);
   C.emitReport(std::move(BR));
 }
 
@@ -70,8 +68,13 @@ PathDiagnosticPieceRef
 ReportDanglingPtrDerefBRVisitor::VisitNode(const ExplodedNode *N,
                                            BugReporterContext &BRC,
                                            PathSensitiveBugReport &BR) {
+  using lifetime_modeling::isBoundToLifetimeSourceSet;
+  const ExplodedNode *Pred = N->getFirstPred();
+  if (!Pred)
+    return nullptr;
+
   if (!isBoundToLifetimeSourceSet(N->getState(), BoundRegion) ||
-      isBoundToLifetimeSourceSet(N->getFirstPred()->getState(), BoundRegion))
+      isBoundToLifetimeSourceSet(Pred->getState(), BoundRegion))
     return nullptr;
 
   const Stmt *S = N->getStmtForDiagnostics();

>From 3fe52b0eb4a0bb6ea2e0fe8fd9503f8fc102b72d Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 13 Jul 2026 21:23:55 +0200
Subject: [PATCH 10/15] Implemented checkPreStmt and refactored reporting
 checkers.

---
 .../Checkers/LifetimeModeling.h               | 20 --------
 .../Checkers/LifetimeModeling.cpp             | 50 ++++++++++++++++++-
 .../Checkers/LifetimeModeling.h               |  5 ++
 .../Checkers/ReportDanglingPtrDeref.cpp       |  2 +-
 clang/test/Analysis/dangling-ptr-deref.cpp    | 30 +++++++++++
 5 files changed, 85 insertions(+), 22 deletions(-)
 delete mode 100644 
clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h 
b/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
deleted file mode 100644
index b39735c09d63a..0000000000000
--- a/clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H
-#define LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include <vector>
-
-namespace clang::ento::lifetime_modeling {
-// FIXME: Once #205951 lands this function might needs to be removed.
-std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef, SVal);
-
-/// Returns true if the SVal key is present in the map.
-bool isBoundToLifetimeSourceSet(ProgramStateRef State, SVal Val);
-
-// FIXME: Once PR #205951 lands this function might needs to be removed.
-bool isDeallocated(ProgramStateRef, const MemRegion *);
-
-} // namespace clang::ento::lifetime_modeling
-
-#endif // LLVM_CLANG_INCLUDE_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H
diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index a2f58e0710801..4abb7d8dc2d2c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -14,14 +14,20 @@ using namespace ento;
 REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(LifetimeSourceSet, const MemRegion *)
 REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMap, SVal, LifetimeSourceSet)
 
+REGISTER_SET_WITH_PROGRAMSTATE(DeallocatedSourceSet, const MemRegion *)
+
 namespace {
 
-class LifetimeModeling : public Checker<check::PostCall, check::DeadSymbols> {
+class LifetimeModeling
+    : public Checker<check::PostCall, check::DeadSymbols,
+                     check::PreStmt<DeclStmt>, check::LifetimeEnd> {
 public:
   void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
                   const char *Sep) const override;
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+  void checkLifetimeEnd(const VarDecl *VD, CheckerContext &C) const;
+  void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
 };
 
 } // namespace
@@ -55,6 +61,16 @@ std::vector<const MemRegion *> 
lifetime_modeling::getDanglingRegionsAfterReturn(
   return Regions;
 }
 
+bool lifetime_modeling::isDeallocated(ProgramStateRef State,
+                                      const MemRegion *Region) {
+  return State->contains<DeallocatedSourceSet>(Region);
+}
+
+bool lifetime_modeling::isBoundToLifetimeSourceSet(ProgramStateRef State,
+                                                   SVal Val) {
+  return State->get<LifetimeBoundMap>(Val) != nullptr;
+}
+
 static ProgramStateRef bindSource(ProgramStateRef State, SVal RetVal,
                                   const MemRegion *Source) {
   LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>();
@@ -97,10 +113,37 @@ void LifetimeModeling::checkPostCall(const CallEvent &Call,
   C.addTransition(State);
 }
 
+void LifetimeModeling::checkLifetimeEnd(const VarDecl *VD,
+                                        CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  if (!VD)
+    return;
+
+  SVal SourceVal = State->getLValue(VD, C.getStackFrame());
+  if (const MemRegion *SourceValRegion = SourceVal.getAsRegion()) {
+    State = State->add<DeallocatedSourceSet>(SourceValRegion);
+    C.addTransition(State);
+  }
+}
+
+void LifetimeModeling::checkPreStmt(const DeclStmt *DS,
+                                    CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  for (const auto *I : DS->decls()) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(I)) {
+      SVal Val = State->getLValue(VD, C.getStackFrame());
+      if (const MemRegion *ValRegion = Val.getAsRegion())
+        State = State->remove<DeallocatedSourceSet>(ValRegion);
+    }
+  }
+  C.addTransition(State);
+}
+
 void LifetimeModeling::checkDeadSymbols(SymbolReaper &SymReaper,
                                         CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   LifetimeBoundMapTy LBMap = State->get<LifetimeBoundMap>();
+  DeallocatedSourceSetTy Sources = State->get<DeallocatedSourceSet>();
 
   for (SVal Val : llvm::make_first_range(LBMap)) {
     if (const auto *R = Val.getAsRegion(); R && SymReaper.isLiveRegion(R))
@@ -112,6 +155,11 @@ void LifetimeModeling::checkDeadSymbols(SymbolReaper 
&SymReaper,
 
     State = State->remove<LifetimeBoundMap>(Val);
   }
+
+  for (const MemRegion *Region : Sources) {
+    if (!SymReaper.isLiveRegion(Region))
+      State = State->remove<DeallocatedSourceSet>(Region);
+  }
   C.addTransition(State);
 }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h
index e13942eb1856b..f34a0c70b237d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h
@@ -13,6 +13,11 @@ std::vector<const MemRegion *>
 getDanglingRegionsAfterReturn(SVal Source, ProgramStateRef State,
                               CheckerContext &C);
 
+/// Returns true if the SVal key is present in the map.
+bool isBoundToLifetimeSourceSet(ProgramStateRef State, SVal Val);
+
+/// Returns true if the underlying MemRegion is deallocated.
+bool isDeallocated(ProgramStateRef State, const MemRegion *Region);
 } // namespace clang::ento::lifetime_modeling
 
 #endif // LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H
diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index 932f8b6fceade..3de5ff4f853e7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -1,5 +1,5 @@
+#include "LifetimeModeling.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
-#include "clang/StaticAnalyzer/Checkers/LifetimeModeling.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index e00307afc4dab..99d5394d492f7 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -29,6 +29,8 @@ void test_case_two() {
   // expected-note@-4 {{Use of 'm' after its lifetime ended}}
 }
 
+void escape(int *ptr);
+
 void test_case_three() {
   int num = 5;
   int *ptr = &num;
@@ -49,3 +51,31 @@ void test_case_four() {
   i += i;
 }
 
+void test_case_five() {
+  int *ptr = nullptr;
+  for(int i = 0; i < 10; ++i) {
+    ptr = &i;
+  }
+  escape(ptr); // no-warning
+}
+
+void test_case_six() {
+  for(int i = 0; i < 10; ++i) {
+    int *ptr = &i;
+    escape(ptr); // no-warning
+  }
+}
+
+void test_case_seven() {
+  int *ptr = nullptr;
+  for (int i = 0; i < 10; ++i) {
+    ptr = &i;
+    escape(ptr);
+  }
+  *ptr = 6;
+  // expected-warning@-1 {{Use of 'i' after its lifetime ended}}
+  // expected-note@-2 {{Use of 'i' after its lifetime ended}}
+  // expected-note@-7 {{Loop condition is true.  Entering loop body}}
+  // expected-note@-8 {{Assuming 'i' is >= 10}}
+  // expected-note@-9 {{Loop condition is false. Execution continues on line 
71}}
+}

>From 503a3b00288a15e2da3fb39e2d910026a62a6b33 Mon Sep 17 00:00:00 2001
From: Benedek Kaibas <[email protected]>
Date: Mon, 13 Jul 2026 23:47:39 +0200
Subject: [PATCH 11/15] Update clang/test/Analysis/dangling-ptr-deref.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Balázs Benics <[email protected]>
---
 clang/test/Analysis/dangling-ptr-deref.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index 99d5394d492f7..b2960a27e1421 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -25,8 +25,8 @@ void test_case_two() {
   *ptr_two = 7; 
   // expected-warning@-2 {{Use of 'n' after its lifetime ended}}
   // expected-warning@-2 {{Use of 'm' after its lifetime ended}}
-  // expected-note@-4 {{Use of 'n' after its lifetime ended}}
-  // expected-note@-4 {{Use of 'm' after its lifetime ended}}
+  // expected-note@-4    {{Use of 'n' after its lifetime ended}}
+  // expected-note@-4    {{Use of 'm' after its lifetime ended}}
 }
 
 void escape(int *ptr);

>From 6c8ee197b67d51c6017d07fc6f6d1b5cf4a0b5da Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Tue, 14 Jul 2026 00:32:07 +0200
Subject: [PATCH 12/15] Removed SVal from BRVisitor constructor and applied
 nits.

---
 .../Checkers/ReportDanglingPtrDeref.cpp       | 24 ++++++++-----------
 clang/test/Analysis/dangling-ptr-deref.cpp    | 21 +++++++++-------
 2 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index 3de5ff4f853e7..9b4fb00ae4cb4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -13,24 +13,20 @@ class ReportDanglingPtrDeref : public 
Checker<check::Location> {
 public:
   void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
                      CheckerContext &C) const;
-  void reportUseAfterScope(const MemRegion *Region, SVal Val, ExplodedNode *N,
+  void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
                            CheckerContext &C) const;
   const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
 };
 
 class ReportDanglingPtrDerefBRVisitor : public BugReporterVisitor {
-  SVal BoundRegion;
   const MemRegion *SourceRegion;
 
 public:
-  ReportDanglingPtrDerefBRVisitor(SVal Region, const MemRegion *Source)
-      : BoundRegion(Region), SourceRegion(Source) {}
+  ReportDanglingPtrDerefBRVisitor(const MemRegion *Source)
+      : SourceRegion(Source) {}
 
   void Profile(llvm::FoldingSetNodeID &ID) const override {
-    static int X = 0;
-    ID.AddPointer(&X);
-    BoundRegion.Profile(ID);
-    SourceRegion->Profile(ID);
+    ID.AddPointer(SourceRegion);
   }
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
@@ -47,20 +43,20 @@ void ReportDanglingPtrDeref::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, Loc, N, C);
+        reportUseAfterScope(LocRegion, N, C);
     }
   }
 }
 
 void ReportDanglingPtrDeref::reportUseAfterScope(const MemRegion *Region,
-                                                 SVal Val, ExplodedNode *N,
+                                                 ExplodedNode *N,
                                                  CheckerContext &C) const {
   auto BR = std::make_unique<PathSensitiveBugReport>(
       BugMsg,
       (llvm::Twine("Use of '") + Region->getString() +
        "' after its lifetime ended."),
       N);
-  BR->addVisitor<ReportDanglingPtrDerefBRVisitor>(Val, Region);
+  BR->addVisitor<ReportDanglingPtrDerefBRVisitor>(Region);
   C.emitReport(std::move(BR));
 }
 
@@ -68,13 +64,13 @@ PathDiagnosticPieceRef
 ReportDanglingPtrDerefBRVisitor::VisitNode(const ExplodedNode *N,
                                            BugReporterContext &BRC,
                                            PathSensitiveBugReport &BR) {
-  using lifetime_modeling::isBoundToLifetimeSourceSet;
+  using lifetime_modeling::isDeallocated;
   const ExplodedNode *Pred = N->getFirstPred();
   if (!Pred)
     return nullptr;
 
-  if (!isBoundToLifetimeSourceSet(N->getState(), BoundRegion) ||
-      isBoundToLifetimeSourceSet(Pred->getState(), BoundRegion))
+  if (!isDeallocated(N->getState(), SourceRegion) ||
+      isDeallocated(Pred->getState(), SourceRegion))
     return nullptr;
 
   const Stmt *S = N->getStmtForDiagnostics();
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index b2960a27e1421..71929c725de9a 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -3,18 +3,21 @@
 
 void test_case_one() {
   int *ptr = nullptr;
+  // expected-note@+1 {{'num' is destroyed here}}
   {
     int num = 5;
     ptr = &num;
   }
   *ptr = 6;
   // expected-warning@-1 {{Use of 'num' after its lifetime ended}}
-  // expected-note@-2 {{Use of 'num' after its lifetime ended}}
+  // expected-note@-2    {{Use of 'num' after its lifetime ended}}
 }
 
 void test_case_two() {
   int *ptr_one = nullptr;
   int *ptr_two = nullptr;
+  // expected-note@+2 {{'n' is destroyed here}}
+  // expected-note@+1 {{'m' is destroyed here}}
   {
     int n = 1;
     int m = 2;
@@ -24,8 +27,8 @@ void test_case_two() {
   *ptr_one = 6;
   *ptr_two = 7; 
   // expected-warning@-2 {{Use of 'n' after its lifetime ended}}
-  // expected-warning@-2 {{Use of 'm' after its lifetime ended}}
-  // expected-note@-4    {{Use of 'n' after its lifetime ended}}
+  // expected-note@-3    {{Use of 'n' after its lifetime ended}}
+  // expected-warning@-3 {{Use of 'm' after its lifetime ended}}
   // expected-note@-4    {{Use of 'm' after its lifetime ended}}
 }
 
@@ -41,13 +44,14 @@ void test_case_three() {
 
 void test_case_four() {
   int *ptr = nullptr;
+  // expected-note@+1 {{'num' is destroyed here}}
   {
     int num = 5;
     ptr = &num;
   }
   int i = *ptr;
   // expected-warning@-1 {{Use of 'num' after its lifetime ended}}
-  // expected-note@-2 {{Use of 'num' after its lifetime ended}}
+  // expected-note@-2    {{Use of 'num' after its lifetime ended}}
   i += i;
 }
 
@@ -68,14 +72,15 @@ void test_case_six() {
 
 void test_case_seven() {
   int *ptr = nullptr;
+  // expected-note@+4 {{'i' is destroyed here}}
+  // 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 
79}}
   for (int i = 0; i < 10; ++i) {
     ptr = &i;
     escape(ptr);
   }
   *ptr = 6;
   // expected-warning@-1 {{Use of 'i' after its lifetime ended}}
-  // expected-note@-2 {{Use of 'i' after its lifetime ended}}
-  // expected-note@-7 {{Loop condition is true.  Entering loop body}}
-  // expected-note@-8 {{Assuming 'i' is >= 10}}
-  // expected-note@-9 {{Loop condition is false. Execution continues on line 
71}}
+  // expected-note@-2    {{Use of 'i' after its lifetime ended}}
 }

>From 546f1f0b9bd2f037afaa4af3c83476903f7c9b9f Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Tue, 14 Jul 2026 12:40:20 +0200
Subject: [PATCH 13/15] Added PathDiagnosticLocation::createEnd and resolved
 nits.

---
 .../lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp |  7 -------
 clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h |  3 ---
 .../Checkers/ReportDanglingPtrDeref.cpp              |  3 ++-
 clang/test/Analysis/dangling-ptr-deref.cpp           | 12 ++++++------
 4 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index 4abb7d8dc2d2c..42219edc5cceb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -66,11 +66,6 @@ bool lifetime_modeling::isDeallocated(ProgramStateRef State,
   return State->contains<DeallocatedSourceSet>(Region);
 }
 
-bool lifetime_modeling::isBoundToLifetimeSourceSet(ProgramStateRef State,
-                                                   SVal Val) {
-  return State->get<LifetimeBoundMap>(Val) != nullptr;
-}
-
 static ProgramStateRef bindSource(ProgramStateRef State, SVal RetVal,
                                   const MemRegion *Source) {
   LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>();
@@ -116,8 +111,6 @@ void LifetimeModeling::checkPostCall(const CallEvent &Call,
 void LifetimeModeling::checkLifetimeEnd(const VarDecl *VD,
                                         CheckerContext &C) const {
   ProgramStateRef State = C.getState();
-  if (!VD)
-    return;
 
   SVal SourceVal = State->getLValue(VD, C.getStackFrame());
   if (const MemRegion *SourceValRegion = SourceVal.getAsRegion()) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h
index f34a0c70b237d..cea2799db4b1d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h
@@ -13,9 +13,6 @@ std::vector<const MemRegion *>
 getDanglingRegionsAfterReturn(SVal Source, ProgramStateRef State,
                               CheckerContext &C);
 
-/// Returns true if the SVal key is present in the map.
-bool isBoundToLifetimeSourceSet(ProgramStateRef State, SVal Val);
-
 /// Returns true if the underlying MemRegion is deallocated.
 bool isDeallocated(ProgramStateRef State, const MemRegion *Region);
 } // namespace clang::ento::lifetime_modeling
diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index 9b4fb00ae4cb4..fef336eb04a4c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -77,7 +77,8 @@ ReportDanglingPtrDerefBRVisitor::VisitNode(const ExplodedNode 
*N,
   if (!S)
     return nullptr;
 
-  PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
+  PathDiagnosticLocation Pos = PathDiagnosticLocation::createEnd(
+      S, BRC.getSourceManager(), N->getStackFrame());
   return std::make_shared<PathDiagnosticEventPiece>(
       Pos,
       (llvm::Twine("'") + SourceRegion->getString() + "' is destroyed here")
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index 71929c725de9a..8fe88887f5a45 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -3,11 +3,11 @@
 
 void test_case_one() {
   int *ptr = nullptr;
-  // expected-note@+1 {{'num' is destroyed here}}
   {
     int num = 5;
     ptr = &num;
   }
+  // expected-note@-1 {{'num' is destroyed here}}
   *ptr = 6;
   // expected-warning@-1 {{Use of 'num' after its lifetime ended}}
   // expected-note@-2    {{Use of 'num' after its lifetime ended}}
@@ -16,14 +16,14 @@ void test_case_one() {
 void test_case_two() {
   int *ptr_one = nullptr;
   int *ptr_two = nullptr;
-  // expected-note@+2 {{'n' is destroyed here}}
-  // expected-note@+1 {{'m' is destroyed here}}
   {
     int n = 1;
     int m = 2;
     ptr_one = &n;
     ptr_two = &m;
   }
+  // expected-note@-1 {{'n' is destroyed here}}
+  // expected-note@-2 {{'m' is destroyed here}}
   *ptr_one = 6;
   *ptr_two = 7; 
   // expected-warning@-2 {{Use of 'n' after its lifetime ended}}
@@ -44,11 +44,11 @@ void test_case_three() {
 
 void test_case_four() {
   int *ptr = nullptr;
-  // expected-note@+1 {{'num' is destroyed here}}
   {
     int num = 5;
     ptr = &num;
   }
+  // expected-note@-1 {{'num' is destroyed here}}
   int i = *ptr;
   // expected-warning@-1 {{Use of 'num' after its lifetime ended}}
   // expected-note@-2    {{Use of 'num' after its lifetime ended}}
@@ -72,14 +72,14 @@ void test_case_six() {
 
 void test_case_seven() {
   int *ptr = nullptr;
-  // expected-note@+4 {{'i' is destroyed here}}
   // 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 
79}}
+  // expected-note@+1 {{Loop condition is false. Execution continues on line 
78}}
   for (int i = 0; i < 10; ++i) {
     ptr = &i;
     escape(ptr);
   }
+  // expected-note@-1 {{'i' is destroyed here}}
   *ptr = 6;
   // expected-warning@-1 {{Use of 'i' after its lifetime ended}}
   // expected-note@-2    {{Use of 'i' after its lifetime ended}}

>From 099746f9d0b2d968e42b0400d51e20e032bbf812 Mon Sep 17 00:00:00 2001
From: Benedek Kaibas <[email protected]>
Date: Tue, 14 Jul 2026 13:14:39 +0200
Subject: [PATCH 14/15] Update
 clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Balázs Benics <[email protected]>
---
 clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
index fef336eb04a4c..81e3a46092475 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp
@@ -22,7 +22,7 @@ class ReportDanglingPtrDerefBRVisitor : public 
BugReporterVisitor {
   const MemRegion *SourceRegion;
 
 public:
-  ReportDanglingPtrDerefBRVisitor(const MemRegion *Source)
+  explicit ReportDanglingPtrDerefBRVisitor(const MemRegion *Source)
       : SourceRegion(Source) {}
 
   void Profile(llvm::FoldingSetNodeID &ID) const override {

>From bee3af0450a88b14a035fe42848b15feec096da6 Mon Sep 17 00:00:00 2001
From: Benedek Kaibas <[email protected]>
Date: Tue, 14 Jul 2026 13:58:35 +0200
Subject: [PATCH 15/15] Update clang/test/Analysis/dangling-ptr-deref.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Balázs Benics <[email protected]>
---
 clang/test/Analysis/dangling-ptr-deref.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp 
b/clang/test/Analysis/dangling-ptr-deref.cpp
index 8fe88887f5a45..125be852ad87c 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -74,7 +74,7 @@ void test_case_seven() {
   int *ptr = nullptr;
   // 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 
78}}
+  // expected-note@+1 {{Loop condition is false. Execution continues on line}}
   for (int i = 0; i < 10; ++i) {
     ptr = &i;
     escape(ptr);

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

Reply via email to