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
