Skip to content

Commit 299ff30

Browse files
committed
[LifetimeSafety] Revamp test suite using unittests
1 parent d9190f8 commit 299ff30

File tree

5 files changed

+652
-60
lines changed

5 files changed

+652
-60
lines changed

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

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,82 @@
1717
//===----------------------------------------------------------------------===//
1818
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
1919
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
20-
#include "clang/AST/DeclBase.h"
2120
#include "clang/Analysis/AnalysisDeclContext.h"
2221
#include "clang/Analysis/CFG.h"
23-
namespace clang {
22+
#include "llvm/ADT/ImmutableSet.h"
23+
#include "llvm/ADT/StringMap.h"
24+
#include <memory>
2425

25-
void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
26-
AnalysisDeclContext &AC);
26+
namespace clang::lifetimes {
27+
namespace internal {
28+
// Forward declarations of internal types.
29+
class Fact;
30+
class FactManager;
31+
class LoanPropagationAnalysis;
32+
struct LifetimeFactory;
2733

28-
} // namespace clang
34+
/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
35+
/// Used for giving ID to loans and origins.
36+
template <typename Tag> struct ID {
37+
uint32_t Value = 0;
38+
39+
bool operator==(const ID<Tag> &Other) const { return Value == Other.Value; }
40+
bool operator!=(const ID<Tag> &Other) const { return !(*this == Other); }
41+
bool operator<(const ID<Tag> &Other) const { return Value < Other.Value; }
42+
ID<Tag> operator++(int) {
43+
ID<Tag> Tmp = *this;
44+
++Value;
45+
return Tmp;
46+
}
47+
void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
48+
IDBuilder.AddInteger(Value);
49+
}
50+
};
51+
52+
using LoanID = ID<struct LoanTag>;
53+
using OriginID = ID<struct OriginTag>;
54+
55+
// Using LLVM's immutable collections is efficient for dataflow analysis
56+
// as it avoids deep copies during state transitions.
57+
// TODO(opt): Consider using a bitset to represent the set of loans.
58+
using LoanSet = llvm::ImmutableSet<LoanID>;
59+
using OriginSet = llvm::ImmutableSet<OriginID>;
60+
61+
using ProgramPoint = std::pair<const CFGBlock *, const Fact *>;
62+
63+
/// Running the lifetime safety analysis and querying its results. It
64+
/// encapsulates the various dataflow analyses.
65+
class LifetimeSafetyAnalysis {
66+
public:
67+
LifetimeSafetyAnalysis(AnalysisDeclContext &AC);
68+
~LifetimeSafetyAnalysis();
69+
70+
void run();
71+
72+
/// Returns the set of loans an origin holds at a specific program point.
73+
LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const;
74+
75+
/// Finds the OriginID for a given declaration.
76+
/// Returns a null optional if not found.
77+
std::optional<OriginID> getOriginIDForDecl(const ValueDecl *D) const;
78+
79+
/// Finds the LoanID for a loan created on a specific variable.
80+
/// Returns a null optional if not found.
81+
std::optional<LoanID> getLoanIDForVar(const VarDecl *VD) const;
82+
83+
llvm::StringMap<ProgramPoint> getTestPoints() const;
84+
85+
private:
86+
AnalysisDeclContext &AC;
87+
std::unique_ptr<LifetimeFactory> Factory;
88+
std::unique_ptr<FactManager> FactMgr;
89+
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
90+
};
91+
} // namespace internal
92+
93+
/// The main entry point for the analysis.
94+
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC);
95+
96+
} // namespace clang::lifetimes
2997

3098
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H

0 commit comments

Comments
 (0)