https://github.com/DEBADRIBASAK updated 
https://github.com/llvm/llvm-project/pull/166568

>From fd8693c51af7d9f91be0926f4150e77c39e2dba4 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 5 Nov 2025 14:07:42 +0000
Subject: [PATCH 1/8] Adding the lifetime stats collection logic to
 AnalysisBasedWarnings

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 15 +++++++---
 .../Analyses/LifetimeSafety/Origins.h         |  6 ++++
 .../clang/Sema/AnalysisBasedWarnings.h        |  9 ++++++
 .../LifetimeSafety/LifetimeSafety.cpp         | 13 +++++---
 clang/lib/Analysis/LifetimeSafety/Origins.cpp | 18 +++++++++++
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 30 +++++++++++++++++--
 6 files changed, 81 insertions(+), 10 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 91ffbb169f947..eb532bc8be3a7 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -23,7 +23,11 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
 
 namespace clang::lifetimes {
 
@@ -44,10 +48,6 @@ class LifetimeSafetyReporter {
                                   Confidence Confidence) {}
 };
 
-/// The main entry point for the analysis.
-void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter);
-
 namespace internal {
 /// An object to hold the factories for immutable collections, ensuring
 /// that all created states share the same underlying memory management.
@@ -60,6 +60,7 @@ struct LifetimeFactory {
 /// Running the lifetime safety analysis and querying its results. It
 /// encapsulates the various dataflow analyses.
 class LifetimeSafetyAnalysis {
+
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                          LifetimeSafetyReporter *Reporter);
@@ -82,6 +83,12 @@ class LifetimeSafetyAnalysis {
   std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
 };
 } // namespace internal
+
+/// The main entry point for the analysis.
+std::unique_ptr<internal::LifetimeSafetyAnalysis>
+runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
+                          LifetimeSafetyReporter *Reporter);
+
 } // namespace clang::lifetimes
 
 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
