https://github.com/suoyuan666 updated https://github.com/llvm/llvm-project/pull/208890
>From 9d667b1da7631efd70dcfa1723ff689d6b3a2948 Mon Sep 17 00:00:00 2001 From: Yuan Suo <[email protected]> Date: Sat, 11 Jul 2026 16:22:16 +0800 Subject: [PATCH 1/4] [LifetimeSafety] Use ImmutableList for buildOriginFlowChain DFS nodes This commit mainly address the suggestion in https://github.com/llvm/llvm-project/pull/204592#discussion_r3523582077 to use `ImmutableList` for the DFS nodes in `buildOriginFlowChain`, and also updates the unreachable messages. Signed-off-by: Yuan Suo <[email protected]> --- .../Analyses/LifetimeSafety/LoanPropagation.h | 23 +++++----- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 2 +- .../LifetimeSafety/LifetimeSafety.cpp | 5 ++- .../LifetimeSafety/LoanPropagation.cpp | 42 +++++++++++-------- clang/lib/Sema/SemaLifetimeSafety.h | 4 +- .../unittests/Analysis/LifetimeSafetyTest.cpp | 22 +++++----- 6 files changed, 56 insertions(+), 42 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h index 838daa024c953..3d489965a5aa6 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h @@ -18,6 +18,7 @@ #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableSet.h" @@ -31,9 +32,11 @@ using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>; class LoanPropagationAnalysis { public: - LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, - OriginLoanMap::Factory &OriginLoanMapFactory, - LoanSet::Factory &LoanSetFactory); + LoanPropagationAnalysis( + const CFG &C, AnalysisDeclContext &AC, FactManager &F, + OriginLoanMap::Factory &OriginLoanMapFactory, + LoanSet::Factory &LoanSetFactory, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory); ~LoanPropagationAnalysis(); LoanSet getLoans(OriginID OID, ProgramPoint P) const; @@ -47,14 +50,14 @@ class LoanPropagationAnalysis { /// The traversal follows OriginFlowFacts backwards to reconstruct the /// sequence of origins through which the loan flowed, ending at the origin /// where the loan was originally issued. - llvm::SmallVector<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, - const OriginID StartOID, - const LoanID TargetLoan, - const CFG *Cfg) const; + llvm::ImmutableList<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, + const OriginID StartOID, + const LoanID TargetLoan, + const CFG *Cfg) const; - llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, - const LoanID TargetLoan, - const CFG *Cfg) const; + llvm::ImmutableList<OriginID> buildOriginFlowChain(const UseFact *UF, + const LoanID TargetLoan, + const CFG *Cfg) const; private: class Impl; diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index f72f7f80abbc0..3b7248b28b945 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -527,7 +527,7 @@ class LifetimeChecker { /// extracts the corresponding expressions for each origin. Origins that refer /// to declarations (rather than expressions) are skipped. llvm::SmallVector<const Expr *> - getExprChain(llvm::ArrayRef<OriginID> OriginFlowChain) { + getExprChain(llvm::ImmutableList<OriginID> OriginFlowChain) { llvm::SmallVector<const Expr *> rs; for (const OriginID CurrOID : OriginFlowChain) if (const Expr *CurrExpr = diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp index 798812327d3ab..50fc8e033d81b 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp @@ -86,8 +86,11 @@ void LifetimeSafetyAnalysis::run() { /// the analysis. /// 3. Collapse ExpireFacts belonging to same source location into a single /// Fact. + + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; LoanPropagation = std::make_unique<LoanPropagationAnalysis>( - Cfg, AC, *FactMgr, Factory.OriginMapFactory, Factory.LoanSetFactory); + Cfg, AC, *FactMgr, Factory.OriginMapFactory, Factory.LoanSetFactory, + OriginFlowChainFactory); LiveOrigins = std::make_unique<LiveOriginsAnalysis>( Cfg, AC, *FactMgr, Factory.LivenessMapFactory); diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp index 078892bd48c10..56e17c080db3d 100644 --- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp @@ -18,6 +18,7 @@ #include "clang/Analysis/CFG.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/TimeProfiler.h" @@ -136,9 +137,11 @@ class AnalysisImpl public: AnalysisImpl(const CFG &C, AnalysisDeclContext &AC, FactManager &F, OriginLoanMap::Factory &OriginLoanMapFactory, - LoanSet::Factory &LoanSetFactory) + LoanSet::Factory &LoanSetFactory, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) : DataflowAnalysis(C, AC, F), OriginLoanMapFactory(OriginLoanMapFactory), LoanSetFactory(LoanSetFactory), + OriginFlowChainFactory(OriginFlowChainFactory), PersistentOrigins(computePersistentOrigins(F, C)) {} using Base::transfer; @@ -203,10 +206,10 @@ class AnalysisImpl return getLoans(getState(P), OID); } - llvm::SmallVector<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, - const OriginID StartOID, - const LoanID TargetLoan, - const CFG *Cfg) const { + llvm::ImmutableList<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, + const OriginID StartOID, + const LoanID TargetLoan, + const CFG *Cfg) const { assert(getLoans(StartOID, StartPoint).contains(TargetLoan) && "TargetLoan must be present in the StartOID at the StartPoint"); @@ -225,12 +228,13 @@ class AnalysisImpl using SearchState = std::pair<const CFGBlock *, OriginID>; struct DFSNode { SearchState CurrState; - llvm::SmallVector<OriginID> OriginFlowChain; + llvm::ImmutableList<OriginID> OriginFlowChain; }; llvm::SmallVector<DFSNode> PendingStates; llvm::SmallSet<SearchState, 16> VistedStates; - PendingStates.push_back({{EndBlock, StartOID}, {}}); + PendingStates.push_back( + {{EndBlock, StartOID}, OriginFlowChainFactory.getEmptyList()}); // DFS loop to trace loan backwards through CFG while (!PendingStates.empty()) { @@ -241,7 +245,9 @@ class AnalysisImpl const auto [BuildResult, Complete] = buildOriginFlowChain(CurrBlock, CurrOID, TargetLoan); if (!BuildResult.empty()) { - CurrNode.OriginFlowChain.append(BuildResult); + for (OriginID OID : BuildResult) + CurrNode.OriginFlowChain = + OriginFlowChainFactory.add(OID, CurrNode.OriginFlowChain); CurrOID = BuildResult.back(); } @@ -259,13 +265,13 @@ class AnalysisImpl } } - llvm_unreachable( - "buildOriginFlowChain did not reach IssueFact for TargetLoan"); + llvm_unreachable("Could not reconstruct origin flow. Search finished " + "without reaching IssueFact"); } - llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, - const LoanID TargetLoan, - const CFG *Cfg) const { + llvm::ImmutableList<OriginID> buildOriginFlowChain(const UseFact *UF, + const LoanID TargetLoan, + const CFG *Cfg) const { for (const OriginList *Cur = UF->getUsedOrigins(); Cur; Cur = Cur->peelOuterOrigin()) if (getLoans(Cur->getOuterOriginID(), UF).contains(TargetLoan)) @@ -333,6 +339,7 @@ class AnalysisImpl OriginLoanMap::Factory &OriginLoanMapFactory; LoanSet::Factory &LoanSetFactory; + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory; /// Boolean vector indexed by origin ID. If true, the origin appears in /// multiple basic blocks and must participate in join operations. If false, /// the origin is block-local and can be discarded at block boundaries. @@ -347,9 +354,10 @@ class LoanPropagationAnalysis::Impl final : public AnalysisImpl { LoanPropagationAnalysis::LoanPropagationAnalysis( const CFG &C, AnalysisDeclContext &AC, FactManager &F, OriginLoanMap::Factory &OriginLoanMapFactory, - LoanSet::Factory &LoanSetFactory) + LoanSet::Factory &LoanSetFactory, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) : PImpl(std::make_unique<Impl>(C, AC, F, OriginLoanMapFactory, - LoanSetFactory)) { + LoanSetFactory, OriginFlowChainFactory)) { PImpl->run(); } @@ -359,13 +367,13 @@ LoanSet LoanPropagationAnalysis::getLoans(OriginID OID, ProgramPoint P) const { return PImpl->getLoans(OID, P); } -llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( +llvm::ImmutableList<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, const CFG *Cfg) const { return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan, Cfg); } -llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( +llvm::ImmutableList<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg) const { return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg); } diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 48edf5f3f070f..c36402b393729 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -668,10 +668,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { if (OriginExprChain.empty()) return; - const Expr *LastExpr = OriginExprChain.back(); + const Expr *LastExpr = OriginExprChain.front(); std::string IssueStr = getDiagSubjectDescription(LastExpr); - for (const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) { + for (const Expr *CurrExpr : OriginExprChain.drop_front()) { if (!shouldShowInAliasChain(CurrExpr, LastExpr)) continue; S.Diag(CurrExpr->getBeginLoc(), diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp index 57cf7068affae..cb69b440c482c 100644 --- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -205,18 +205,18 @@ class LifetimeTestHelper { return Runner.getAnalysis().getFactManager().getBlockContaining(P); } - llvm::SmallVector<OriginID> + llvm::ImmutableList<OriginID> buildOriginFlowChain(llvm::StringRef StartOriginVar, llvm::StringRef EndLoanVar, llvm::StringRef Annotation) { std::optional<OriginID> StartOriginID = getOriginForDecl(StartOriginVar); std::vector<LoanID> EndLoanIDs = getLoansForVar(EndLoanVar); for (LoanID LID : EndLoanIDs) { - llvm::SmallVector<OriginID> OriginFlowChain = + llvm::ImmutableList<OriginID> OriginFlowChain = Runner.getAnalysis().getLoanPropagation().buildOriginFlowChain( getProgramPoint(Annotation), *StartOriginID, LID, Runner.getAnalysisContext().getCFG()); - if (!OriginFlowChain.empty()) + if (!OriginFlowChain.isEmpty()) return OriginFlowChain; } @@ -2001,11 +2001,11 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChain) { } )"); - llvm::SmallVector<OriginID> ChainForTgtA = + llvm::ImmutableList<OriginID> ChainForTgtA = Helper->buildOriginFlowChain("s", "tgta", "after_nested_merge"); - llvm::SmallVector<OriginID> ChainForTgtB = + llvm::ImmutableList<OriginID> ChainForTgtB = Helper->buildOriginFlowChain("s", "tgtb", "after_nested_merge"); - llvm::SmallVector<OriginID> ChainForTgtC = + llvm::ImmutableList<OriginID> ChainForTgtC = Helper->buildOriginFlowChain("s", "tgtc", "after_nested_merge"); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); @@ -2050,7 +2050,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithSelfAssignment) { } )"); - const llvm::SmallVector<OriginID> OriginFlowChain = + const llvm::ImmutableList<OriginID> OriginFlowChain = Helper->buildOriginFlowChain("s", "tgt", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); @@ -2067,7 +2067,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithMultiAssignInSameStmt) { } )"); - const llvm::SmallVector<OriginID> OriginFlowChain = + const llvm::ImmutableList<OriginID> OriginFlowChain = Helper->buildOriginFlowChain("s", "tgt", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); @@ -2088,7 +2088,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithOverwritingAssignments) { } )"); - const llvm::SmallVector<OriginID> OriginFlowChain = + const llvm::ImmutableList<OriginID> OriginFlowChain = Helper->buildOriginFlowChain("s", "tgt1", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); @@ -2110,9 +2110,9 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithLifetimeBound) { } )"); - llvm::SmallVector<OriginID> ChainForTgtA = + llvm::ImmutableList<OriginID> ChainForTgtA = Helper->buildOriginFlowChain("s", "tgta", "after_use"); - llvm::SmallVector<OriginID> ChainForTgtB = + llvm::ImmutableList<OriginID> ChainForTgtB = Helper->buildOriginFlowChain("s", "tgtb", "after_use"); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); >From 82eb90682a5199aabbf185ba17c1da1f6e41faaa Mon Sep 17 00:00:00 2001 From: Yuan Suo <[email protected]> Date: Sat, 11 Jul 2026 18:09:34 +0800 Subject: [PATCH 2/4] Move ImmutableListFactory from LoanPropagationAnalysis to function parameter Signed-off-by: Yuan Suo <[email protected]> --- .../Analyses/LifetimeSafety/LoanPropagation.h | 22 ++++---- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 7 ++- .../LifetimeSafety/LifetimeSafety.cpp | 4 +- .../LifetimeSafety/LoanPropagation.cpp | 38 +++++++------- .../unittests/Analysis/LifetimeSafetyTest.cpp | 50 ++++++++++++------- 5 files changed, 67 insertions(+), 54 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h index 3d489965a5aa6..6b9f748ead026 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h @@ -32,11 +32,9 @@ using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>; class LoanPropagationAnalysis { public: - LoanPropagationAnalysis( - const CFG &C, AnalysisDeclContext &AC, FactManager &F, - OriginLoanMap::Factory &OriginLoanMapFactory, - LoanSet::Factory &LoanSetFactory, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory); + LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, + OriginLoanMap::Factory &OriginLoanMapFactory, + LoanSet::Factory &LoanSetFactory); ~LoanPropagationAnalysis(); LoanSet getLoans(OriginID OID, ProgramPoint P) const; @@ -50,14 +48,14 @@ class LoanPropagationAnalysis { /// The traversal follows OriginFlowFacts backwards to reconstruct the /// sequence of origins through which the loan flowed, ending at the origin /// where the loan was originally issued. - llvm::ImmutableList<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, - const OriginID StartOID, - const LoanID TargetLoan, - const CFG *Cfg) const; + llvm::ImmutableList<OriginID> buildOriginFlowChain( + ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, + const CFG *Cfg, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const; - llvm::ImmutableList<OriginID> buildOriginFlowChain(const UseFact *UF, - const LoanID TargetLoan, - const CFG *Cfg) const; + llvm::ImmutableList<OriginID> buildOriginFlowChain( + const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const; private: class Impl; diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index 3b7248b28b945..e32faff310dbc 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -270,11 +270,14 @@ class LifetimeChecker { SemaHelper->reportUseAfterInvalidation( InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr); - } else + } else { // Scope-based expiry (use-after-scope). + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; SemaHelper->reportUseAfterScope( IssueExpr, UF->getUseExpr(), MovedExpr, ExpiryLoc, - getExprChain(LoanPropagation.buildOriginFlowChain(UF, LID, Cfg))); + getExprChain(LoanPropagation.buildOriginFlowChain( + UF, LID, Cfg, OriginFlowChainFactory))); + } } else if (const auto *OEF = CausingFact.dyn_cast<const OriginEscapesFact *>()) { diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp index 50fc8e033d81b..95e854abc540e 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp @@ -87,10 +87,8 @@ void LifetimeSafetyAnalysis::run() { /// 3. Collapse ExpireFacts belonging to same source location into a single /// Fact. - llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; LoanPropagation = std::make_unique<LoanPropagationAnalysis>( - Cfg, AC, *FactMgr, Factory.OriginMapFactory, Factory.LoanSetFactory, - OriginFlowChainFactory); + Cfg, AC, *FactMgr, Factory.OriginMapFactory, Factory.LoanSetFactory); LiveOrigins = std::make_unique<LiveOriginsAnalysis>( Cfg, AC, *FactMgr, Factory.LivenessMapFactory); diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp index 56e17c080db3d..49d65d536507a 100644 --- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp @@ -137,11 +137,9 @@ class AnalysisImpl public: AnalysisImpl(const CFG &C, AnalysisDeclContext &AC, FactManager &F, OriginLoanMap::Factory &OriginLoanMapFactory, - LoanSet::Factory &LoanSetFactory, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) + LoanSet::Factory &LoanSetFactory) : DataflowAnalysis(C, AC, F), OriginLoanMapFactory(OriginLoanMapFactory), LoanSetFactory(LoanSetFactory), - OriginFlowChainFactory(OriginFlowChainFactory), PersistentOrigins(computePersistentOrigins(F, C)) {} using Base::transfer; @@ -206,10 +204,10 @@ class AnalysisImpl return getLoans(getState(P), OID); } - llvm::ImmutableList<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, - const OriginID StartOID, - const LoanID TargetLoan, - const CFG *Cfg) const { + llvm::ImmutableList<OriginID> buildOriginFlowChain( + ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, + const CFG *Cfg, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { assert(getLoans(StartOID, StartPoint).contains(TargetLoan) && "TargetLoan must be present in the StartOID at the StartPoint"); @@ -269,14 +267,14 @@ class AnalysisImpl "without reaching IssueFact"); } - llvm::ImmutableList<OriginID> buildOriginFlowChain(const UseFact *UF, - const LoanID TargetLoan, - const CFG *Cfg) const { + llvm::ImmutableList<OriginID> buildOriginFlowChain( + const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { for (const OriginList *Cur = UF->getUsedOrigins(); Cur; Cur = Cur->peelOuterOrigin()) if (getLoans(Cur->getOuterOriginID(), UF).contains(TargetLoan)) return buildOriginFlowChain(UF, Cur->getOuterOriginID(), TargetLoan, - Cfg); + Cfg, OriginFlowChainFactory); return {}; } @@ -339,7 +337,6 @@ class AnalysisImpl OriginLoanMap::Factory &OriginLoanMapFactory; LoanSet::Factory &LoanSetFactory; - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory; /// Boolean vector indexed by origin ID. If true, the origin appears in /// multiple basic blocks and must participate in join operations. If false, /// the origin is block-local and can be discarded at block boundaries. @@ -354,10 +351,9 @@ class LoanPropagationAnalysis::Impl final : public AnalysisImpl { LoanPropagationAnalysis::LoanPropagationAnalysis( const CFG &C, AnalysisDeclContext &AC, FactManager &F, OriginLoanMap::Factory &OriginLoanMapFactory, - LoanSet::Factory &LoanSetFactory, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) + LoanSet::Factory &LoanSetFactory) : PImpl(std::make_unique<Impl>(C, AC, F, OriginLoanMapFactory, - LoanSetFactory, OriginFlowChainFactory)) { + LoanSetFactory)) { PImpl->run(); } @@ -369,12 +365,16 @@ LoanSet LoanPropagationAnalysis::getLoans(OriginID OID, ProgramPoint P) const { llvm::ImmutableList<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, - const CFG *Cfg) const { - return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan, Cfg); + const CFG *Cfg, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { + return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan, Cfg, + OriginFlowChainFactory); } llvm::ImmutableList<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( - const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg) const { - return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg); + const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { + return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg, + OriginFlowChainFactory); } } // namespace clang::lifetimes::internal diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp index cb69b440c482c..d164acf73a8a9 100644 --- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -205,9 +205,10 @@ class LifetimeTestHelper { return Runner.getAnalysis().getFactManager().getBlockContaining(P); } - llvm::ImmutableList<OriginID> - buildOriginFlowChain(llvm::StringRef StartOriginVar, - llvm::StringRef EndLoanVar, llvm::StringRef Annotation) { + llvm::ImmutableList<OriginID> buildOriginFlowChain( + llvm::StringRef StartOriginVar, llvm::StringRef EndLoanVar, + llvm::StringRef Annotation, + llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) { std::optional<OriginID> StartOriginID = getOriginForDecl(StartOriginVar); std::vector<LoanID> EndLoanIDs = getLoansForVar(EndLoanVar); @@ -215,7 +216,7 @@ class LifetimeTestHelper { llvm::ImmutableList<OriginID> OriginFlowChain = Runner.getAnalysis().getLoanPropagation().buildOriginFlowChain( getProgramPoint(Annotation), *StartOriginID, LID, - Runner.getAnalysisContext().getCFG()); + Runner.getAnalysisContext().getCFG(), OriginFlowChainFactory); if (!OriginFlowChain.isEmpty()) return OriginFlowChain; } @@ -2001,12 +2002,15 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChain) { } )"); - llvm::ImmutableList<OriginID> ChainForTgtA = - Helper->buildOriginFlowChain("s", "tgta", "after_nested_merge"); - llvm::ImmutableList<OriginID> ChainForTgtB = - Helper->buildOriginFlowChain("s", "tgtb", "after_nested_merge"); - llvm::ImmutableList<OriginID> ChainForTgtC = - Helper->buildOriginFlowChain("s", "tgtc", "after_nested_merge"); + llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtA; + llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtB; + llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtC; + llvm::ImmutableList<OriginID> ChainForTgtA = Helper->buildOriginFlowChain( + "s", "tgta", "after_nested_merge", ChainFactoryForTgtA); + llvm::ImmutableList<OriginID> ChainForTgtB = Helper->buildOriginFlowChain( + "s", "tgtb", "after_nested_merge", ChainFactoryForTgtB); + llvm::ImmutableList<OriginID> ChainForTgtC = Helper->buildOriginFlowChain( + "s", "tgtc", "after_nested_merge", ChainFactoryForTgtC); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(ChainForTgtA, Not(Contains(*Helper->getOriginForDecl("b")))); @@ -2032,7 +2036,9 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithErrorTargetLoan) { )"); #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST - EXPECT_DEATH(Helper->buildOriginFlowChain("s", "a", "after_use"), + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; + EXPECT_DEATH(Helper->buildOriginFlowChain("s", "a", "after_use", + OriginFlowChainFactory), "TargetLoan must be present in the StartOID at the StartPoint"); #endif } @@ -2050,8 +2056,10 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithSelfAssignment) { } )"); + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; const llvm::ImmutableList<OriginID> OriginFlowChain = - Helper->buildOriginFlowChain("s", "tgt", "after_use"); + Helper->buildOriginFlowChain("s", "tgt", "after_use", + OriginFlowChainFactory); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); } @@ -2067,8 +2075,10 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithMultiAssignInSameStmt) { } )"); + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; const llvm::ImmutableList<OriginID> OriginFlowChain = - Helper->buildOriginFlowChain("s", "tgt", "after_use"); + Helper->buildOriginFlowChain("s", "tgt", "after_use", + OriginFlowChainFactory); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("b"))); @@ -2088,8 +2098,10 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithOverwritingAssignments) { } )"); + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; const llvm::ImmutableList<OriginID> OriginFlowChain = - Helper->buildOriginFlowChain("s", "tgt1", "after_use"); + Helper->buildOriginFlowChain("s", "tgt1", "after_use", + OriginFlowChainFactory); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("b"))); @@ -2110,10 +2122,12 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithLifetimeBound) { } )"); - llvm::ImmutableList<OriginID> ChainForTgtA = - Helper->buildOriginFlowChain("s", "tgta", "after_use"); - llvm::ImmutableList<OriginID> ChainForTgtB = - Helper->buildOriginFlowChain("s", "tgtb", "after_use"); + llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtA; + llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtB; + llvm::ImmutableList<OriginID> ChainForTgtA = Helper->buildOriginFlowChain( + "s", "tgta", "after_use", ChainFactoryForTgtB); + llvm::ImmutableList<OriginID> ChainForTgtB = Helper->buildOriginFlowChain( + "s", "tgtb", "after_use", ChainFactoryForTgtB); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("result"))); >From 0a5aba669ee80e822b32218a463870cc02e2654c Mon Sep 17 00:00:00 2001 From: Yuan Suo <[email protected]> Date: Sun, 12 Jul 2026 09:54:03 +0800 Subject: [PATCH 3/4] Move OriginFlowChainFactory inside the function Signed-off-by: Yuan Suo <[email protected]> --- .../Analyses/LifetimeSafety/LoanPropagation.h | 14 ++--- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 9 +-- .../LifetimeSafety/LifetimeSafety.cpp | 1 - .../LifetimeSafety/LoanPropagation.cpp | 41 ++++++------- .../unittests/Analysis/LifetimeSafetyTest.cpp | 60 +++++++------------ 5 files changed, 54 insertions(+), 71 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h index 6b9f748ead026..2dc6f745de38d 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h @@ -48,14 +48,14 @@ class LoanPropagationAnalysis { /// The traversal follows OriginFlowFacts backwards to reconstruct the /// sequence of origins through which the loan flowed, ending at the origin /// where the loan was originally issued. - llvm::ImmutableList<OriginID> buildOriginFlowChain( - ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, - const CFG *Cfg, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const; + llvm::SmallVector<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, + const OriginID StartOID, + const LoanID TargetLoan, + const CFG *Cfg) const; - llvm::ImmutableList<OriginID> buildOriginFlowChain( - const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const; + llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, + const LoanID TargetLoan, + const CFG *Cfg) const; private: class Impl; diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index e32faff310dbc..c56726864f20c 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -270,14 +270,11 @@ class LifetimeChecker { SemaHelper->reportUseAfterInvalidation( InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr); - } else { + } else // Scope-based expiry (use-after-scope). - llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; SemaHelper->reportUseAfterScope( IssueExpr, UF->getUseExpr(), MovedExpr, ExpiryLoc, - getExprChain(LoanPropagation.buildOriginFlowChain( - UF, LID, Cfg, OriginFlowChainFactory))); - } + getExprChain(LoanPropagation.buildOriginFlowChain(UF, LID, Cfg))); } else if (const auto *OEF = CausingFact.dyn_cast<const OriginEscapesFact *>()) { @@ -530,7 +527,7 @@ class LifetimeChecker { /// extracts the corresponding expressions for each origin. Origins that refer /// to declarations (rather than expressions) are skipped. llvm::SmallVector<const Expr *> - getExprChain(llvm::ImmutableList<OriginID> OriginFlowChain) { + getExprChain(llvm::SmallVector<OriginID> OriginFlowChain) { llvm::SmallVector<const Expr *> rs; for (const OriginID CurrOID : OriginFlowChain) if (const Expr *CurrExpr = diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp index 95e854abc540e..798812327d3ab 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp @@ -86,7 +86,6 @@ void LifetimeSafetyAnalysis::run() { /// the analysis. /// 3. Collapse ExpireFacts belonging to same source location into a single /// Fact. - LoanPropagation = std::make_unique<LoanPropagationAnalysis>( Cfg, AC, *FactMgr, Factory.OriginMapFactory, Factory.LoanSetFactory); diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp index 49d65d536507a..1a5deb5bfca10 100644 --- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp @@ -204,10 +204,10 @@ class AnalysisImpl return getLoans(getState(P), OID); } - llvm::ImmutableList<OriginID> buildOriginFlowChain( - ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, - const CFG *Cfg, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { + llvm::SmallVector<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, + const OriginID StartOID, + const LoanID TargetLoan, + const CFG *Cfg) const { assert(getLoans(StartOID, StartPoint).contains(TargetLoan) && "TargetLoan must be present in the StartOID at the StartPoint"); @@ -231,6 +231,7 @@ class AnalysisImpl llvm::SmallVector<DFSNode> PendingStates; llvm::SmallSet<SearchState, 16> VistedStates; + llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; PendingStates.push_back( {{EndBlock, StartOID}, OriginFlowChainFactory.getEmptyList()}); @@ -250,8 +251,12 @@ class AnalysisImpl } // If we found the IssueFact, we're done - if (Complete) - return CurrNode.OriginFlowChain; + if (Complete) { + llvm::SmallVector<OriginID> Chain; + for (OriginID OID : CurrNode.OriginFlowChain) + Chain.push_back(OID); + return Chain; + } // Only explore predecessor blocks where the target loan is present in the // current origin. @@ -267,14 +272,14 @@ class AnalysisImpl "without reaching IssueFact"); } - llvm::ImmutableList<OriginID> buildOriginFlowChain( - const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { + llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, + const LoanID TargetLoan, + const CFG *Cfg) const { for (const OriginList *Cur = UF->getUsedOrigins(); Cur; Cur = Cur->peelOuterOrigin()) if (getLoans(Cur->getOuterOriginID(), UF).contains(TargetLoan)) return buildOriginFlowChain(UF, Cur->getOuterOriginID(), TargetLoan, - Cfg, OriginFlowChainFactory); + Cfg); return {}; } @@ -363,18 +368,14 @@ LoanSet LoanPropagationAnalysis::getLoans(OriginID OID, ProgramPoint P) const { return PImpl->getLoans(OID, P); } -llvm::ImmutableList<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( +llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, - const CFG *Cfg, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { - return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan, Cfg, - OriginFlowChainFactory); + const CFG *Cfg) const { + return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan, Cfg); } -llvm::ImmutableList<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( - const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) const { - return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg, - OriginFlowChainFactory); +llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( + const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg) const { + return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg); } } // namespace clang::lifetimes::internal diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp index d164acf73a8a9..57cf7068affae 100644 --- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -205,19 +205,18 @@ class LifetimeTestHelper { return Runner.getAnalysis().getFactManager().getBlockContaining(P); } - llvm::ImmutableList<OriginID> buildOriginFlowChain( - llvm::StringRef StartOriginVar, llvm::StringRef EndLoanVar, - llvm::StringRef Annotation, - llvm::ImmutableList<OriginID>::Factory &OriginFlowChainFactory) { + llvm::SmallVector<OriginID> + buildOriginFlowChain(llvm::StringRef StartOriginVar, + llvm::StringRef EndLoanVar, llvm::StringRef Annotation) { std::optional<OriginID> StartOriginID = getOriginForDecl(StartOriginVar); std::vector<LoanID> EndLoanIDs = getLoansForVar(EndLoanVar); for (LoanID LID : EndLoanIDs) { - llvm::ImmutableList<OriginID> OriginFlowChain = + llvm::SmallVector<OriginID> OriginFlowChain = Runner.getAnalysis().getLoanPropagation().buildOriginFlowChain( getProgramPoint(Annotation), *StartOriginID, LID, - Runner.getAnalysisContext().getCFG(), OriginFlowChainFactory); - if (!OriginFlowChain.isEmpty()) + Runner.getAnalysisContext().getCFG()); + if (!OriginFlowChain.empty()) return OriginFlowChain; } @@ -2002,15 +2001,12 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChain) { } )"); - llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtA; - llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtB; - llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtC; - llvm::ImmutableList<OriginID> ChainForTgtA = Helper->buildOriginFlowChain( - "s", "tgta", "after_nested_merge", ChainFactoryForTgtA); - llvm::ImmutableList<OriginID> ChainForTgtB = Helper->buildOriginFlowChain( - "s", "tgtb", "after_nested_merge", ChainFactoryForTgtB); - llvm::ImmutableList<OriginID> ChainForTgtC = Helper->buildOriginFlowChain( - "s", "tgtc", "after_nested_merge", ChainFactoryForTgtC); + llvm::SmallVector<OriginID> ChainForTgtA = + Helper->buildOriginFlowChain("s", "tgta", "after_nested_merge"); + llvm::SmallVector<OriginID> ChainForTgtB = + Helper->buildOriginFlowChain("s", "tgtb", "after_nested_merge"); + llvm::SmallVector<OriginID> ChainForTgtC = + Helper->buildOriginFlowChain("s", "tgtc", "after_nested_merge"); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(ChainForTgtA, Not(Contains(*Helper->getOriginForDecl("b")))); @@ -2036,9 +2032,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithErrorTargetLoan) { )"); #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST - llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; - EXPECT_DEATH(Helper->buildOriginFlowChain("s", "a", "after_use", - OriginFlowChainFactory), + EXPECT_DEATH(Helper->buildOriginFlowChain("s", "a", "after_use"), "TargetLoan must be present in the StartOID at the StartPoint"); #endif } @@ -2056,10 +2050,8 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithSelfAssignment) { } )"); - llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; - const llvm::ImmutableList<OriginID> OriginFlowChain = - Helper->buildOriginFlowChain("s", "tgt", "after_use", - OriginFlowChainFactory); + const llvm::SmallVector<OriginID> OriginFlowChain = + Helper->buildOriginFlowChain("s", "tgt", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); } @@ -2075,10 +2067,8 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithMultiAssignInSameStmt) { } )"); - llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; - const llvm::ImmutableList<OriginID> OriginFlowChain = - Helper->buildOriginFlowChain("s", "tgt", "after_use", - OriginFlowChainFactory); + const llvm::SmallVector<OriginID> OriginFlowChain = + Helper->buildOriginFlowChain("s", "tgt", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("b"))); @@ -2098,10 +2088,8 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithOverwritingAssignments) { } )"); - llvm::ImmutableList<OriginID>::Factory OriginFlowChainFactory; - const llvm::ImmutableList<OriginID> OriginFlowChain = - Helper->buildOriginFlowChain("s", "tgt1", "after_use", - OriginFlowChainFactory); + const llvm::SmallVector<OriginID> OriginFlowChain = + Helper->buildOriginFlowChain("s", "tgt1", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("b"))); @@ -2122,12 +2110,10 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithLifetimeBound) { } )"); - llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtA; - llvm::ImmutableList<OriginID>::Factory ChainFactoryForTgtB; - llvm::ImmutableList<OriginID> ChainForTgtA = Helper->buildOriginFlowChain( - "s", "tgta", "after_use", ChainFactoryForTgtB); - llvm::ImmutableList<OriginID> ChainForTgtB = Helper->buildOriginFlowChain( - "s", "tgtb", "after_use", ChainFactoryForTgtB); + llvm::SmallVector<OriginID> ChainForTgtA = + Helper->buildOriginFlowChain("s", "tgta", "after_use"); + llvm::SmallVector<OriginID> ChainForTgtB = + Helper->buildOriginFlowChain("s", "tgtb", "after_use"); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("result"))); >From 8ec261b353bab115d7366d64d6bd001bb49b5532 Mon Sep 17 00:00:00 2001 From: Yuan Suo <[email protected]> Date: Sun, 12 Jul 2026 09:59:27 +0800 Subject: [PATCH 4/4] Delete the unnecessary parts Signed-off-by: Yuan Suo <[email protected]> --- .../clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h | 1 - clang/lib/Analysis/LifetimeSafety/Checker.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h index 2dc6f745de38d..838daa024c953 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h @@ -18,7 +18,6 @@ #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" -#include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableSet.h" diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index c56726864f20c..f72f7f80abbc0 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -527,7 +527,7 @@ class LifetimeChecker { /// extracts the corresponding expressions for each origin. Origins that refer /// to declarations (rather than expressions) are skipped. llvm::SmallVector<const Expr *> - getExprChain(llvm::SmallVector<OriginID> OriginFlowChain) { + getExprChain(llvm::ArrayRef<OriginID> OriginFlowChain) { llvm::SmallVector<const Expr *> rs; for (const OriginID CurrOID : OriginFlowChain) if (const Expr *CurrExpr = _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
