@@ -518,6 +518,8 @@ enum class Direction { Forward, Backward };
518
518
// / analysis.
519
519
// / \tparam LatticeType The dataflow lattice used by the analysis.
520
520
// / \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.
521
523
template <typename Derived, typename LatticeType, Direction Dir>
522
524
class DataflowAnalysis {
523
525
public:
@@ -775,6 +777,65 @@ class LoanPropagationAnalysis
775
777
}
776
778
};
777
779
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
+
778
839
// ========================================================================= //
779
840
// TODO:
780
841
// - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -807,5 +868,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
807
868
LoanPropagationAnalysis LoanPropagation (Cfg, AC, FactMgr, Factory);
808
869
LoanPropagation.run ();
809
870
DEBUG_WITH_TYPE (" LifetimeLoanPropagation" , LoanPropagation.dump ());
871
+
872
+ ExpiredLoansAnalysis ExpiredLoans (Cfg, AC, FactMgr, Factory);
873
+ ExpiredLoans.run ();
810
874
}
811
875
} // namespace clang
0 commit comments