https://github.com/kashika0112 updated 
https://github.com/llvm/llvm-project/pull/174178

>From f0c7f3d76972790470a867326fdbd7311c2c92f6 Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Fri, 2 Jan 2026 05:48:33 +0000
Subject: [PATCH 1/2] Add post-order analysis using call graph

---
 clang/include/clang/Basic/LangOptions.def     |  2 +
 clang/include/clang/Options/Options.td        |  9 ++
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 19 +++--
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 84 ++++++++++++++++++-
 .../Sema/warn-lifetime-safety-suggestions.cpp | 19 ++---
 5 files changed, 116 insertions(+), 17 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 8cba1dbaee24e..8b1f76a0a8382 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -505,6 +505,8 @@ LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, 
"Experimental lifetime safety
 
 LANGOPT(EnableLifetimeSafetyInference, 1, 0, NotCompatible, "Experimental 
lifetime safety inference analysis for C++")
 
+LANGOPT(EnableLifetimeSafetyInferencePostOrder, 1, 0, NotCompatible, 
"Experimental lifetime safety inference analysis in post-order for C++")
+
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
 #undef LANGOPT
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 04756ce486eaf..5bc3e6a6b1e7a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1972,6 +1972,15 @@ defm lifetime_safety_inference
                   BothFlags<[], [CC1Option],
                             " experimental lifetime safety inference for 
C++">>;
 
+defm lifetime_safety_inference_post_order
+    : BoolFOption<"experimental-lifetime-safety-inference-post-order",
+                  LangOpts<"EnableLifetimeSafetyInferencePostOrder">,
+                  DefaultFalse, PosFlag<SetTrue, [], [CC1Option], "Enable">,
+                  NegFlag<SetFalse, [], [CC1Option], "Disable">,
+                  BothFlags<[], [CC1Option],
+                            " experimental lifetime safety inference in "
+                            "post-order for C++">>;
+
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
   PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index ff2650be594f5..9d93c837495e5 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -194,16 +194,23 @@ class LifetimeChecker {
   }
 
   void inferAnnotations() {
-    // FIXME: To maximise inference propagation, functions should be analyzed 
in
-    // post-order of the call graph, allowing inferred annotations to propagate
-    // through the call chain
-    // FIXME: Add the inferred attribute to all redeclarations of the function,
-    // not just the definition being analyzed.
     for (const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
       ParmVarDecl *PVD = const_cast<ParmVarDecl *>(ConstPVD);
-      if (!PVD->hasAttr<LifetimeBoundAttr>())
+      if (!PVD->hasAttr<LifetimeBoundAttr>()) {
         PVD->addAttr(
             LifetimeBoundAttr::CreateImplicit(AST, PVD->getLocation()));
+        if (const FunctionDecl *FD =
+                dyn_cast<FunctionDecl>(PVD->getDeclContext())) {
+          for (const FunctionDecl *Redecl : FD->redecls()) {
+            if (Redecl != FD)
+              if (const ParmVarDecl *RedeclPVD =
+                      Redecl->getParamDecl(PVD->getFunctionScopeIndex());
+                  RedeclPVD)
+                const_cast<ParmVarDecl *>(RedeclPVD)->addAttr(
+                    LifetimeBoundAttr::CreateImplicit(AST, 
PVD->getLocation()));
+          }
+        }
+      }
     }
   }
 };
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 7b08648080710..85d3c5fb4caff 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -23,6 +23,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMap.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/Type.h"
@@ -36,6 +37,7 @@
 #include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CallGraph.h"
 #include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticSema.h"
@@ -48,6 +50,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -2915,6 +2918,43 @@ class LifetimeSafetyReporterImpl : public 
LifetimeSafetyReporter {
 } // namespace
 } // namespace clang::lifetimes
 
