Skip to content

Commit d5b093e

Browse files
committed
[LifetimeSafety] Add loan expiry analysis
1 parent 16fccbd commit d5b093e

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

clang/include/clang/Analysis/Analyses/LifetimeSafety.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace internal {
3333
class Fact;
3434
class FactManager;
3535
class LoanPropagationAnalysis;
36+
class ExpiredLoansAnalysis;
3637
struct LifetimeFactory;
3738

3839
/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
@@ -96,6 +97,7 @@ class LifetimeSafetyAnalysis {
9697
std::unique_ptr<LifetimeFactory> Factory;
9798
std::unique_ptr<FactManager> FactMgr;
9899
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
100+
std::unique_ptr<ExpiredLoansAnalysis> ExpiredLoans;
99101
};
100102
} // namespace internal
101103
} // namespace clang::lifetimes

clang/lib/Analysis/LifetimeSafety.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Support/Debug.h"
2424
#include "llvm/Support/TimeProfiler.h"
2525
#include <cstdint>
26+
#include <memory>
2627

2728
namespace clang::lifetimes {
2829
namespace internal {
@@ -832,6 +833,65 @@ class LoanPropagationAnalysis
832833
}
833834
};
834835

836+
// ========================================================================= //
837+
// Expired Loans Analysis
838+
// ========================================================================= //
839+
840+
/// The dataflow lattice for tracking the set of expired loans.
841+
struct ExpiredLattice {
842+
LoanSet Expired;
843+
844+
ExpiredLattice() : Expired(nullptr) {};
845+
explicit ExpiredLattice(LoanSet S) : Expired(S) {}
846+
847+
bool operator==(const ExpiredLattice &Other) const {
848+
return Expired == Other.Expired;
849+
}
850+
bool operator!=(const ExpiredLattice &Other) const {
851+
return !(*this == Other);
852+
}
853+
854+
void dump(llvm::raw_ostream &OS) const {
855+
OS << "ExpiredLattice State:\n";
856+
if (Expired.isEmpty())
857+
OS << " <empty>\n";
858+
for (const LoanID &LID : Expired)
859+
OS << " Loan " << LID << " is expired\n";
860+
}
861+
};
862+
863+
/// The analysis that tracks which loans have expired.
864+
class ExpiredLoansAnalysis
865+
: public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice,
866+
Direction::Forward> {
867+
868+
LoanSet::Factory &Factory;
869+
870+
public:
871+
ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
872+
LifetimeFactory &Factory)
873+
: DataflowAnalysis(C, AC, F), Factory(Factory.LoanSetFactory) {}
874+
875+
using Base::transfer;
876+
877+
StringRef getAnalysisName() const { return "ExpiredLoans"; }
878+
879+
Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
880+
881+
/// Merges two lattices by taking the union of the expired loan sets.
882+
Lattice join(Lattice L1, Lattice L2) const {
883+
return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
884+
}
885+
886+
Lattice transfer(Lattice In, const ExpireFact &F) {
887+
return Lattice(Factory.add(In.Expired, F.getLoanID()));
888+
}
889+
890+
Lattice transfer(Lattice In, const IssueFact &F) {
891+
return Lattice(Factory.remove(In.Expired, F.getLoanID()));
892+
}
893+
};
894+
835895
// ========================================================================= //
836896
// TODO:
837897
// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
@@ -872,6 +932,10 @@ void LifetimeSafetyAnalysis::run() {
872932
LoanPropagation =
873933
std::make_unique<LoanPropagationAnalysis>(Cfg, AC, *FactMgr, *Factory);
874934
LoanPropagation->run();
935+
936+
ExpiredLoans =
937+
std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory);
938+
ExpiredLoans->run();
875939
}
876940

877941
LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,

0 commit comments

Comments
 (0)