[clang] 5b23e22 - [LifetimeSafety][NFC] Support printing propagated loans in Fact::dump (#207526)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 4 10:36:53 PDT 2026
Author: Utkarsh Saxena
Date: 2026-07-04T17:36:48Z
New Revision: 5b23e226ed8a38b725253748e623ad9bf27ac4a4
URL: https://github.com/llvm/llvm-project/commit/5b23e226ed8a38b725253748e623ad9bf27ac4a4
DIFF: https://github.com/llvm/llvm-project/commit/5b23e226ed8a38b725253748e623ad9bf27ac4a4.diff
LOG: [LifetimeSafety][NFC] Support printing propagated loans in Fact::dump (#207526)
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.
Added:
Modified:
clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
clang/lib/Analysis/LifetimeSafety/Facts.cpp
clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
clang/test/Sema/LifetimeSafety/lifetime-facts.cpp
Removed:
################################################################################
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, Type : int **)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_PP_INNER:[0-9]+]] (Decl: pp, Type : int *)
+// CHECK-NEXT: Dest: [[O_PP_INNER:[0-9]+]] (Decl: pp, Type : int *) has loans to { a }
// CHECK-NEXT: Src: {{[0-9]+}} (Expr: UnaryOperator, Type : int *)
// FIXME: Propagate origins across dereference unary operator*
@@ -146,22 +146,22 @@ void pointer_indirection() {
// CHECK: Use ([[O_PP_OUTER]] (Decl: pp, Type : int **), [[O_PP_INNER]] (Decl: pp, Type : int *), Read)
// CHECK: Issue ({{[0-9]+}} (Path: pp), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: pp))
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int **)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int **) has loans to { p }
// CHECK-NEXT: Src: [[O_PP_OUTER]] (Decl: pp, Type : int **)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *) has loans to { a }
// CHECK-NEXT: Src: [[O_PP_INNER]] (Decl: pp, Type : int *)
// 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: ImplicitCastExpr, Type : int **)
// 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: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *) has loans to { a }
// CHECK-NEXT: Src: {{[0-9]+}} (Expr: UnaryOperator, Type : int *)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: q, Type : int *)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: q, Type : int *) has loans to { a }
// CHECK-NEXT: Src: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
}
@@ -180,30 +180,30 @@ void test_use_lifetimebound_call() {
MyObj *q = &y;
// CHECK: Issue ([[L_Y:[0-9]+]] (Path: y), ToOrigin: [[O_DRE_Y:[0-9]+]] (Expr: DeclRefExpr, Decl: y))
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_ADDR_Y:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *)
+// CHECK-NEXT: Dest: [[O_ADDR_Y:[0-9]+]] (Expr: UnaryOperator, Type : MyObj *) has loans to { y }
// CHECK-NEXT: Src: [[O_DRE_Y]] (Expr: DeclRefExpr, Decl: y)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_Q:[0-9]+]] (Decl: q, Type : MyObj *)
+// CHECK-NEXT: Dest: [[O_Q:[0-9]+]] (Decl: q, Type : MyObj *) has loans to { y }
// CHECK-NEXT: Src: [[O_ADDR_Y]] (Expr: UnaryOperator, Type : MyObj *)
MyObj* r = LifetimeBoundCall(p, q);
// CHECK: Use ([[O_P]] (Decl: p, Type : MyObj *), Read)
// CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p))
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_P_RVAL:[0-9]+]] (Expr: ImplicitCastExpr, Type : MyObj *)
+// CHECK-NEXT: Dest: [[O_P_RVAL:[0-9]+]] (Expr: ImplicitCastExpr, Type : MyObj *) has loans to { x }
// CHECK-NEXT: Src: [[O_P]] (Decl: p, Type : MyObj *)
// CHECK: Use ([[O_Q]] (Decl: q, Type : MyObj *), Read)
// CHECK: Issue ({{[0-9]+}} (Path: q), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: q))
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_Q_RVAL:[0-9]+]] (Expr: ImplicitCastExpr, Type : MyObj *)
+// CHECK-NEXT: Dest: [[O_Q_RVAL:[0-9]+]] (Expr: ImplicitCastExpr, Type : MyObj *) has loans to { y }
// CHECK-NEXT: Src: [[O_Q]] (Decl: q, Type : MyObj *)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_CALL_EXPR:[0-9]+]] (Expr: CallExpr, Type : MyObj *)
+// CHECK-NEXT: Dest: [[O_CALL_EXPR:[0-9]+]] (Expr: CallExpr, Type : MyObj *) has loans to { x }
// CHECK-NEXT: Src: [[O_P_RVAL]] (Expr: ImplicitCastExpr, Type : MyObj *)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_CALL_EXPR]] (Expr: CallExpr, Type : MyObj *)
+// CHECK-NEXT: Dest: [[O_CALL_EXPR]] (Expr: CallExpr, Type : MyObj *) has loans to { x y }
// CHECK-NEXT: Src: [[O_Q_RVAL]] (Expr: ImplicitCastExpr, Type : MyObj *), Merge
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: r, Type : MyObj *)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: r, Type : MyObj *) has loans to { x y }
// CHECK-NEXT: Src: [[O_CALL_EXPR]] (Expr: CallExpr, Type : MyObj *)
// CHECK: Expire (y)
// CHECK: Expire (x)
@@ -217,23 +217,23 @@ void test_reference_variable() {
// CHECK: Block B{{[0-9]+}}:
// CHECK: Issue ([[L_X:[0-9]+]] (Path: x), ToOrigin: [[O_DRE_X:[0-9]+]] (Expr: DeclRefExpr, Decl: x))
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_CAST_Y:[0-9]+]] (Expr: ImplicitCastExpr, Type : const MyObj &)
+// CHECK-NEXT: Dest: [[O_CAST_Y:[0-9]+]] (Expr: ImplicitCastExpr, Type : const MyObj &) has loans to { x }
// CHECK-NEXT: Src: [[O_DRE_X]] (Expr: DeclRefExpr, Decl: x)
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_Y:[0-9]+]] (Decl: y, Type : const MyObj &)
+// CHECK-NEXT: Dest: [[O_Y:[0-9]+]] (Decl: y, Type : const MyObj &) has loans to { x }
// CHECK-NEXT: Src: [[O_CAST_Y]] (Expr: ImplicitCastExpr, Type : const MyObj &)
const MyObj& z = y;
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: [[O_Z:[0-9]+]] (Decl: z, Type : const MyObj &)
+// CHECK-NEXT: Dest: [[O_Z:[0-9]+]] (Decl: z, Type : const MyObj &) has loans to { x }
// CHECK-NEXT: Src: [[O_Y]] (Decl: y, Type : const MyObj &)
p = &z;
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : const MyObj *)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : const MyObj *) has loans to { x }
// CHECK-NEXT: Src: [[O_Z]] (Decl: z, Type : const MyObj &)
// CHECK: Use ({{[0-9]+}} (Decl: p, Type : const MyObj *), Write)
// CHECK: Issue ({{[0-9]+}} (Path: p), ToOrigin: {{[0-9]+}} (Expr: DeclRefExpr, Decl: p))
// CHECK: OriginFlow:
-// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: p, Type : const MyObj *)
+// CHECK-NEXT: Dest: {{[0-9]+}} (Decl: p, Type : const MyObj *) has loans to { x }
// CHECK-NEXT: Src: {{[0-9]+}} (Expr: UnaryOperator, Type : const MyObj *)
// CHECK: Expire (x)
}
More information about the cfe-commits
mailing list