+class CallGraphBuilder : public clang::RecursiveASTVisitor<CallGraphBuilder> {
+  clang::CallGraph &CG;
+  clang::Sema &S;
+  clang::FunctionDecl *CurrentFD = nullptr;
+
+public:
+  explicit CallGraphBuilder(clang::CallGraph &CG, clang::Sema &S)
+      : CG(CG), S(S) {}
+
+  void addCallsFrom(clang::FunctionDecl *FD) {
+    CurrentFD = FD;
+    if (FD->hasBody())
+      TraverseStmt(FD->getBody());
+  }
+
+  // Visitor for call expressions.
+  bool VisitCallExpr(clang::CallExpr *CE) {
+    if (clang::FunctionDecl *CalleeFD = CE->getDirectCallee()) {
+      const clang::FunctionDecl *Def = nullptr;
+      if (CalleeFD->hasBody(Def) && Def) {
+        if (!S.getSourceManager().isInSystemHeader(Def->getLocation())) {
+          const FunctionDecl *CanonicalCaller = CurrentFD->getCanonicalDecl();
+          const FunctionDecl *CanonicalCallee = Def->getCanonicalDecl();
+
+          clang::CallGraphNode *CallerNode = CG.getOrInsertNode(
+              const_cast<clang::FunctionDecl *>(CanonicalCaller));
+          clang::CallGraphNode *CalleeNode = CG.getOrInsertNode(
+              const_cast<clang::FunctionDecl *>(CanonicalCallee));
+          // Add an edge from caller to callee.
+          CallerNode->addCallee({CalleeNode, CE});
+        }
+      }
+    }
+    return true;
+  }
+};
+
 void clang::sema::AnalysisBasedWarnings::IssueWarnings(
      TranslationUnitDecl *TU) {
   if (!TU)
@@ -2969,6 +3009,46 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
     CallableVisitor(CallAnalyzers, TU->getOwningModule())
         .TraverseTranslationUnitDecl(TU);
   }
