|
17 | 17 | //===----------------------------------------------------------------------===//
|
18 | 18 | #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
|
19 | 19 | #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
|
20 |
| -#include "clang/AST/DeclBase.h" |
21 | 20 | #include "clang/Analysis/AnalysisDeclContext.h"
|
22 | 21 | #include "clang/Analysis/CFG.h"
|
23 |
| -namespace clang { |
| 22 | +#include "llvm/ADT/ImmutableSet.h" |
| 23 | +#include "llvm/ADT/StringMap.h" |
| 24 | +#include <memory> |
24 | 25 |
|
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; |
27 | 33 |
|
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 |
29 | 97 |
|
30 | 98 | #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
|
0 commit comments