llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-temporal-safety Author: Utkarsh Saxena (usx95) <details> <summary>Changes</summary> This patch updates Fact::dump to accept an optional LoanPropagationAnalysis parameter. If provided, OriginFlowFact::dump will query it to print the loans held by the destination origin. This enables richer debug output for LifetimeFacts. --- Patch is 26.40 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/207526.diff 4 Files Affected: - (modified) clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h (+29-22) - (modified) clang/lib/Analysis/LifetimeSafety/Facts.cpp (+41-15) - (modified) clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp (+6-4) - (modified) clang/test/Sema/LifetimeSafety/lifetime-facts.cpp (+32-32) ``````````diff diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h index 5c671a93b149c..8dccccc0f2257 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h @@ -23,11 +23,14 @@ #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include <cstdint> #include <optional> namespace clang::lifetimes::internal { +class LoanPropagationAnalysis; + using FactID = utils::ID<struct FactTag>; /// An abstract base class for a single, atomic lifetime-relevant event. @@ -80,7 +83,8 @@ class Fact { } virtual void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &) const; + const OriginManager &, + const LoanPropagationAnalysis *LPA = nullptr) const; }; /// A `ProgramPoint` identifies a location in the CFG by pointing to a specific @@ -101,7 +105,8 @@ class IssueFact : public Fact { LoanID getLoanID() const { return LID; } OriginID getOriginID() const { return OID; } void dump(llvm::raw_ostream &OS, const LoanManager &LM, - const OriginManager &OM) const override; + const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// When an AccessPath expires (e.g., a variable goes out of scope), all loans @@ -127,7 +132,8 @@ class ExpireFact : public Fact { SourceLocation getExpiryLoc() const { return ExpiryLoc; } void dump(llvm::raw_ostream &OS, const LoanManager &LM, - const OriginManager &OM) const override; + const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; class OriginFlowFact : public Fact { @@ -150,8 +156,8 @@ class OriginFlowFact : public Fact { OriginID getSrcOriginID() const { return OIDSrc; } bool getKillDest() const { return KillDest; } - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// Represents that an origin escapes the current scope through various means. @@ -191,8 +197,8 @@ class ReturnEscapeFact : public OriginEscapesFact { EscapeKind::Return; } const Expr *getReturnExpr() const { return ReturnExpr; }; - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// Represents that an origin escapes via assignment to a field. @@ -211,8 +217,8 @@ class FieldEscapeFact : public OriginEscapesFact { EscapeKind::Field; } const FieldDecl *getFieldDecl() const { return FDecl; }; - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// Represents that an origin escapes via assignment to global or static @@ -230,8 +236,8 @@ class GlobalEscapeFact : public OriginEscapesFact { EscapeKind::Global; } const VarDecl *getGlobal() const { return Global; }; - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; class UseFact : public Fact { @@ -253,8 +259,8 @@ class UseFact : public Fact { void markAsWritten() { IsWritten = true; } bool isWritten() const { return IsWritten; } - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// Represents that an origin's storage has been invalidated by a container @@ -276,8 +282,8 @@ class InvalidateOriginFact : public Fact { OriginID getInvalidatedOrigin() const { return OID; } const Expr *getInvalidationExpr() const { return InvalidationExpr; } - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// Top-level origin of the expression which was found to be moved, e.g, when @@ -297,8 +303,8 @@ class MovedOriginFact : public Fact { OriginID getMovedOrigin() const { return MovedOrigin; } const Expr *getMoveExpr() const { return MoveExpr; } - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// A dummy-fact used to mark a specific point in the code for testing. @@ -314,8 +320,8 @@ class TestPointFact : public Fact { StringRef getAnnotation() const { return Annotation; } - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; /// All loans are cleared from an origin (e.g., assigning a callable without @@ -332,8 +338,8 @@ class KillOriginFact : public Fact { OriginID getKilledOrigin() const { return OID; } - void dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const override; + void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, + const LoanPropagationAnalysis *LPA = nullptr) const override; }; class FactManager { @@ -363,7 +369,8 @@ class FactManager { return Res; } - void dump(const CFG &Cfg, AnalysisDeclContext &AC) const; + void dump(const CFG &Cfg, AnalysisDeclContext &AC, + const LoanPropagationAnalysis *LPA = nullptr) const; /// Retrieves program points that were specially marked in the source code /// for testing. diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp b/clang/lib/Analysis/LifetimeSafety/Facts.cpp index 3d7fbcdacc830..15b666fbdf7ca 100644 --- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp @@ -8,17 +8,19 @@ #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h" #include "clang/AST/Decl.h" +#include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" namespace clang::lifetimes::internal { void Fact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &) const { + const OriginManager &, const LoanPropagationAnalysis *) const { OS << "Fact (Kind: " << static_cast<int>(K) << ")\n"; } void IssueFact::dump(llvm::raw_ostream &OS, const LoanManager &LM, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "Issue ("; LM.getLoan(getLoanID())->dump(OS); OS << ", ToOrigin: "; @@ -27,7 +29,8 @@ void IssueFact::dump(llvm::raw_ostream &OS, const LoanManager &LM, } void ExpireFact::dump(llvm::raw_ostream &OS, const LoanManager &LM, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *LPA) const { OS << "Expire ("; getAccessPath().dump(OS); if (auto OID = getOriginID()) { @@ -37,11 +40,25 @@ void ExpireFact::dump(llvm::raw_ostream &OS, const LoanManager &LM, OS << ")\n"; } -void OriginFlowFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { +void OriginFlowFact::dump(llvm::raw_ostream &OS, const LoanManager &LM, + const OriginManager &OM, + const LoanPropagationAnalysis *LPA) const { OS << "OriginFlow: \n"; OS << "\tDest: "; OM.dump(getDestOriginID(), OS); + if (LPA) { + LoanSet DestinationLoans = LPA->getLoans(getDestOriginID(), this); + if (DestinationLoans.isEmpty()) + OS << " has no loans"; + else { + OS << " has loans to { "; + for (LoanID LID : DestinationLoans) { + LM.getLoan(LID)->getAccessPath().dump(OS); + OS << " "; + } + OS << "}"; + } + } OS << "\n"; OS << "\tSrc: "; OM.dump(getSrcOriginID(), OS); @@ -50,35 +67,40 @@ void OriginFlowFact::dump(llvm::raw_ostream &OS, const LoanManager &, } void MovedOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "MovedOrigins ("; OM.dump(getMovedOrigin(), OS); OS << ")\n"; } void ReturnEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "OriginEscapes ("; OM.dump(getEscapedOriginID(), OS); OS << ", via Return)\n"; } void FieldEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "OriginEscapes ("; OM.dump(getEscapedOriginID(), OS); OS << ", via Field)\n"; } void GlobalEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "OriginEscapes ("; OM.dump(getEscapedOriginID(), OS); OS << ", via Global)\n"; } void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "Use ("; size_t NumUsedOrigins = getUsedOrigins()->getLength(); size_t I = 0; @@ -92,19 +114,22 @@ void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &, } void InvalidateOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "InvalidateOrigin ("; OM.dump(getInvalidatedOrigin(), OS); OS << ")\n"; } void TestPointFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &) const { + const OriginManager &, + const LoanPropagationAnalysis *) const { OS << "TestPoint (Annotation: \"" << getAnnotation() << "\")\n"; } void KillOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &, - const OriginManager &OM) const { + const OriginManager &OM, + const LoanPropagationAnalysis *) const { OS << "KillOrigin ("; OM.dump(getKilledOrigin(), OS); OS << ")\n"; @@ -125,7 +150,8 @@ llvm::StringMap<ProgramPoint> FactManager::getTestPoints() const { return AnnotationToPointMap; } -void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC) const { +void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC, + const LoanPropagationAnalysis *LPA) const { llvm::dbgs() << "==========================================\n"; llvm::dbgs() << " Lifetime Analysis Facts:\n"; llvm::dbgs() << "==========================================\n"; @@ -137,7 +163,7 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC) const { llvm::dbgs() << " Block B" << B->getBlockID() << ":\n"; for (const Fact *F : getFacts(B)) { llvm::dbgs() << " "; - F->dump(llvm::dbgs(), LoanMgr, OriginMgr); + F->dump(llvm::dbgs(), LoanMgr, OriginMgr, LPA); } llvm::dbgs() << " End of Block\n"; } diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp index 680095a54177c..798812327d3ab 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp @@ -35,7 +35,8 @@ namespace internal { #ifndef NDEBUG static void DebugOnlyFunction(AnalysisDeclContext &AC, const CFG &Cfg, - FactManager &FactMgr) { + FactManager &FactMgr, + const LoanPropagationAnalysis *LPA) { std::string Name; if (const Decl *D = AC.getDecl()) { if (const auto *ND = dyn_cast<NamedDecl>(D)) @@ -44,7 +45,7 @@ static void DebugOnlyFunction(AnalysisDeclContext &AC, const CFG &Cfg, DEBUG_WITH_TYPE(Name.c_str(), AC.getDecl()->dumpColor()); DEBUG_WITH_TYPE(Name.c_str(), Cfg.dump(AC.getASTContext().getLangOpts(), /*ShowColors=*/true)); - DEBUG_WITH_TYPE(Name.c_str(), FactMgr.dump(Cfg, AC)); + DEBUG_WITH_TYPE(Name.c_str(), FactMgr.dump(Cfg, AC, LPA)); } #endif @@ -101,12 +102,13 @@ void LifetimeSafetyAnalysis::run() { DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(), /*ShowColors=*/true)); - DEBUG_WITH_TYPE("LifetimeFacts", FactMgr->dump(Cfg, AC)); + DEBUG_WITH_TYPE("LifetimeFacts", + FactMgr->dump(Cfg, AC, LoanPropagation.get())); // Debug print facts for a specific function using // -debug-only=EnableFilterByFunctionName,YourFunctionNameFoo DEBUG_WITH_TYPE("EnableFilterByFunctionName", - DebugOnlyFunction(AC, Cfg, *FactMgr)); + DebugOnlyFunction(AC, Cfg, *FactMgr, LoanPropagation.get())); DEBUG_WITH_TYPE("LiveOrigins", LiveOrigins->dump(llvm::dbgs(), FactMgr->getTestPoints())); } diff --git a/clang/test/Sema/LifetimeSafety/lifetime-facts.cpp b/clang/test/Sema/LifetimeSafety/lifetime-facts.cpp index d655bf7391203..028833902aa94 100644 --- a/clang/test/Sema/LifetimeSafety/lifetime-facts.cpp +++ b/clang/test/Sema/LifetimeSafety/lifetime-facts.cpp @@ -23,7 +23,7 @@ MyObj* return_local_addr() { return p; // CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_RET_VAL:[0-9]+]] (Expr: ImplicitCastExpr, Type : MyObj *) +// CHECK-NEXT: Dest: [[O_RET_VAL:[0-9]+]] (Expr: ImplicitCastExpr, Type : MyObj *) has loans to { x } // CHECK-NEXT: Src: [[O_P]] (Decl: p, Type : MyObj *) // CHECK: Expire (x) // CHECK: Expire (p, Origin: [[O_P]] (Decl: p, Type : MyObj *)) @@ -37,11 +37,11 @@ void loan_expires_cpp() { // CHECK: Block B{{[0-9]+}}: // CHECK: Issue ([[L_OBJ:[0-9]+]] (Path: obj), ToOrigin: [[O_DRE_OBJ:[0-9]+]] (Expr: DeclRefExpr, Decl: obj)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_ADDR_OBJ:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *) +// CHECK-NEXT: Dest: [[O_ADDR_OBJ:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *) has loans to { obj } // CHECK-NEXT: Src: [[O_DRE_OBJ]] (Expr: DeclRefExpr, Decl: obj) MyObj* pObj = &obj; // CHECK: OriginFlow: -// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: pObj, Type : MyObj *) +// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: pObj, Type : MyObj *) has loans to { obj } // CHECK-NEXT: Src: [[O_ADDR_OBJ]] (Expr: UnaryOperator, Type : MyObj *) // CHECK: Expire (obj) } @@ -53,11 +53,11 @@ void loan_expires_trivial() { // CHECK: Block B{{[0-9]+}}: // CHECK: Issue ([[L_TRIVIAL_OBJ:[0-9]+]] (Path: trivial_obj), ToOrigin: [[O_DRE_TRIVIAL:[0-9]+]] (Expr: DeclRefExpr, Decl: trivial_obj)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_ADDR_TRIVIAL_OBJ:[0-9]+]] (Expr: UnaryOperator, Type : int *) +// CHECK-NEXT: Dest: [[O_ADDR_TRIVIAL_OBJ:[0-9]+]] (Expr: UnaryOperator, Type : int *) has loans to { trivial_obj } // CHECK-NEXT: Src: [[O_DRE_TRIVIAL]] (Expr: DeclRefExpr, Decl: trivial_obj) int* pTrivialObj = &trivial_obj; // CHECK: OriginFlow: -// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: pTrivialObj, Type : int *) +// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: pTrivialObj, Type : int *) has loans to { trivial_obj } // CHECK-NEXT: Src: [[O_ADDR_TRIVIAL_OBJ]] (Expr: UnaryOperator, Type : int *) // CHECK: Expire (trivial_obj) // CHECK-NEXT: End of Block @@ -79,12 +79,12 @@ void overwrite_origin() { p = &s2; // CHECK: Issue ([[L_S2:[0-9]+]] (Path: s2), ToOrigin: [[O_DRE_S2:[0-9]+]] (Expr: DeclRefExpr, Decl: s2)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *) +// CHECK-NEXT: Dest: [[O_ADDR_S2:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *) has loans to { s2 } // CHECK-NEXT: Src: [[O_DRE_S2]] (Expr: DeclRefExpr, Decl: s2) // CHECK: Use ([[O_P]] (Decl: p, Type : MyObj *), Write) // CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_P]] (Decl: p, Type : MyObj *) +// CHECK-NEXT: Dest: [[O_P]] (Decl: p, Type : MyObj *) has loans to { s2 } // CHECK-NEXT: Src: [[O_ADDR_S2]] (Expr: UnaryOperator, Type : MyObj *) // CHECK: Expire (s2) // CHECK: Expire (s1) @@ -106,7 +106,7 @@ void reassign_to_null() { // CHECK: Use ([[O_P]] (Decl: p, Type : MyObj *), Write) // CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_P]] (Decl: p, Type : MyObj *) +// CHECK-NEXT: Dest: [[O_P]] (Decl: p, Type : MyObj *) has no loans // CHECK-NEXT: Src: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : MyObj *) // CHECK: Expire (s1) } @@ -120,25 +120,25 @@ void pointer_indirection() { // CHECK: Block B{{[0-9]+}}: // CHECK: Issue ([[L_A:[0-9]+]] (Path: a), ToOrigin: [[O_DRE_A:[0-9]+]] (Expr: DeclRefExpr, Decl: a)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_ADDR_A:[0-9]+]] (Expr: UnaryOperator, Type : int *) +// CHECK-NEXT: Dest: [[O_ADDR_A:[0-9]+]] (Expr: UnaryOperator, Type : int *) has loans to { a } // CHECK-NEXT: Src: [[O_DRE_A]] (Expr: DeclRefExpr, Decl: a) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_P:[0-9]+]] (Decl: p, Type : int *) +// CHECK-NEXT: Dest: [[O_P:[0-9]+]] (Decl: p, Type : int *) has loans to { a } // CHECK-NEXT: Src: [[O_ADDR_A]] (Expr: UnaryOperator, Type : int *) int **pp = &p; // CHECK: Use ([[O_P]] (Decl: p, Type : int *), Read) // CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p)) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int **) +// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int **) has loans to { p } // CHECK-NEXT: Src: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int *) +// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int *) has loans to { a } // CHECK-NEXT: Src: [[O_P]] (Decl: p, Type : int *) // CHECK: OriginFlow: -// CHECK-NEXT: Dest: [[O_PP_OUTER:[0-9]+]] (Decl: pp, Type : int **) +// CHECK-NEXT: Dest: [[O_PP_OUTER:[0-9]+]] (Decl: pp, Type : int **) has loans to { p } // CHECK-NEXT: Src: {{[0-9]+}} (Expr: UnaryOperator, T... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/207526 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