+
+  if (S.getLangOpts().EnableLifetimeSafety && S.getLangOpts().CPlusPlus &&
+      S.getLangOpts().EnableLifetimeSafetyInferencePostOrder) {
+    llvm::SmallVector<const FunctionDecl *, 64> AllFunctions;
+    auto AddFunctionToList = [&](const Decl *D) -> void {
+      if (const auto *FD = dyn_cast<FunctionDecl>(D))
+        if (FD->doesThisDeclarationHaveABody() &&
+            !S.getSourceManager().isInSystemHeader(FD->getLocation()))
+          AllFunctions.push_back(FD);
+    };
+    CallableVisitor(AddFunctionToList, TU->getOwningModule())
+        .TraverseTranslationUnitDecl(TU);
+
+    if (AllFunctions.empty())
+      return;
+
+    clang::CallGraph CG;
+    for (const clang::FunctionDecl *FD : AllFunctions)
+      CG.getOrInsertNode(const_cast<clang::FunctionDecl *>(FD));
+
+    CallGraphBuilder Builder(CG, S);
+    for (const clang::FunctionDecl *FD : AllFunctions)
+      Builder.addCallsFrom(const_cast<clang::FunctionDecl *>(FD));
+
+    lifetimes::LifetimeSafetyReporterImpl Reporter(S);
+    for (auto *Node : llvm::post_order(&CG)) {
+      if (const clang::FunctionDecl *CanonicalFD =
+              dyn_cast_or_null<clang::FunctionDecl>(Node->getDecl())) {
+        const FunctionDecl *FD = CanonicalFD->getDefinition();
+        if (!FD)
+          continue;
+
+        AnalysisDeclContext AC(nullptr, FD);
+        AC.getCFGBuildOptions().PruneTriviallyFalseEdges = false;
+        AC.getCFGBuildOptions().AddLifetime = true;
+        AC.getCFGBuildOptions().setAllAlwaysAdd();
+        runLifetimeSafetyAnalysis(AC, &Reporter, LSStats, S.CollectStats);
+      }
+    }
+  }
 }
 
 void clang::sema::AnalysisBasedWarnings::IssueWarnings(
@@ -3015,7 +3095,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   AC.getCFGBuildOptions().AddCXXNewAllocator = false;
   AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
 
-  bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
+  bool EnableLifetimeSafetyAnalysis =
+      S.getLangOpts().EnableLifetimeSafety &&
+      !S.getLangOpts().EnableLifetimeSafetyInferencePostOrder;
 
   if (EnableLifetimeSafetyAnalysis)
     AC.getCFGBuildOptions().AddLifetime = true;
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 8a328dfbc8d9e..5aeb76e530bad 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -1,6 +1,6 @@
 // RUN: rm -rf %t
 // RUN: split-file %s %t
-// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-fexperimental-lifetime-safety-inference 
-Wexperimental-lifetime-safety-suggestions -Wexperimental-lifetime-safety 
-Wno-dangling -I%t -verify %t/test_source.cpp
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-fexperimental-lifetime-safety-inference 
-fexperimental-lifetime-safety-inference-post-order 
-Wexperimental-lifetime-safety-suggestions -Wexperimental-lifetime-safety 
-Wno-dangling -I%t -verify %t/test_source.cpp
 
 View definition_before_header(View a);
 
@@ -204,9 +204,8 @@ MyObj* return_pointer_by_func(MyObj* a) {         // 
expected-warning {{paramete
 namespace incorrect_order_inference_view {
 View return_view_callee(View a);
 
-// FIXME: No lifetime annotation suggestion when functions are not present in 
the callee-before-caller pattern
-View return_view_caller(View a) {
-  return return_view_callee(a);
+View return_view_caller(View a) {     // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
+  return return_view_callee(a);       // expected-note {{param returned here}}
 }
 
 View return_view_callee(View a) {     // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
@@ -218,8 +217,8 @@ namespace incorrect_order_inference_object {
 MyObj* return_object_callee(MyObj* a);
 
 // FIXME: No lifetime annotation suggestion warning when functions are not 
present in the callee-before-caller pattern
-MyObj* return_object_caller(MyObj* a) {
-  return return_object_callee(a);
+MyObj* return_object_caller(MyObj* a) {      // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}.
+  return return_object_callee(a);            // expected-note {{param returned 
here}}
 }
 
 MyObj* return_object_callee(MyObj* a) {      // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}.
@@ -268,14 +267,14 @@ T* template_identity(T* a) {            // 
expected-warning {{parameter in intra
 }
 
 template<typename T>
-T* template_caller(T* a) {
-  return template_identity(a);          // expected-note {{in instantiation of 
function template specialization 
'inference_with_templates::template_identity<MyObj>' requested here}}
+T* template_caller(T* a) {              // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
+  return template_identity(a);          // expected-note {{param returned 
here}}
 }
 
-// FIXME: Fails to detect UAR as template instantiations are deferred to the 
end of the Translation Unit.
 MyObj* test_template_inference_with_stack() {
   MyObj local_stack;
-  return template_caller(&local_stack); // expected-note {{in instantiation of 
function template specialization 
'inference_with_templates::template_caller<MyObj>' requested here}}             
                                 
+  return template_caller(&local_stack);   // expected-warning {{address of 
stack memory is returned later}}
+                                          // expected-note@-1 {{returned 
here}}                                       
 }
 } // namespace inference_with_templates
 

>From 025f643d7a7c451ef505daa5f0462ceaef4ba757 Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Wed, 7 Jan 2026 07:57:15 +0000
Subject: [PATCH 2/2] Use addToCallGraph istead of custom visitor

---
 clang/include/clang/Basic/LangOptions.def     |   3 +-
 clang/include/clang/Options/Options.td        |  13 +--
 clang/lib/Analysis/LifetimeSafety/Checker.cpp |  21 ++--
 .../LifetimeSafety/FactsGenerator.cpp         |  11 +-
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 101 +++++-------------
 .../Sema/warn-lifetime-safety-suggestions.cpp |   3 +-
 6 files changed, 50 insertions(+), 102 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 8b1f76a0a8382..36fec24638363 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -505,7 +505,8 @@ LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, 
