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

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

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

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index b565481d28fdb..631a273bb4f18 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -788,9 +788,20 @@ def SmartPtrChecker: Checker<"SmartPtr">,
   Dependencies<[SmartPtrModeling]>,
   Documentation<HasDocumentation>;
 
+def LifetimeModeling : Checker<"LifetimeModeling">,
+  HelpText<"Model [[clang::lifetimebound]] annotations for lifetime analysis">,
+  Documentation<NotDocumented>,
+  Hidden;
+
 def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">,
   HelpText<"Check for uses of references or pointers that "
            "outlive their bound object">,
+  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 46c0c36fda736..b05a51c46485c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -92,6 +92,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   PointerSubChecker.cpp
   PthreadLockChecker.cpp
   PutenvStackArrayChecker.cpp
+  ReportDanglingPtrDeref.cpp
   RetainCountChecker/RetainCountChecker.cpp
   RetainCountChecker/RetainCountDiagnostics.cpp
   ReturnPointerRangeChecker.cpp

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

---
 .../Checkers/LifetimeModeling.h               |  18 ++++
 .../StaticAnalyzer/Checkers/CMakeLists.txt    |   1 +
 .../Checkers/LifetimeModeling.cpp             | 101 ++++++++++++++++++
 3 files changed, 120 insertions(+)
 create mode 100644 
clang/include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp

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
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index b05a51c46485c..4ec6e368c8fc3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -55,6 +55,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   IteratorModeling.cpp
   IteratorRangeChecker.cpp
   IvarInvalidationChecker.cpp
+  LifetimeModeling.cpp
   LLVMConventionsChecker.cpp
   LocalizationChecker.cpp
   MacOSKeychainAPIChecker.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
new file mode 100644
index 0000000000000..65aa071a3284a
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -0,0 +1,101 @@
+#include "clang/StaticAnalyzer/Checkers/LifetimeModeling.h"
+#include "clang/AST/Attr.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using namespace lifetimemodeling;
+
+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::LifetimeEnd> {
+public:
+  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+  void checkLifetimeEnd(const VarDecl *VD, CheckerContext &C) const;
+};
+
+} // namespace
+
+std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef State,
+                                                    SVal Val) {
+  std::vector<const MemRegion *> StoreRegion;
+  if (const auto *SourceSet = State->get<LifetimeBoundMap>(Val)) {
+    for (const MemRegion *Region : *SourceSet)
+      StoreRegion.push_back(Region);
+    return StoreRegion;
+  }
+  return StoreRegion;
+}
+
+static ProgramStateRef bindValues(ProgramStateRef State, SVal RetVal,
+                                  const MemRegion *Source) {
+  LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>();
+  const LifetimeSourceSet *LSet = State->get<LifetimeBoundMap>(RetVal);
+
+  LifetimeSourceSet Set = LSet ? *LSet : F.getEmptySet();
+  Set = F.add(Set, Source);
+  State = State->set<LifetimeBoundMap>(RetVal, Set);
+  return State;
+}
+
+void LifetimeModeling::checkPostCall(const CallEvent &Call,
+                                     CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+
+  const auto *FC = dyn_cast<AnyFunctionCall>(&Call);
+  if (!FC)
+    return;
+
+  const FunctionDecl *FD = FC->getDecl();
+  if (!FD)
+    return;
+
+  SVal RetVal = Call.getReturnValue();
+
+  for (const ParmVarDecl *PVD : FD->parameters()) {
+    if (PVD->hasAttr<LifetimeBoundAttr>()) {
+      unsigned Idx = PVD->getFunctionScopeIndex();
+      SVal Arg = Call.getArgSVal(Idx);
+      if (const MemRegion *ArgValRegion = Arg.getAsRegion())
+        State = bindValues(State, RetVal, ArgValRegion);
+    }
+  }
+
+  if (const auto *IC = dyn_cast<CXXInstanceCall>(&Call)) {
+    if (lifetimes::implicitObjectParamIsLifetimeBound(FD)) {
+      if (const MemRegion *AttrRegion = IC->getCXXThisVal().getAsRegion())
+        State = bindValues(State, RetVal, AttrRegion);
+    }
+  }
+  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 ento::registerLifetimeModeling(CheckerManager &Mgr) {
+  Mgr.registerChecker<LifetimeModeling>();
+}
+
+bool ento::shouldRegisterLifetimeModeling(const CheckerManager &Mgr) {
+  return true;
+}

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

---
 .../include/clang/StaticAnalyzer/Checkers/LifetimeModeling.h | 1 +
 clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp       | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

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
diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index 65aa071a3284a..1355c4218f921 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -31,11 +31,14 @@ std::vector<const MemRegion *> 
getLifetimeSourceSet(ProgramStateRef State,
   if (const auto *SourceSet = State->get<LifetimeBoundMap>(Val)) {
     for (const MemRegion *Region : *SourceSet)
       StoreRegion.push_back(Region);
-    return StoreRegion;
   }
   return StoreRegion;
 }
 
+bool isDeallocated(ProgramStateRef State, const MemRegion *Region) {
+  return State->contains<DeallocatedSourceSet>(Region);
+}
+
 static ProgramStateRef bindValues(ProgramStateRef State, SVal RetVal,
                                   const MemRegion *Source) {
   LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>();

>From 98aaa83b3029da553dfe751488597e97367c17ea Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 29 Jun 2026 12:57:19 +0200
Subject: [PATCH 4/7] Added ReportDanglingPtrDeref checker.

---
 .../Checkers/LifetimeModeling.cpp             | 10 +++-
 .../Checkers/ReportDanglingPtrDeref.cpp       | 46 +++++++++++++++++++
 2 files changed, 54 insertions(+), 2 deletions(-)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ReportDanglingPtrDeref.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index 1355c4218f921..ea9949d9696ba 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -8,7 +8,6 @@
 
 using namespace clang;
 using namespace ento;
-using namespace lifetimemodeling;
 
 REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(LifetimeSourceSet, const MemRegion *)
 REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMap, SVal, LifetimeSourceSet)
@@ -24,9 +23,12 @@ class LifetimeModeling : public Checker<check::PostCall, 
check::LifetimeEnd> {
 };
 
 } // namespace