index ba138b078b379..3f8c8a4d7ce9b 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
@@ -16,7 +16,10 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/TypeBase.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace clang::lifetimes::internal {
 
@@ -76,6 +79,8 @@ class OriginManager {
 
   void dump(OriginID OID, llvm::raw_ostream &OS) const;
 
+  const llvm::StringMap<int> getMissingOrigins() const;
+
 private:
   OriginID getNextOriginID() { return NextOriginID++; }
 
@@ -85,6 +90,7 @@ class OriginManager {
   llvm::SmallVector<Origin> AllOrigins;
   llvm::DenseMap<const clang::ValueDecl *, OriginID> DeclToOriginID;
   llvm::DenseMap<const clang::Expr *, OriginID> ExprToOriginID;
+  llvm::StringMap<unsigned> ExprTypeToMissingOriginCount;
 };
 } // namespace clang::lifetimes::internal
 
diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h 
b/clang/include/clang/Sema/AnalysisBasedWarnings.h
index 4103c3f006a8f..604039ef61cb7 100644
--- a/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -14,7 +14,10 @@
 #define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H
 
 #include "clang/AST/Decl.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
 #include <memory>
 
 namespace clang {
@@ -95,6 +98,9 @@ class AnalysisBasedWarnings {
   /// a single function.
   unsigned MaxUninitAnalysisBlockVisitsPerFunction;
 
+  /// Map from expressions missing origin in OriginManager to their counts.
+  llvm::StringMap<unsigned> MissingOriginCount;
+
   /// @}
 
 public:
@@ -116,6 +122,9 @@ class AnalysisBasedWarnings {
   Policy &getPolicyOverrides() { return PolicyOverrides; }
 
   void PrintStats() const;
+
+  void FindMissingOrigins(AnalysisDeclContext &AC,
+                          clang::lifetimes::internal::FactManager &FactMgr);
 };
 
 } // namespace sema
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index 00c7ed90503e7..d183ce976f946 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -23,9 +23,11 @@
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/TimeProfiler.h"
+#include "llvm/Support/raw_ostream.h"
 #include <memory>
 
 namespace clang::lifetimes {
@@ -69,9 +71,12 @@ void LifetimeSafetyAnalysis::run() {
 }
 } // namespace internal
 
-void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter) {
-  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
-  Analysis.run();
+std::unique_ptr<internal::LifetimeSafetyAnalysis>
+runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
+                          LifetimeSafetyReporter *Reporter) {
+  std::unique_ptr<internal::LifetimeSafetyAnalysis> Analysis =
+      std::make_unique<internal::LifetimeSafetyAnalysis>(AC, Reporter);
+  Analysis->run();
+  return Analysis;
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index ea51a75324e06..453abf48261c2 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -7,6 +7,9 @@
 
//===----------------------------------------------------------------------===//
 
 #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/TypeBase.h"
+#include "llvm/ADT/StringMap.h"
 
 namespace clang::lifetimes::internal {
 
@@ -22,6 +25,10 @@ void OriginManager::dump(OriginID OID, llvm::raw_ostream 
&OS) const {
   OS << ")";
 }
 
+const llvm::StringMap<unsigned> OriginManager::getMissingOrigins() const {
+  return ExprTypeToMissingOriginCount;
+}
+
 Origin &OriginManager::addOrigin(OriginID ID, const clang::ValueDecl &D) {
   AllOrigins.emplace_back(ID, &D);
   return AllOrigins.back();
@@ -37,6 +44,17 @@ OriginID OriginManager::get(const Expr &E) {
   auto It = ExprToOriginID.find(&E);
   if (It != ExprToOriginID.end())
     return It->second;
+
+  // if the expression has no specific origin, increment the missing origin
+  // counter.
+  std::string ExprStr(E.getStmtClassName());
+  ExprStr = ExprStr + "<" + E.getType().getAsString() + ">";
+  auto CountIt = ExprTypeToMissingOriginCount.find(ExprStr);
+  if (CountIt == ExprTypeToMissingOriginCount.end()) {
+    ExprTypeToMissingOriginCount[ExprStr] = 1;
+  } else {
+    CountIt->second++;
+  }
   // If the expression itself has no specific origin, and it's a reference
   // to a declaration, its origin is that of the declaration it refers to.
   // For pointer types, where we don't pre-emptively create an origin for the
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 140b709dbb651..9160939a85735 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -29,7 +29,9 @@
 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
 #include "clang/Analysis/Analyses/CalledOnceCheck.h"
 #include "clang/Analysis/Analyses/Consumed.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/Analyses/ReachableCode.h"
 #include "clang/Analysis/Analyses/ThreadSafety.h"
 #include "clang/Analysis/Analyses/UninitializedValues.h"
@@ -52,7 +54,9 @@
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <deque>
 #include <iterator>
@@ -3065,7 +3069,11 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
-      lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
+      std::unique_ptr<clang::lifetimes::internal::LifetimeSafetyAnalysis>
+          Analysis =
+              lifetimes::runLifetimeSafetyAnalysis(AC, 
&LifetimeSafetyReporter);
+      if (S.CollectStats)
+        FindMissingOrigins(AC, Analysis->getFactManager());
     }
   }
   // Check for violations of "called once" parameter properties.
@@ -3131,9 +3139,27 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   }
 }
 
+void clang::sema::AnalysisBasedWarnings::FindMissingOrigins(
+    AnalysisDeclContext &AC, lifetimes::internal::FactManager &FactMgr) {
+  if (AC.getCFG()) {
+    for (const auto &[expr, count] :
+         FactMgr.getOriginMgr().getMissingOrigins()) {
+      MissingOriginCount[expr] += count;
+    }
+  }
+}
+
 void clang::sema::AnalysisBasedWarnings::PrintStats() const {
+  llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
+                  "(expression_type : count) :\n";
+  unsigned totalMissingOrigins = 0;
+  for (const auto &[expr, count] : MissingOriginCount) {
+    llvm::errs() << expr << " : " << count << '\n';
+    totalMissingOrigins += count;
+  }
+  llvm::errs() << "Total missing origins: " << totalMissingOrigins << "\n";
+  llvm::errs() << "****************************************\n";
   llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
-
   unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
   unsigned AvgCFGBlocksPerFunction =
       !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;

>From 3ff81d6435d7da0b4c86459fd71344cf2008acca Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 5 Nov 2025 14:22:48 +0000
Subject: [PATCH 2/8] Correcting the signature of getMissingOrigins

---
 .../include/clang/Analysis/Analyses/LifetimeSafety/Origins.h  | 2 +-
 clang/lib/Sema/AnalysisBasedWarnings.cpp                      | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
index 3f8c8a4d7ce9b..26686a63e9204 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
@@ -79,7 +79,7 @@ class OriginManager {
 
   void dump(OriginID OID, llvm::raw_ostream &OS) const;
 
-  const llvm::StringMap<int> getMissingOrigins() const;
+  const llvm::StringMap<unsigned> getMissingOrigins() const;
 
 private:
   OriginID getNextOriginID() { return NextOriginID++; }
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 9160939a85735..77d2013ff3a93 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3151,14 +3151,14 @@ void 
clang::sema::AnalysisBasedWarnings::FindMissingOrigins(
 
 void clang::sema::AnalysisBasedWarnings::PrintStats() const {
   llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
-                  "(expression_type : count) :\n";
+                  "(expression_type : count) :\n\n";
   unsigned totalMissingOrigins = 0;
   for (const auto &[expr, count] : MissingOriginCount) {
     llvm::errs() << expr << " : " << count << '\n';
     totalMissingOrigins += count;
   }
   llvm::errs() << "Total missing origins: " << totalMissingOrigins << "\n";
-  llvm::errs() << "****************************************\n";
+  llvm::errs() << "\n****************************************\n";
   llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
   unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
   unsigned AvgCFGBlocksPerFunction =

>From 499d3b07efd16cce82960ad2c7db5164e9d97b35 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Tue, 18 Nov 2025 13:53:55 +0000
Subject: [PATCH 3/8] Adding a LifetimeSafetyStats struct to keep track of
 missing origins and change the signature of runLifetimeSafetyAnalysis to not
 return the analysis object

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 15 ++++++++--
 .../clang/Sema/AnalysisBasedWarnings.h        |  7 ++---
 .../LifetimeSafety/LifetimeSafety.cpp         | 23 ++++++++++++---
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 28 +++----------------
 4 files changed, 38 insertions(+), 35 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index eb532bc8be3a7..cbbaa6e1884ee 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -38,6 +38,12 @@ enum class Confidence : uint8_t {
   Definite // Reported as a definite error (-Wlifetime-safety-permissive)
 };
 
+/// A structure to hold the statistics related to LifetimeAnalysis.
+/// Curently it holds only the missing origin details.
+struct LifetimeSafetyStats {
+  llvm::StringMap<unsigned> MissingOriginCount;
+};
+
 class LifetimeSafetyReporter {
 public:
   LifetimeSafetyReporter() = default;
@@ -84,10 +90,13 @@ class LifetimeSafetyAnalysis {
 };
 } // namespace internal
 
+// utility function to print missing origin stats.
+void PrintStats(const LifetimeSafetyStats &Stats);
+
 /// The main entry point for the analysis.
-std::unique_ptr<internal::LifetimeSafetyAnalysis>
-runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                          LifetimeSafetyReporter *Reporter);
+void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
+                               LifetimeSafetyReporter *Reporter,
+                               LifetimeSafetyStats &Stats, bool CollectStats);
 
 } // namespace clang::lifetimes
 
diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h 
b/clang/include/clang/Sema/AnalysisBasedWarnings.h
index 604039ef61cb7..eb334fd0e6390 100644
--- a/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -15,8 +15,10 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/StringMap.h"
 #include <memory>
 
@@ -99,7 +101,7 @@ class AnalysisBasedWarnings {
   unsigned MaxUninitAnalysisBlockVisitsPerFunction;
 
   /// Map from expressions missing origin in OriginManager to their counts.
-  llvm::StringMap<unsigned> MissingOriginCount;
+  clang::lifetimes::LifetimeSafetyStats LSStats;
 
   /// @}
 
@@ -122,9 +124,6 @@ class AnalysisBasedWarnings {
   Policy &getPolicyOverrides() { return PolicyOverrides; }
 
   void PrintStats() const;
-
-  void FindMissingOrigins(AnalysisDeclContext &AC,
-                          clang::lifetimes::internal::FactManager &FactMgr);
 };
 
 } // namespace sema
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index d183ce976f946..5935c5fd6df93 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -71,12 +71,27 @@ void LifetimeSafetyAnalysis::run() {
 }
 } // namespace internal
 
-std::unique_ptr<internal::LifetimeSafetyAnalysis>
-runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                          LifetimeSafetyReporter *Reporter) {
+void PrintStats(const LifetimeSafetyStats &Stats) {
+  llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
+                  "(expression_type : count) :\n\n";
+  unsigned totalMissingOrigins = 0;
+  for (const auto &[expr, count] : Stats.MissingOriginCount) {
+    llvm::errs() << expr << " : " << count << '\n';
+    totalMissingOrigins += count;
+  }
+  llvm::errs() << "Total missing origins: " << totalMissingOrigins << "\n";
+  llvm::errs() << "\n****************************************\n";
+}
+
+void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
+                               LifetimeSafetyReporter *Reporter,
+                               LifetimeSafetyStats &Stats, bool CollectStats) {
   std::unique_ptr<internal::LifetimeSafetyAnalysis> Analysis =
       std::make_unique<internal::LifetimeSafetyAnalysis>(AC, Reporter);
   Analysis->run();
-  return Analysis;
+  for (const auto &[expr, count] :
+       Analysis->getFactManager().getOriginMgr().getMissingOrigins()) {
+    Stats.MissingOriginCount[expr] += count;
+  }
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 77d2013ff3a93..e2ad6eb209059 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3069,11 +3069,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
-      std::unique_ptr<clang::lifetimes::internal::LifetimeSafetyAnalysis>
-          Analysis =
-              lifetimes::runLifetimeSafetyAnalysis(AC, 
&LifetimeSafetyReporter);
-      if (S.CollectStats)
-        FindMissingOrigins(AC, Analysis->getFactManager());
+      lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter, 
LSStats,
+                                           S.CollectStats);
     }
   }
   // Check for violations of "called once" parameter properties.