"Experimental lifetime safety
 
 LANGOPT(EnableLifetimeSafetyInference, 1, 0, NotCompatible, "Experimental 
lifetime safety inference analysis for C++")
 
-LANGOPT(EnableLifetimeSafetyInferencePostOrder, 1, 0, NotCompatible, 
"Experimental lifetime safety inference analysis in post-order for C++")
+// TODO: Remove flag and default to end-of-TU analysis for lifetime safety 
after performance validation.
+LANGOPT(EnableLifetimeSafetyTUAnalysis, 1, 0, NotCompatible, "Experimental 
lifetime safety at translation-unit end, analyzing functions in call graph 
post-order for C++")
 
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 5bc3e6a6b1e7a..f4b6d176e168a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1972,14 +1972,15 @@ defm lifetime_safety_inference
                   BothFlags<[], [CC1Option],
                             " experimental lifetime safety inference for 
C++">>;
 
-defm lifetime_safety_inference_post_order
-    : BoolFOption<"experimental-lifetime-safety-inference-post-order",
-                  LangOpts<"EnableLifetimeSafetyInferencePostOrder">,
-                  DefaultFalse, PosFlag<SetTrue, [], [CC1Option], "Enable">,
+defm lifetime_safety_tu_analysis
+    : BoolFOption<"experimental-lifetime-safety-tu-analysis",
+                  LangOpts<"EnableLifetimeSafetyTUAnalysis">, DefaultFalse,
+                  PosFlag<SetTrue, [], [CC1Option], "Enable">,
                   NegFlag<SetFalse, [], [CC1Option], "Disable">,
                   BothFlags<[], [CC1Option],
-                            " experimental lifetime safety inference in "
-                            "post-order for C++">>;
+                            " run lifetime safety analysis at translation-unit 
"
+                            "end, analyzing functions in call graph post-order 
"
+                            "to best propagate inferred annotations">>;
 
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 9d93c837495e5..eebcfa8a90a3e 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -196,20 +196,15 @@ class LifetimeChecker {
   void inferAnnotations() {
     for (const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
       ParmVarDecl *PVD = const_cast<ParmVarDecl *>(ConstPVD);
-      if (!PVD->hasAttr<LifetimeBoundAttr>()) {
-        PVD->addAttr(
+      const auto *FD = dyn_cast<FunctionDecl>(PVD->getDeclContext());
+      if (!FD)
+        continue;
+      const FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
+      ParmVarDecl *CanonicalPVD = const_cast<ParmVarDecl *>(
+          CanonicalFD->getParamDecl(PVD->getFunctionScopeIndex()));
+      if (!CanonicalPVD->hasAttr<LifetimeBoundAttr>()) {
+        CanonicalPVD->addAttr(
             LifetimeBoundAttr::CreateImplicit(AST, PVD->getLocation()));
-        if (const FunctionDecl *FD =
-                dyn_cast<FunctionDecl>(PVD->getDeclContext())) {
-          for (const FunctionDecl *Redecl : FD->redecls()) {
-            if (Redecl != FD)
-              if (const ParmVarDecl *RedeclPVD =
-                      Redecl->getParamDecl(PVD->getFunctionScopeIndex());
-                  RedeclPVD)
-                const_cast<ParmVarDecl *>(RedeclPVD)->addAttr(
-                    LifetimeBoundAttr::CreateImplicit(AST, 
PVD->getLocation()));
-          }
-        }
       }
     }
   }
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp 
b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 6a213a71afe12..b9e0816092595 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -392,11 +392,12 @@ void FactsGenerator::handleFunctionCall(const Expr *Call,
                                         bool IsGslConstruction) {
   OriginList *CallList = getOriginsList(*Call);
   // Ignore functions returning values with no origin.
-  if (!FD || !CallList)
+  const FunctionDecl *CanonicalFD = FD ? FD->getCanonicalDecl() : nullptr;
+  if (!CanonicalFD || !CallList)
     return;
-  auto IsArgLifetimeBound = [FD](unsigned I) -> bool {
+  auto IsArgLifetimeBound = [CanonicalFD](unsigned I) -> bool {
     const ParmVarDecl *PVD = nullptr;
-    if (const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+    if (const auto *Method = dyn_cast<CXXMethodDecl>(CanonicalFD);
         Method && Method->isInstance()) {
       if (I == 0)
         // For the 'this' argument, the attribute is on the method itself.
@@ -405,9 +406,9 @@ void FactsGenerator::handleFunctionCall(const Expr *Call,
         // For explicit arguments, find the corresponding parameter
         // declaration.
         PVD = Method->getParamDecl(I - 1);
-    } else if (I < FD->getNumParams()) {
+    } else if (I < CanonicalFD->getNumParams()) {
       // For free functions or static methods.
-      PVD = FD->getParamDecl(I);
+      PVD = CanonicalFD->getParamDecl(I);
     }
     return PVD ? PVD->hasAttr<clang::LifetimeBoundAttr>() : false;
   };
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 85d3c5fb4caff..56d7db649afbe 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -23,7 +23,6 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/Type.h"
@@ -55,6 +54,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
 #include <algorithm>
 #include <deque>
 #include <iterator>
@@ -2918,42 +2918,29 @@ class LifetimeSafetyReporterImpl : public 
LifetimeSafetyReporter {
 } // namespace
 } // namespace clang::lifetimes
 
-class CallGraphBuilder : public clang::RecursiveASTVisitor<CallGraphBuilder> {
-  clang::CallGraph &CG;
-  clang::Sema &S;
-  clang::FunctionDecl *CurrentFD = nullptr;
-
-public:
-  explicit CallGraphBuilder(clang::CallGraph &CG, clang::Sema &S)
-      : CG(CG), S(S) {}
-
-  void addCallsFrom(clang::FunctionDecl *FD) {
-    CurrentFD = FD;
-    if (FD->hasBody())
-      TraverseStmt(FD->getBody());
-  }
-
-  // Visitor for call expressions.
-  bool VisitCallExpr(clang::CallExpr *CE) {
-    if (clang::FunctionDecl *CalleeFD = CE->getDirectCallee()) {
-      const clang::FunctionDecl *Def = nullptr;
-      if (CalleeFD->hasBody(Def) && Def) {
-        if (!S.getSourceManager().isInSystemHeader(Def->getLocation())) {
-          const FunctionDecl *CanonicalCaller = CurrentFD->getCanonicalDecl();
-          const FunctionDecl *CanonicalCallee = Def->getCanonicalDecl();
-
-          clang::CallGraphNode *CallerNode = CG.getOrInsertNode(
-              const_cast<clang::FunctionDecl *>(CanonicalCaller));
-          clang::CallGraphNode *CalleeNode = CG.getOrInsertNode(
-              const_cast<clang::FunctionDecl *>(CanonicalCallee));
-          // Add an edge from caller to callee.
-          CallerNode->addCallee({CalleeNode, CE});
-        }
-      }
-    }
-    return true;
+static void
+LifetimeSafetyTUAnalysis(Sema &S, TranslationUnitDecl *TU,
+                         clang::lifetimes::LifetimeSafetyStats &LSStats) {
+  llvm::TimeTraceScope TimeProfile("LifetimeSafetyTUAnalysis");
+  CallGraph CG;
+  CG.addToCallGraph(TU);
+  lifetimes::LifetimeSafetyReporterImpl Reporter(S);
+  for (auto *Node : llvm::post_order(&CG)) {
+    const clang::FunctionDecl *CanonicalFD =
+        dyn_cast_or_null<clang::FunctionDecl>(Node->getDecl());
+    if (!CanonicalFD)
+      continue;
+    const FunctionDecl *FD = CanonicalFD->getDefinition();
+    if (!FD)
+      continue;
+    AnalysisDeclContext AC(nullptr, FD);
+    AC.getCFGBuildOptions().PruneTriviallyFalseEdges = false;
+    AC.getCFGBuildOptions().AddLifetime = true;
+    AC.getCFGBuildOptions().setAllAlwaysAdd();
+    if (AC.getCFG())
+      runLifetimeSafetyAnalysis(AC, &Reporter, LSStats, S.CollectStats);
   }
-};
+}
 
 void clang::sema::AnalysisBasedWarnings::IssueWarnings(
      TranslationUnitDecl *TU) {
@@ -3011,44 +2998,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   }
 
   if (S.getLangOpts().EnableLifetimeSafety && S.getLangOpts().CPlusPlus &&
-      S.getLangOpts().EnableLifetimeSafetyInferencePostOrder) {
-    llvm::SmallVector<const FunctionDecl *, 64> AllFunctions;
-    auto AddFunctionToList = [&](const Decl *D) -> void {
-      if (const auto *FD = dyn_cast<FunctionDecl>(D))
-        if (FD->doesThisDeclarationHaveABody() &&
-            !S.getSourceManager().isInSystemHeader(FD->getLocation()))
-          AllFunctions.push_back(FD);
-    };
-    CallableVisitor(AddFunctionToList, TU->getOwningModule())
-        .TraverseTranslationUnitDecl(TU);
-
-    if (AllFunctions.empty())
-      return;
-
-    clang::CallGraph CG;
-    for (const clang::FunctionDecl *FD : AllFunctions)
-      CG.getOrInsertNode(const_cast<clang::FunctionDecl *>(FD));
-
-    CallGraphBuilder Builder(CG, S);
-    for (const clang::FunctionDecl *FD : AllFunctions)
-      Builder.addCallsFrom(const_cast<clang::FunctionDecl *>(FD));
-
-    lifetimes::LifetimeSafetyReporterImpl Reporter(S);
-    for (auto *Node : llvm::post_order(&CG)) {
-      if (const clang::FunctionDecl *CanonicalFD =
-              dyn_cast_or_null<clang::FunctionDecl>(Node->getDecl())) {
-        const FunctionDecl *FD = CanonicalFD->getDefinition();
-        if (!FD)
-          continue;
-
-        AnalysisDeclContext AC(nullptr, FD);
-        AC.getCFGBuildOptions().PruneTriviallyFalseEdges = false;
-        AC.getCFGBuildOptions().AddLifetime = true;
-        AC.getCFGBuildOptions().setAllAlwaysAdd();
-        runLifetimeSafetyAnalysis(AC, &Reporter, LSStats, S.CollectStats);
-      }
-    }
-  }
+      S.getLangOpts().EnableLifetimeSafetyTUAnalysis)
+    LifetimeSafetyTUAnalysis(S, TU, LSStats);
 }
 
 void clang::sema::AnalysisBasedWarnings::IssueWarnings(
@@ -3097,7 +3048,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
 
   bool EnableLifetimeSafetyAnalysis =
       S.getLangOpts().EnableLifetimeSafety &&
-      !S.getLangOpts().EnableLifetimeSafetyInferencePostOrder;
+      !S.getLangOpts().EnableLifetimeSafetyTUAnalysis;
 
   if (EnableLifetimeSafetyAnalysis)
     AC.getCFGBuildOptions().AddLifetime = true;
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 5aeb76e530bad..8e66a672273d5 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -1,6 +1,6 @@
 // RUN: rm -rf %t
 // RUN: split-file %s %t
-// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-fexperimental-lifetime-safety-inference 
-fexperimental-lifetime-safety-inference-post-order 
-Wexperimental-lifetime-safety-suggestions -Wexperimental-lifetime-safety 
-Wno-dangling -I%t -verify %t/test_source.cpp
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-fexperimental-lifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis 
-Wexperimental-lifetime-safety-suggestions -Wexperimental-lifetime-safety 
-Wno-dangling -I%t -verify %t/test_source.cpp
 
 View definition_before_header(View a);
 
@@ -216,7 +216,6 @@ View return_view_callee(View a) {     // expected-warning 
{{parameter in intra-T
 namespace incorrect_order_inference_object {
 MyObj* return_object_callee(MyObj* a);
 
-// FIXME: No lifetime annotation suggestion warning when functions are not 
present in the callee-before-caller pattern
 MyObj* return_object_caller(MyObj* a) {      // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}.
   return return_object_callee(a);            // expected-note {{param returned 
here}}
 }

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

Reply via email to