23
23
#include " llvm/Support/Debug.h"
24
24
#include " llvm/Support/TimeProfiler.h"
25
25
#include < cstdint>
26
+ #include < memory>
26
27
27
28
namespace clang ::lifetimes {
28
29
namespace internal {
@@ -832,6 +833,65 @@ class LoanPropagationAnalysis
832
833
}
833
834
};
834
835
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
+
835
895
// ========================================================================= //
836
896
// TODO:
837
897
// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
@@ -873,6 +933,10 @@ void LifetimeSafetyAnalysis::run() {
873
933
LoanPropagation =
874
934
std::make_unique<LoanPropagationAnalysis>(Cfg, AC, *FactMgr, *Factory);
875
935
LoanPropagation->run ();
936
+
937
+ ExpiredLoans =
938
+ std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory);
939
+ ExpiredLoans->run ();
876
940
}
877
941
878
942
LoanSet LifetimeSafetyAnalysis::getLoansAtPoint (OriginID OID,
@@ -881,6 +945,11 @@ LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
881
945
return LoanPropagation->getLoans (OID, PP);
882
946
}
883
947
948
+ LoanSet LifetimeSafetyAnalysis::getExpiredLoansAtPoint (ProgramPoint PP) const {
949
+ assert (ExpiredLoans && " ExpiredLoansAnalysis has not been run." );
950
+ return ExpiredLoans->getState (PP).Expired ;
951
+ }
952
+
884
953
std::optional<OriginID>
885
954
LifetimeSafetyAnalysis::getOriginIDForDecl (const ValueDecl *D) const {
886
955
assert (FactMgr && " FactManager not initialized" );
0 commit comments