@@ -3139,26 +3136,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   }
 }
 
-void clang::sema::AnalysisBasedWarnings::FindMissingOrigins(
-    AnalysisDeclContext &AC, lifetimes::internal::FactManager &FactMgr) {
-  if (AC.getCFG()) {
-    for (const auto &[expr, count] :
-         FactMgr.getOriginMgr().getMissingOrigins()) {
-      MissingOriginCount[expr] += count;
-    }
-  }
-}
-
 void clang::sema::AnalysisBasedWarnings::PrintStats() const {
-  llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
-                  "(expression_type : count) :\n\n";
-  unsigned totalMissingOrigins = 0;
-  for (const auto &[expr, count] : MissingOriginCount) {
-    llvm::errs() << expr << " : " << count << '\n';
-    totalMissingOrigins += count;
-  }
-  llvm::errs() << "Total missing origins: " << totalMissingOrigins << "\n";
-  llvm::errs() << "\n****************************************\n";
+
+  clang::lifetimes::PrintStats(LSStats);
   llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
   unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
   unsigned AvgCFGBlocksPerFunction =

>From 83417784cd7c3870bf82fef500be01db79eaef6f Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 26 Nov 2025 05:32:39 +0000
Subject: [PATCH 4/8] Moving the missing origin calculation logic after
 lifetime analysis using an AST visitor

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 20 +++---
 .../Analyses/LifetimeSafety/Origins.h         | 28 +++++++-
 .../clang/Sema/AnalysisBasedWarnings.h        |  4 +-
 .../LifetimeSafety/LifetimeSafety.cpp         | 17 +++--
 clang/lib/Analysis/LifetimeSafety/Origins.cpp | 70 +++++++++++++++----
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  3 +-
 6 files changed, 112 insertions(+), 30 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index cbbaa6e1884ee..6c091fa6f6d6b 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -54,7 +54,19 @@ class LifetimeSafetyReporter {
                                   Confidence Confidence) {}
 };
 
+// utility function to print missing origin stats.
+void printStats(const LifetimeSafetyStats &Stats);
+
+/// The main entry point for the analysis.
+void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
+                               LifetimeSafetyReporter *Reporter,
+                               LifetimeSafetyStats &Stats, bool CollectStats);
+
 namespace internal {
+
+void collectLifetimeStats(AnalysisDeclContext &AC, OriginManager &OM,
+                          LifetimeSafetyStats &Stats);
+
 /// An object to hold the factories for immutable collections, ensuring
 /// that all created states share the same underlying memory management.
 struct LifetimeFactory {
@@ -90,14 +102,6 @@ class LifetimeSafetyAnalysis {
 };
 } // namespace internal
 
-// utility function to print missing origin stats.
-void PrintStats(const LifetimeSafetyStats &Stats);
-
-/// The main entry point for the analysis.
-void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter,
-                               LifetimeSafetyStats &Stats, bool CollectStats);
-
 } // namespace clang::lifetimes
 
 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
index 5c0c73f9b321c..baf9bb9be8439 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
@@ -16,11 +16,17 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeBase.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/raw_ostream.h"
 
+namespace clang::lifetimes {
+
+struct LifetimeSafetyStats;
+} // namespace clang::lifetimes
+
 namespace clang::lifetimes::internal {
 
 using OriginID = utils::ID<struct OriginTag>;
@@ -81,7 +87,10 @@ class OriginManager {
 
   void dump(OriginID OID, llvm::raw_ostream &OS) const;
 
-  const llvm::StringMap<unsigned> getMissingOrigins() const;
+  const llvm::DenseMap<const clang::Expr *, OriginID> &
+  getExprToOriginId() const;
+
+  void collectMissingOrigins(Stmt *FunctionBody, LifetimeSafetyStats &LSStats);
 
 private:
   OriginID getNextOriginID() { return NextOriginID++; }
@@ -92,8 +101,23 @@ class OriginManager {
   llvm::SmallVector<Origin> AllOrigins;
   llvm::DenseMap<const clang::ValueDecl *, OriginID> DeclToOriginID;
   llvm::DenseMap<const clang::Expr *, OriginID> ExprToOriginID;
-  llvm::StringMap<unsigned> ExprTypeToMissingOriginCount;
 };
+
+/// An utility class to traverse the function body in the analysis
+/// context and collect the count of expressions with missing origins.
+class MissingOriginCollector
+    : public RecursiveASTVisitor<MissingOriginCollector> {
+public:
+  MissingOriginCollector(const OriginManager &om,
+                         llvm::StringMap<unsigned> &MissingOriginCount)
+      : OM(om), MissingOriginCount(MissingOriginCount) {}
+  bool VisitExpr(Expr *E);
+
+private:
+  const OriginManager &OM;
+  llvm::StringMap<unsigned> &MissingOriginCount;
+};
+
 } // namespace clang::lifetimes::internal
 
 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_ORIGINS_H
diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h 
b/clang/include/clang/Sema/AnalysisBasedWarnings.h
index 221ee60483546..d17486a66b297 100644
--- a/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -105,7 +105,9 @@ class AnalysisBasedWarnings {
   /// a single function.
   unsigned MaxUninitAnalysisBlockVisitsPerFunction;
 
-  /// Map from expressions missing origin in OriginManager to their counts.
+  /// Statistics collected during lifetime safety analysis.
+  /// These are accumulated across all analyzed functions and printed
+  /// when -print-stats is enabled.
   clang::lifetimes::LifetimeSafetyStats LSStats;
 
   /// @}
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index b38640b1c0642..cc0acbd42df39 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -20,6 +20,7 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -70,9 +71,17 @@ void LifetimeSafetyAnalysis::run() {
 
   runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter);
 }
+
+void collectLifetimeStats(AnalysisDeclContext &AC, OriginManager &OM,
+                          LifetimeSafetyStats &Stats) {
+  if (!AC.getBody())
+    return;
+  Stmt *FunctionBody = AC.getBody();
+  OM.collectMissingOrigins(FunctionBody, Stats);
+}
 } // namespace internal
 
