Skip to content

Commit 5f09913

Browse files
committed
[LifetimeSafety] Add loan expiry analysis
1 parent 111163f commit 5f09913

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

clang/lib/Analysis/LifetimeSafety.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ enum class Direction { Forward, Backward };
518518
/// analysis.
519519
/// \tparam LatticeType The dataflow lattice used by the analysis.
520520
/// \tparam Dir The direction of the analysis (Forward or Backward).
521+
/// TODO: Maybe use the dataflow framework! The framework might need changes
522+
/// to support the current comparison done at block-entry.
521523
template <typename Derived, typename LatticeType, Direction Dir>
522524
class DataflowAnalysis {
523525
public:
@@ -775,6 +777,65 @@ class LoanPropagationAnalysis
775777
}
776778
};
777779

780+
// ========================================================================= //
781+
// Expired Loans Analysis
782+
// ========================================================================= //
783+
784+
/// The dataflow lattice for tracking the set of expired loans.
785+
struct ExpiredLattice {
786+
LoanSet Expired;
787+
788+
ExpiredLattice() : Expired(nullptr) {};
789+
explicit ExpiredLattice(LoanSet S) : Expired(S) {}
790+
791+
bool operator==(const ExpiredLattice &Other) const {
792+
return Expired == Other.Expired;
793+
}
794+
bool operator!=(const ExpiredLattice &Other) const {
795+
return !(*this == Other);
796+
}
797+
798+
void dump(llvm::raw_ostream &OS) const {
799+
OS << "ExpiredLattice State:\n";
800+
if (Expired.isEmpty())
801+
OS << " <empty>\n";
802+
for (const LoanID &LID : Expired)
803+
OS << " Loan " << LID << " is expired\n";
804+
}
805+
};
806+
807+
/// The analysis that tracks which loans have expired.
808+
class ExpiredLoansAnalysis
809+
: public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice,
810+
Direction::Forward> {
811+
812+
LoanSet::Factory &Factory;
813+
814+
public:
815+
ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
816+
LifetimeFactory &SF)
817+
: DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
818+
819+
using Base::transfer;
820+
821+
StringRef getAnalysisName() const { return "ExpiredLoans"; }
822+
823+
Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
824+
825+
/// Merges two lattices by taking the union of the expired loan sets.
826+
Lattice join(Lattice L1, Lattice L2) const {
827+
return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
828+
}
829+
830+
Lattice transfer(Lattice In, const ExpireFact &F) {
831+
return Lattice(Factory.add(In.Expired, F.getLoanID()));
832+
}
833+
834+
Lattice transfer(Lattice In, const IssueFact &F) {
835+
return Lattice(Factory.remove(In.Expired, F.getLoanID()));
836+
}
837+
};
838+
778839
// ========================================================================= //
779840
// TODO:
780841
// - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -807,5 +868,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
807868
LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
808869
LoanPropagation.run();
809870
DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
871+
872+
ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
873+
ExpiredLoans.run();
810874
}
811875
} // namespace clang

0 commit comments

Comments
 (0)