-
+namespace clang {
+namespace ento {
+namespace lifetimemodeling {
 std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef State,
                                                     SVal Val) {
+
   std::vector<const MemRegion *> StoreRegion;
   if (const auto *SourceSet = State->get<LifetimeBoundMap>(Val)) {
     for (const MemRegion *Region : *SourceSet)
@@ -39,6 +41,10 @@ bool isDeallocated(ProgramStateRef State, const MemRegion 
*Region) {
   return State->contains<DeallocatedSourceSet>(Region);
 }
 
+} // namespace lifetimemodeling
+} // namespace ento
+} // namespace clang
+
 static ProgramStateRef bindValues(ProgramStateRef State, SVal RetVal,
                                   const MemRegion *Source) {
   LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>();
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 3c6bce8714d946417a0832a57cd36185981b9228 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Mon, 29 Jun 2026 17:47:21 +0200
Subject: [PATCH 5/7] Implemented reportDanglingPtrDeref checker and added test
 suites for the checker.

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

diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index ea9949d9696ba..ab99dcd2ba851 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -23,12 +23,12 @@ class LifetimeModeling : public Checker<check::PostCall, 
check::LifetimeEnd> {
 };
 
 } // namespace
+
 namespace clang {
 namespace ento {
 namespace lifetimemodeling {
 std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef State,
                                                     SVal Val) {
-
   std::vector<const MemRegion *> StoreRegion;
   if (const auto *SourceSet = State->get<LifetimeBoundMap>(Val)) {
     for (const MemRegion *Region : *SourceSet)
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 04f31a393fe9750f2ebb5d6d8fc4739dded2a814 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Thu, 9 Jul 2026 12:59:16 +0200
Subject: [PATCH 6/7] [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 aedc5859fbd80d469f13eb1be3237836d375fcef Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Thu, 9 Jul 2026 13:11:43 +0200
Subject: [PATCH 7/7] [analyzer] Updated the modeling checker.

---
 .../StaticAnalyzer/Checkers/LifetimeModeling.h    | 15 ++++++++-------
 .../StaticAnalyzer/Checkers/LifetimeModeling.cpp  | 12 ++++++------
 2 files changed, 14 insertions(+), 13 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
diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index ab99dcd2ba851..d7e881f29fb97 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -24,9 +24,11 @@ class LifetimeModeling : public Checker<check::PostCall, 
check::LifetimeEnd> {
 
 } // namespace
 
-namespace clang {
-namespace ento {
-namespace lifetimemodeling {
+namespace clang::ento::lifetime_modeling {
+bool isBoundToLifetimeSourceSet(ProgramStateRef State, SVal Val) {
+  return State->get<LifetimeBoundMap>(Val) != nullptr;
+}
+
 std::vector<const MemRegion *> getLifetimeSourceSet(ProgramStateRef State,
                                                     SVal Val) {
   std::vector<const MemRegion *> StoreRegion;
@@ -41,9 +43,7 @@ bool isDeallocated(ProgramStateRef State, const MemRegion 
*Region) {
   return State->contains<DeallocatedSourceSet>(Region);
 }
 
-} // namespace lifetimemodeling
-} // namespace ento
-} // namespace clang
+} // namespace clang::ento::lifetime_modeling
 
 static ProgramStateRef bindValues(ProgramStateRef State, SVal RetVal,
                                   const MemRegion *Source) {

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

Reply via email to