-void PrintStats(const LifetimeSafetyStats &Stats) {
+void printStats(const LifetimeSafetyStats &Stats) {
   llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
                   "(expression_type : count) :\n\n";
   unsigned totalMissingOrigins = 0;
@@ -90,9 +99,7 @@ void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
   std::unique_ptr<internal::LifetimeSafetyAnalysis> Analysis =
       std::make_unique<internal::LifetimeSafetyAnalysis>(AC, Reporter);
   Analysis->run();
-  for (const auto &[expr, count] :
-       Analysis->getFactManager().getOriginMgr().getMissingOrigins()) {
-    Stats.MissingOriginCount[expr] += count;
-  }
+  if (CollectStats)
+    collectLifetimeStats(AC, Analysis->getFactManager().getOriginMgr(), Stats);
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 96750d9f94990..0f0b20305fbf2 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -9,10 +9,31 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/TypeBase.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
 #include "llvm/ADT/StringMap.h"
 
 namespace clang::lifetimes::internal {
 
+static bool isGslPointerType(QualType QT) {
+  if (const auto *RD = QT->getAsCXXRecordDecl()) {
+    // We need to check the template definition for specializations.
+    if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+      return CTSD->getSpecializedTemplate()
+          ->getTemplatedDecl()
+          ->hasAttr<PointerAttr>();
+    return RD->hasAttr<PointerAttr>();
+  }
+  return false;
+}
+
+static bool isPointerType(QualType QT) {
+  return QT->isPointerOrReferenceType() || isGslPointerType(QT);
+}
+// Check if a type has an origin.
+static bool hasOrigin(const Expr *E) {
+  return E->isGLValue() || isPointerType(E->getType());
+}
+
 void OriginManager::dump(OriginID OID, llvm::raw_ostream &OS) const {
   OS << OID << " (";
   Origin O = getOrigin(OID);
@@ -25,10 +46,6 @@ void OriginManager::dump(OriginID OID, llvm::raw_ostream 
&OS) const {
   OS << ")";
 }
 
-const llvm::StringMap<unsigned> OriginManager::getMissingOrigins() const {
-  return ExprTypeToMissingOriginCount;
-}
-
 Origin &OriginManager::addOrigin(OriginID ID, const clang::ValueDecl &D) {
   AllOrigins.emplace_back(ID, &D);
   return AllOrigins.back();
@@ -49,14 +66,14 @@ OriginID OriginManager::get(const Expr &E) {
 
   // if the expression has no specific origin, increment the missing origin
   // counter.
-  std::string ExprStr(E.getStmtClassName());
-  ExprStr = ExprStr + "<" + E.getType().getAsString() + ">";
-  auto CountIt = ExprTypeToMissingOriginCount.find(ExprStr);
-  if (CountIt == ExprTypeToMissingOriginCount.end()) {
-    ExprTypeToMissingOriginCount[ExprStr] = 1;
-  } else {
-    CountIt->second++;
-  }
+  // std::string ExprStr(E.getStmtClassName());
+  // ExprStr = ExprStr + "<" + E.getType().getAsString() + ">";
+  // auto CountIt = ExprTypeToMissingOriginCount.find(ExprStr);
+  // if (CountIt == ExprTypeToMissingOriginCount.end())
+  //   ExprTypeToMissingOriginCount[ExprStr] = 1;
+  // else
+  //   CountIt->second++;
+
   // If the expression itself has no specific origin, and it's a reference
   // to a declaration, its origin is that of the declaration it refers to.
   // For pointer types, where we don't pre-emptively create an origin for the
@@ -106,4 +123,33 @@ OriginID OriginManager::getOrCreate(const ValueDecl &D) {
   return NewID;
 }
 
+const llvm::DenseMap<const clang::Expr *, OriginID> &
+OriginManager::getExprToOriginId() const {
+  return ExprToOriginID;
+}
+
+void OriginManager::collectMissingOrigins(Stmt *FunctionBody,
+                                          LifetimeSafetyStats &LSStats) {
+  if (!FunctionBody)
+    return;
+
+  MissingOriginCollector Collector(*this, LSStats.MissingOriginCount);
+  Collector.TraverseStmt(const_cast<Stmt *>(FunctionBody));
+}
+
+bool MissingOriginCollector::VisitExpr(Expr *E) {
+  if (!hasOrigin(E))
+    return true;
+  // Check if we have an origin for this expression
+  const auto &ExprToOriginId = OM.getExprToOriginId();
+  auto It = ExprToOriginId.find(E);
+  if (It == ExprToOriginId.end()) {
+    // No origin found - count this as missing
+    std::string ExprStr = std::string(E->getStmtClassName()) + "<" +
+                          E->getType().getAsString() + ">";
+    MissingOriginCount[ExprStr]++;
+  }
+  return true;
+}
+
 } // namespace clang::lifetimes::internal
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 2ad2684c7f292..ae549f6b4f877 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -54,7 +54,6 @@
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -3165,7 +3164,6 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
 
 void clang::sema::AnalysisBasedWarnings::PrintStats() const {
 
-  clang::lifetimes::PrintStats(LSStats);
   llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
   unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
   unsigned AvgCFGBlocksPerFunction =
@@ -3194,4 +3192,5 @@ void clang::sema::AnalysisBasedWarnings::PrintStats() 
const {
                << " average block visits per function.\n"
                << "  " << MaxUninitAnalysisBlockVisitsPerFunction
                << " max block visits per function.\n";
+  clang::lifetimes::printStats(LSStats);
 }

>From 56b2dd9315a686e6aa05e9afc353100f02ded2be Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 26 Nov 2025 05:36:55 +0000
Subject: [PATCH 5/8] Removing an outdated comment

---
 clang/lib/Analysis/LifetimeSafety/Origins.cpp | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 0f0b20305fbf2..03efc27e9d959 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -64,16 +64,6 @@ OriginID OriginManager::get(const Expr &E) {
   if (It != ExprToOriginID.end())
     return It->second;
 
-  // if the expression has no specific origin, increment the missing origin
-  // counter.
-  // std::string ExprStr(E.getStmtClassName());
-  // ExprStr = ExprStr + "<" + E.getType().getAsString() + ">";
-  // auto CountIt = ExprTypeToMissingOriginCount.find(ExprStr);
-  // if (CountIt == ExprTypeToMissingOriginCount.end())
-  //   ExprTypeToMissingOriginCount[ExprStr] = 1;
-  // else
-  //   CountIt->second++;
-
   // If the expression itself has no specific origin, and it's a reference
   // to a declaration, its origin is that of the declaration it refers to.
   // For pointer types, where we don't pre-emptively create an origin for the

>From 0ca0f5876e2a9a6184e729d0de5b7bc4b2bbf311 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Thu, 27 Nov 2025 06:14:25 +0000
Subject: [PATCH 6/8] Made MissingOriginCollector internal to Origins.cpp

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  |  5 +-
 .../Analyses/LifetimeSafety/Origins.h         | 20 +------
 .../LifetimeSafety/LifetimeSafety.cpp         | 13 ++---
 clang/lib/Analysis/LifetimeSafety/Origins.cpp | 55 +++++++++++--------
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  3 -
 5 files changed, 43 insertions(+), 53 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index cb11bbe863c0a..06f1a093233fa 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -39,8 +39,10 @@ enum class Confidence : uint8_t {
 };
 
 /// A structure to hold the statistics related to LifetimeAnalysis.
-/// Curently it holds only the missing origin details.
+/// Currently it holds only the missing origin details.
 struct LifetimeSafetyStats {
+  /// A map from `ExpressionClassName<QualType>` to their missing origin
+  /// counts.
   llvm::StringMap<unsigned> MissingOriginCount;
 };
 
@@ -106,7 +108,6 @@ class LifetimeSafetyAnalysis {
   std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
 };
 } // namespace internal
-
 } // namespace clang::lifetimes
 
 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
index baf9bb9be8439..05a19def04d96 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
@@ -87,9 +87,7 @@ class OriginManager {
 
   void dump(OriginID OID, llvm::raw_ostream &OS) const;
 
-  const llvm::DenseMap<const clang::Expr *, OriginID> &
-  getExprToOriginId() const;
-
+  /// Collects statistics about expressions that lack associated origins.
   void collectMissingOrigins(Stmt *FunctionBody, LifetimeSafetyStats &LSStats);
 
 private:
@@ -102,22 +100,6 @@ class OriginManager {
   llvm::DenseMap<const clang::ValueDecl *, OriginID> DeclToOriginID;
   llvm::DenseMap<const clang::Expr *, OriginID> ExprToOriginID;
 };
-
-/// An utility class to traverse the function body in the analysis
-/// context and collect the count of expressions with missing origins.
-class MissingOriginCollector
-    : public RecursiveASTVisitor<MissingOriginCollector> {
-public:
-  MissingOriginCollector(const OriginManager &om,
-                         llvm::StringMap<unsigned> &MissingOriginCount)
-      : OM(om), MissingOriginCount(MissingOriginCount) {}
-  bool VisitExpr(Expr *E);
-
-private:
-  const OriginManager &OM;
-  llvm::StringMap<unsigned> &MissingOriginCount;
-};
-
 } // namespace clang::lifetimes::internal
 
 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_ORIGINS_H
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index cc0acbd42df39..e1f016b9d58a4 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -84,22 +84,21 @@ void collectLifetimeStats(AnalysisDeclContext &AC, 
OriginManager &OM,
 void printStats(const LifetimeSafetyStats &Stats) {
   llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
                   "(expression_type : count) :\n\n";
-  unsigned totalMissingOrigins = 0;
+  unsigned TotalMissingOrigins = 0;
   for (const auto &[expr, count] : Stats.MissingOriginCount) {
     llvm::errs() << expr << " : " << count << '\n';
-    totalMissingOrigins += count;
+    TotalMissingOrigins += count;
   }
-  llvm::errs() << "Total missing origins: " << totalMissingOrigins << "\n";
+  llvm::errs() << "Total missing origins: " << TotalMissingOrigins << "\n";
   llvm::errs() << "\n****************************************\n";
 }
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
                                LifetimeSafetyStats &Stats, bool CollectStats) {
-  std::unique_ptr<internal::LifetimeSafetyAnalysis> Analysis =
-      std::make_unique<internal::LifetimeSafetyAnalysis>(AC, Reporter);
-  Analysis->run();
+  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
+  Analysis.run();
   if (CollectStats)
-    collectLifetimeStats(AC, Analysis->getFactManager().getOriginMgr(), Stats);
+    collectLifetimeStats(AC, Analysis.getFactManager().getOriginMgr(), Stats);
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 03efc27e9d959..ece6535880fe9 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -34,6 +34,37 @@ static bool hasOrigin(const Expr *E) {
   return E->isGLValue() || isPointerType(E->getType());
 }
 
+namespace {
+/// An utility class to traverse the function body in the analysis
+/// context and collect the count of expressions with missing origins.
+class MissingOriginCollector
+    : public RecursiveASTVisitor<MissingOriginCollector> {
+public:
+  MissingOriginCollector(
+      const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId,
+      llvm::StringMap<unsigned> &MissingOriginCount)
+      : ExprToOriginId(ExprToOriginId), MissingOriginCount(MissingOriginCount) 
{
+  }
+  bool VisitExpr(Expr *E) {
+    if (!hasOrigin(E))
+      return true;
+    // Check if we have an origin for this expression.
+    auto It = this->ExprToOriginId.find(E);
+    if (It == this->ExprToOriginId.end()) {
+      // No origin found: count this as missing origin.
+      std::string ExprStr = std::string(E->getStmtClassName()) +
+                            " (Type: " + E->getType().getAsString() + ")";
+      MissingOriginCount[ExprStr]++;
+    }
+    return true;
+  }
+
+private:
+  const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId;
+  llvm::StringMap<unsigned> &MissingOriginCount;
+};
+} // namespace
+
 void OriginManager::dump(OriginID OID, llvm::raw_ostream &OS) const {
   OS << OID << " (";
   Origin O = getOrigin(OID);
@@ -63,7 +94,6 @@ OriginID OriginManager::get(const Expr &E) {
   auto It = ExprToOriginID.find(&E);
   if (It != ExprToOriginID.end())
     return It->second;
-
   // If the expression itself has no specific origin, and it's a reference
   // to a declaration, its origin is that of the declaration it refers to.
   // For pointer types, where we don't pre-emptively create an origin for the
@@ -113,33 +143,14 @@ OriginID OriginManager::getOrCreate(const ValueDecl &D) {
   return NewID;
 }
 
-const llvm::DenseMap<const clang::Expr *, OriginID> &
-OriginManager::getExprToOriginId() const {
-  return ExprToOriginID;
-}
-
 void OriginManager::collectMissingOrigins(Stmt *FunctionBody,
                                           LifetimeSafetyStats &LSStats) {
   if (!FunctionBody)
     return;
 
-  MissingOriginCollector Collector(*this, LSStats.MissingOriginCount);
+  MissingOriginCollector Collector(this->ExprToOriginID,
+                                   LSStats.MissingOriginCount);
   Collector.TraverseStmt(const_cast<Stmt *>(FunctionBody));
 }
 
-bool MissingOriginCollector::VisitExpr(Expr *E) {
-  if (!hasOrigin(E))
-    return true;
-  // Check if we have an origin for this expression
-  const auto &ExprToOriginId = OM.getExprToOriginId();
-  auto It = ExprToOriginId.find(E);
-  if (It == ExprToOriginId.end()) {
-    // No origin found - count this as missing
-    std::string ExprStr = std::string(E->getStmtClassName()) + "<" +
-                          E->getType().getAsString() + ">";
-    MissingOriginCount[ExprStr]++;
-  }
-  return true;
-}
-
 } // namespace clang::lifetimes::internal
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 9188b87e7faa9..4e0b75ef2d8ed 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -29,9 +29,7 @@
 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
 #include "clang/Analysis/Analyses/CalledOnceCheck.h"
 #include "clang/Analysis/Analyses/Consumed.h"
-#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
-#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/Analyses/ReachableCode.h"
 #include "clang/Analysis/Analyses/ThreadSafety.h"
 #include "clang/Analysis/Analyses/UninitializedValues.h"
@@ -49,7 +47,6 @@
 #include "clang/Sema/SemaInternal.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"

>From a30fa2e3003d2cb7120e8bd298c6acfb1ad0ece8 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Thu, 27 Nov 2025 09:20:59 +0000
Subject: [PATCH 7/8] Introducing a dedicated file for LifetimeSafetyStats and
 changing the report format.

instead of using ExprClassName<QualType> it will be shown in the following way:

```
*** LifetimeSafety Missing Origin Stats (expression_type : count) :

UnaryOperator (Type: const value_type) : 1
BinaryOperator (Type: char *) : 3
CXXOperatorCallExpr (Type: const value_type) : 2
CXXMemberCallExpr (Type: basic_string_view<char>) : 1
DeclRefExpr (Type: char *) : 9
CXXMemberCallExpr (Type: const_iterator) : 1
CXXOperatorCallExpr (Type: class std::basic_string<char>) : 1
DeclRefExpr (Type: std::string_view) : 27
CXXOperatorCallExpr (Type: basic_string<char>) : 3
Total missing origins: 48
```
---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 13 +-------
 .../Analyses/LifetimeSafety/LifetimeStats.h   | 33 +++++++++++++++++++
 .../Analyses/LifetimeSafety/Origins.h         |  8 +----
 .../clang/Sema/AnalysisBasedWarnings.h        |  4 +--
 .../Analysis/LifetimeSafety/CMakeLists.txt    |  1 +
 .../LifetimeSafety/LifetimeSafety.cpp         | 15 +--------
 .../Analysis/LifetimeSafety/LifetimeStats.cpp | 30 +++++++++++++++++
 clang/lib/Analysis/LifetimeSafety/Origins.cpp | 24 ++++----------
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  2 +-
 9 files changed, 75 insertions(+), 55 deletions(-)
 create mode 100644 
clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h
 create mode 100644 clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 06f1a093233fa..7c0744ec007c5 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -21,11 +21,11 @@
 #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
 
 #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/raw_ostream.h"
 #include <string>
 
@@ -38,14 +38,6 @@ enum class Confidence : uint8_t {
   Definite // Reported as a definite error (-Wlifetime-safety-permissive)
 };
 
-/// A structure to hold the statistics related to LifetimeAnalysis.
-/// Currently it holds only the missing origin details.
-struct LifetimeSafetyStats {
-  /// A map from `ExpressionClassName<QualType>` to their missing origin
-  /// counts.
-  llvm::StringMap<unsigned> MissingOriginCount;
-};
-
 class LifetimeSafetyReporter {
 public:
   LifetimeSafetyReporter() = default;
@@ -61,9 +53,6 @@ class LifetimeSafetyReporter {
                                     Confidence Confidence) {}
 };
 
-// utility function to print missing origin stats.
-void printStats(const LifetimeSafetyStats &Stats);
-
 /// The main entry point for the analysis.
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h
new file mode 100644
index 0000000000000..1f8fcc3fa68e0
--- /dev/null
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h
@@ -0,0 +1,33 @@
+//===- LifetimeStats.h - Miscellaneous statistics related to lifetime safety
+//analysis ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------------------------------===//
+//
+// This file declares the data structures and utility function for collection 
of
+// staticstics related to Lifetimesafety analysis.
+//
+//===----------------------------------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
+
+#include "llvm/ADT/StringMap.h"
+
+namespace clang::lifetimes {
+/// A structure to hold the statistics related to LifetimeAnalysis.
+/// Currently it holds only the missing origin details.
+struct LifetimeSafetyStats {
+  /// A map from `ExpressionClassName<QualType>` to their missing origin
+  /// counts.
+  llvm::StringMap<unsigned> MissingOriginCount;
+};
+
+// utility function to print missing origin stats.
+void printStats(const LifetimeSafetyStats &Stats);
+} // namespace clang::lifetimes
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
\ No newline at end of file
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
index 05a19def04d96..8e3a4ac3554f1 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
@@ -16,17 +16,11 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeBase.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/raw_ostream.h"
 
-namespace clang::lifetimes {
-
-struct LifetimeSafetyStats;
-} // namespace clang::lifetimes
-
 namespace clang::lifetimes::internal {
 
 using OriginID = utils::ID<struct OriginTag>;
diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h 
b/clang/include/clang/Sema/AnalysisBasedWarnings.h
index d17486a66b297..126e32a857ced 100644
--- a/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -16,11 +16,9 @@
 #include "clang/AST/Decl.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Sema/ScopeInfo.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/StringMap.h"
 #include <memory>
 
 namespace clang {
diff --git a/clang/lib/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/lib/Analysis/LifetimeSafety/CMakeLists.txt
index 5874e8405baf6..e5876e747610a 100644
--- a/clang/lib/Analysis/LifetimeSafety/CMakeLists.txt
+++ b/clang/lib/Analysis/LifetimeSafety/CMakeLists.txt
@@ -5,6 +5,7 @@ add_clang_library(clangAnalysisLifetimeSafety
   LifetimeAnnotations.cpp
   LifetimeSafety.cpp
   LiveOrigins.cpp
+  LifetimeStats.cpp
   Loans.cpp
   LoanPropagation.cpp
   Origins.cpp
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index e1f016b9d58a4..68f8492e70aea 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -18,17 +18,16 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/Checker.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
 #include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/TimeProfiler.h"
-#include "llvm/Support/raw_ostream.h"
 #include <memory>
 
 namespace clang::lifetimes {
@@ -81,18 +80,6 @@ void collectLifetimeStats(AnalysisDeclContext &AC, 
OriginManager &OM,
 }
 } // namespace internal
 
-void printStats(const LifetimeSafetyStats &Stats) {
-  llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
-                  "(expression_type : count) :\n\n";
-  unsigned TotalMissingOrigins = 0;
-  for (const auto &[expr, count] : Stats.MissingOriginCount) {
-    llvm::errs() << expr << " : " << count << '\n';
-    TotalMissingOrigins += count;
-  }
-  llvm::errs() << "Total missing origins: " << TotalMissingOrigins << "\n";
-  llvm::errs() << "\n****************************************\n";
-}
-
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
                                LifetimeSafetyStats &Stats, bool CollectStats) {
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp
new file mode 100644
index 0000000000000..dae2294e58564
--- /dev/null
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp
@@ -0,0 +1,30 @@
+//===- LifetimeStats.cpp - Miscellaneous statistics related to C++ Lifetime
+//Safety analysis -*--------- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the data structures and utility function for collection of
+// staticstics related to Lifetimesafety analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::lifetimes {
+void printStats(const LifetimeSafetyStats &Stats) {
+  llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
+                  "(expression_type : count) :\n\n";
+  unsigned TotalMissingOrigins = 0;
+  for (const auto &[expr, count] : Stats.MissingOriginCount) {
+    llvm::errs() << expr << " : " << count << '\n';
+    TotalMissingOrigins += count;
+  }
+  llvm::errs() << "Total missing origins: " << TotalMissingOrigins << "\n";
+  llvm::errs() << "\n****************************************\n";
+}
+} // namespace clang::lifetimes
\ No newline at end of file
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index ece6535880fe9..b9759ea40b623 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -8,33 +8,21 @@
 
 #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeBase.h"
-#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
 #include "llvm/ADT/StringMap.h"
 
 namespace clang::lifetimes::internal {
-
-static bool isGslPointerType(QualType QT) {
-  if (const auto *RD = QT->getAsCXXRecordDecl()) {
-    // We need to check the template definition for specializations.
-    if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
-      return CTSD->getSpecializedTemplate()
-          ->getTemplatedDecl()
-          ->hasAttr<PointerAttr>();
-    return RD->hasAttr<PointerAttr>();
-  }
-  return false;
-}
-
-static bool isPointerType(QualType QT) {
+namespace {
+bool isPointerType(QualType QT) {
   return QT->isPointerOrReferenceType() || isGslPointerType(QT);
 }
 // Check if a type has an origin.
-static bool hasOrigin(const Expr *E) {
+bool hasOrigin(const Expr *E) {
   return E->isGLValue() || isPointerType(E->getType());
 }
-
-namespace {
 /// An utility class to traverse the function body in the analysis
 /// context and collect the count of expressions with missing origins.
 class MissingOriginCollector
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 4e0b75ef2d8ed..27e67c69eccc6 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3175,8 +3175,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
 }
 
 void clang::sema::AnalysisBasedWarnings::PrintStats() const {
-
   llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
+
   unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
   unsigned AvgCFGBlocksPerFunction =
       !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;

>From 82648094e153a0a1640d3f7e877c062755e94d72 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Fri, 28 Nov 2025 17:35:13 +0000
Subject: [PATCH 8/8] Separating the StmtClassName and QualType for missing
 origin counts and putting them in separate maps

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  |  1 -
 .../Analyses/LifetimeSafety/LifetimeStats.h   | 23 +++++++++---------
 .../Analysis/LifetimeSafety/LifetimeStats.cpp | 20 +++++++++-------
 clang/lib/Analysis/LifetimeSafety/Origins.cpp | 24 ++++++++++---------
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  2 +-
 5 files changed, 38 insertions(+), 32 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 7c0744ec007c5..2351635a8fd6d 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -74,7 +74,6 @@ struct LifetimeFactory {
 /// Running the lifetime safety analysis and querying its results. It
 /// encapsulates the various dataflow analyses.
 class LifetimeSafetyAnalysis {
-
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                          LifetimeSafetyReporter *Reporter);
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h
index 1f8fcc3fa68e0..670436e3e3b5f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h
@@ -1,16 +1,15 @@
-//===- LifetimeStats.h - Miscellaneous statistics related to lifetime safety
-//analysis ---*- C++ -*-===//
+//===- LifetimeStats.h - Lifetime Safety Statistics --------------*- C++-* 
-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
-//===----------------------------------------------------------------------------------------------===//
+//===------------------------------------------------------------------------===//
 //
 // This file declares the data structures and utility function for collection 
of
-// staticstics related to Lifetimesafety analysis.
+// statistics related to Lifetime Safety analysis.
 //
-//===----------------------------------------------------------------------------------------------===//
+//===------------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
 #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
@@ -19,15 +18,17 @@
 
 namespace clang::lifetimes {
 /// A structure to hold the statistics related to LifetimeAnalysis.
-/// Currently it holds only the missing origin details.
+/// These are accumulated across all analyzed functions and printed
+/// when -print-stats is enabled.
 struct LifetimeSafetyStats {
-  /// A map from `ExpressionClassName<QualType>` to their missing origin
-  /// counts.
-  llvm::StringMap<unsigned> MissingOriginCount;
+  /// A map from `QualType` to their missing origin counts.
+  llvm::StringMap<unsigned> ExprStmtClassToMissingOriginCount;
+  /// A map from `StmtClassName` to their missing origin counts.
+  llvm::StringMap<unsigned> ExprTypeToMissingOriginCount;
 };
 
-// utility function to print missing origin stats.
+/// Utility function to print missing origin stats.
 void printStats(const LifetimeSafetyStats &Stats);
 } // namespace clang::lifetimes
 
-#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
\ No newline at end of file
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp
index dae2294e58564..69f24e1161e62 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp
@@ -1,5 +1,4 @@
-//===- LifetimeStats.cpp - Miscellaneous statistics related to C++ Lifetime
-//Safety analysis -*--------- C++-*-===//
+//===- LifetimeStats.cpp - Lifetime Safety Statistics -*------------ 
C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -17,14 +16,19 @@
 
 namespace clang::lifetimes {
 void printStats(const LifetimeSafetyStats &Stats) {
-  llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
-                  "(expression_type : count) :\n\n";
+  llvm::errs() << "\n*** LifetimeSafety Missing Origin per QualType: "
+                  "(QualType : count) :\n\n";
   unsigned TotalMissingOrigins = 0;
-  for (const auto &[expr, count] : Stats.MissingOriginCount) {
-    llvm::errs() << expr << " : " << count << '\n';
+  for (const auto &[type, count] : Stats.ExprTypeToMissingOriginCount) {
+    llvm::errs() << type << " : " << count << '\n';
     TotalMissingOrigins += count;
   }
-  llvm::errs() << "Total missing origins: " << TotalMissingOrigins << "\n";
+  llvm::errs() << "\n\n*** LifetimeSafety Missing Origin per StmtClassName: "
+                  "(StmtClassName : count) :\n\n";
+  for (const auto &[stmt, count] : Stats.ExprStmtClassToMissingOriginCount) {
+    llvm::errs() << stmt << " : " << count << '\n';
+  }
+  llvm::errs() << "\nTotal missing origins: " << TotalMissingOrigins << "\n";
   llvm::errs() << "\n****************************************\n";
 }
-} // namespace clang::lifetimes
\ No newline at end of file
+} // namespace clang::lifetimes
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index b9759ea40b623..c9d9cb7cad6e8 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -23,33 +23,34 @@ bool isPointerType(QualType QT) {
 bool hasOrigin(const Expr *E) {
   return E->isGLValue() || isPointerType(E->getType());
 }
-/// An utility class to traverse the function body in the analysis
+/// A utility class to traverse the function body in the analysis
 /// context and collect the count of expressions with missing origins.
 class MissingOriginCollector
     : public RecursiveASTVisitor<MissingOriginCollector> {
 public:
   MissingOriginCollector(
       const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId,
-      llvm::StringMap<unsigned> &MissingOriginCount)
-      : ExprToOriginId(ExprToOriginId), MissingOriginCount(MissingOriginCount) 
{
-  }
+      llvm::StringMap<unsigned> &ExprStmtClassToMissingOriginCount,
+      llvm::StringMap<unsigned> &ExprTypeToMissingOriginCount)
+      : ExprToOriginId(ExprToOriginId),
+        ExprStmtClassToMissingOriginCount(ExprStmtClassToMissingOriginCount),
+        ExprTypeToMissingOriginCount(ExprTypeToMissingOriginCount) {}
   bool VisitExpr(Expr *E) {
     if (!hasOrigin(E))
       return true;
     // Check if we have an origin for this expression.
-    auto It = this->ExprToOriginId.find(E);
-    if (It == this->ExprToOriginId.end()) {
+    if (!ExprToOriginId.contains(E)) {
       // No origin found: count this as missing origin.
-      std::string ExprStr = std::string(E->getStmtClassName()) +
-                            " (Type: " + E->getType().getAsString() + ")";
-      MissingOriginCount[ExprStr]++;
+      ExprTypeToMissingOriginCount[std::string(E->getType().getAsString())]++;
+      ExprStmtClassToMissingOriginCount[std::string(E->getStmtClassName())]++;
     }
     return true;
   }
 
 private:
   const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId;
-  llvm::StringMap<unsigned> &MissingOriginCount;
+  llvm::StringMap<unsigned> &ExprStmtClassToMissingOriginCount;
+  llvm::StringMap<unsigned> &ExprTypeToMissingOriginCount;
 };
 } // namespace
 
@@ -137,7 +138,8 @@ void OriginManager::collectMissingOrigins(Stmt 
*FunctionBody,
     return;
 
   MissingOriginCollector Collector(this->ExprToOriginID,
-                                   LSStats.MissingOriginCount);
+                                   LSStats.ExprStmtClassToMissingOriginCount,
+                                   LSStats.ExprTypeToMissingOriginCount);
   Collector.TraverseStmt(const_cast<Stmt *>(FunctionBody));
 }
 
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 27e67c69eccc6..ac3c9665887b9 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -47,12 +47,12 @@
 #include "clang/Sema/SemaInternal.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <deque>
 #include <iterator>

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

Reply via email to