clang 23.0.0git
Facts.h
Go to the documentation of this file.
1//===- Facts.h - Lifetime Analysis Facts and Fact Manager ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines Facts, which are atomic lifetime-relevant events (such as
10// loan issuance, loan expiration, origin flow, and use), and the FactManager,
11// which manages the storage and retrieval of facts for each CFG block.
12//
13//===----------------------------------------------------------------------===//
14#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_FACTS_H
15#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_FACTS_H
16
21#include "clang/Analysis/CFG.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/Support/Debug.h"
24#include <cstdint>
25
27
29
30/// An abstract base class for a single, atomic lifetime-relevant event.
31class Fact {
32
33public:
34 enum class Kind : uint8_t {
35 /// A new loan is issued from a borrow expression (e.g., &x).
37 /// A loan expires as its underlying storage is freed (e.g., variable goes
38 /// out of scope).
40 /// An origin is propagated from a source to a destination (e.g., p = q).
41 /// This can also optionally kill the destination origin before flowing into
42 /// it. Otherwise, the source's loan set is merged into the destination's
43 /// loan set.
45 /// An origin is used (eg. appears as l-value expression like DeclRefExpr).
47 /// A marker for a specific point in the code, for testing.
49 /// An origin that escapes the function scope (e.g., via return).
51 };
52
53private:
54 Kind K;
55 FactID ID;
56
57protected:
58 Fact(Kind K) : K(K) {}
59
60public:
61 virtual ~Fact() = default;
62 Kind getKind() const { return K; }
63
64 void setID(FactID ID) { this->ID = ID; }
65 FactID getID() const { return ID; }
66
67 template <typename T> const T *getAs() const {
68 if (T::classof(this))
69 return static_cast<const T *>(this);
70 return nullptr;
71 }
72
73 virtual void dump(llvm::raw_ostream &OS, const LoanManager &,
74 const OriginManager &) const;
75};
76
77/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific
78/// `Fact`. identified by a lifetime-related event (`Fact`).
79///
80/// A `ProgramPoint` has "after" semantics: it represents the location
81/// immediately after its corresponding `Fact`.
82using ProgramPoint = const Fact *;
83
84class IssueFact : public Fact {
85 LoanID LID;
86 OriginID OID;
87
88public:
89 static bool classof(const Fact *F) { return F->getKind() == Kind::Issue; }
90
91 IssueFact(LoanID LID, OriginID OID) : Fact(Kind::Issue), LID(LID), OID(OID) {}
92 LoanID getLoanID() const { return LID; }
93 OriginID getOriginID() const { return OID; }
94 void dump(llvm::raw_ostream &OS, const LoanManager &LM,
95 const OriginManager &OM) const override;
96};
97
98class ExpireFact : public Fact {
99 LoanID LID;
100 SourceLocation ExpiryLoc;
101
102public:
103 static bool classof(const Fact *F) { return F->getKind() == Kind::Expire; }
104
106 : Fact(Kind::Expire), LID(LID), ExpiryLoc(ExpiryLoc) {}
107
108 LoanID getLoanID() const { return LID; }
109 SourceLocation getExpiryLoc() const { return ExpiryLoc; }
110
111 void dump(llvm::raw_ostream &OS, const LoanManager &LM,
112 const OriginManager &) const override;
113};
114
115class OriginFlowFact : public Fact {
116 OriginID OIDDest;
117 OriginID OIDSrc;
118 // True if the destination origin should be killed (i.e., its current loans
119 // cleared) before the source origin's loans are flowed into it.
120 bool KillDest;
121
122public:
123 static bool classof(const Fact *F) {
124 return F->getKind() == Kind::OriginFlow;
125 }
126
127 OriginFlowFact(OriginID OIDDest, OriginID OIDSrc, bool KillDest)
128 : Fact(Kind::OriginFlow), OIDDest(OIDDest), OIDSrc(OIDSrc),
129 KillDest(KillDest) {}
130
131 OriginID getDestOriginID() const { return OIDDest; }
132 OriginID getSrcOriginID() const { return OIDSrc; }
133 bool getKillDest() const { return KillDest; }
134
135 void dump(llvm::raw_ostream &OS, const LoanManager &,
136 const OriginManager &OM) const override;
137};
138
139/// Represents that an origin escapes the current scope through various means.
140/// This is the base class for different escape scenarios.
141class OriginEscapesFact : public Fact {
142 OriginID OID;
143
144public:
145 /// The way an origin can escape the current scope.
146 enum class EscapeKind : uint8_t {
147 Return, /// Escapes via return statement.
148 Field, /// Escapes via assignment to a field.
149 // FIXME: Add support for escape to global (dangling global ptr).
151
152 static bool classof(const Fact *F) {
153 return F->getKind() == Kind::OriginEscapes;
154 }
155
158 OriginID getEscapedOriginID() const { return OID; }
159 EscapeKind getEscapeKind() const { return EscKind; }
160};
161
162/// Represents that an origin escapes via a return statement.
164 const Expr *ReturnExpr;
165
166public:
167 ReturnEscapeFact(OriginID OID, const Expr *ReturnExpr)
168 : OriginEscapesFact(OID, EscapeKind::Return), ReturnExpr(ReturnExpr) {}
169
170 static bool classof(const Fact *F) {
171 return F->getKind() == Kind::OriginEscapes &&
172 static_cast<const OriginEscapesFact *>(F)->getEscapeKind() ==
174 }
175 const Expr *getReturnExpr() const { return ReturnExpr; };
176 void dump(llvm::raw_ostream &OS, const LoanManager &,
177 const OriginManager &OM) const override;
178};
179
180/// Represents that an origin escapes via assignment to a field.
181/// Example: `this->view = local_var;` where local_var outlives the assignment
182/// but not the object containing the field.
184 const FieldDecl *FDecl;
185
186public:
188 : OriginEscapesFact(OID, EscapeKind::Field), FDecl(FDecl) {}
189
190 static bool classof(const Fact *F) {
191 return F->getKind() == Kind::OriginEscapes &&
192 static_cast<const OriginEscapesFact *>(F)->getEscapeKind() ==
194 }
195 const FieldDecl *getFieldDecl() const { return FDecl; };
196 void dump(llvm::raw_ostream &OS, const LoanManager &,
197 const OriginManager &OM) const override;
198};
199
200class UseFact : public Fact {
201 const Expr *UseExpr;
202 const OriginList *OList;
203 // True if this use is a write operation (e.g., left-hand side of assignment).
204 // Write operations are exempted from use-after-free checks.
205 bool IsWritten = false;
206
207public:
208 static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
209
210 UseFact(const Expr *UseExpr, const OriginList *OList)
211 : Fact(Kind::Use), UseExpr(UseExpr), OList(OList) {}
212
213 const OriginList *getUsedOrigins() const { return OList; }
214 const Expr *getUseExpr() const { return UseExpr; }
215 void markAsWritten() { IsWritten = true; }
216 bool isWritten() const { return IsWritten; }
217
218 void dump(llvm::raw_ostream &OS, const LoanManager &,
219 const OriginManager &OM) const override;
220};
221
222/// A dummy-fact used to mark a specific point in the code for testing.
223/// It is generated by recognizing a `void("__lifetime_test_point_...")` cast.
224class TestPointFact : public Fact {
225 StringRef Annotation;
226
227public:
228 static bool classof(const Fact *F) { return F->getKind() == Kind::TestPoint; }
229
230 explicit TestPointFact(StringRef Annotation)
231 : Fact(Kind::TestPoint), Annotation(Annotation) {}
232
233 StringRef getAnnotation() const { return Annotation; }
234
235 void dump(llvm::raw_ostream &OS, const LoanManager &,
236 const OriginManager &) const override;
237};
238
240public:
241 FactManager(const AnalysisDeclContext &AC, const CFG &Cfg)
242 : OriginMgr(AC.getASTContext(), AC.getDecl()) {
243 BlockToFacts.resize(Cfg.getNumBlockIDs());
244 }
245
247 return BlockToFacts[B->getBlockID()];
248 }
249
251 if (!NewFacts.empty())
252 BlockToFacts[B->getBlockID()].assign(NewFacts.begin(), NewFacts.end());
253 }
254
255 template <typename FactType, typename... Args>
256 FactType *createFact(Args &&...args) {
257 void *Mem = FactAllocator.Allocate<FactType>();
258 FactType *Res = new (Mem) FactType(std::forward<Args>(args)...);
259 Res->setID(NextFactID++);
260 return Res;
261 }
262
263 void dump(const CFG &Cfg, AnalysisDeclContext &AC) const;
264
265 /// Retrieves program points that were specially marked in the source code
266 /// for testing.
267 ///
268 /// The analysis recognizes special function calls of the form
269 /// `void("__lifetime_test_point_<name>")` as test points. This method returns
270 /// a map from the annotation string (<name>) to the corresponding
271 /// `ProgramPoint`. This allows test harnesses to query the analysis state at
272 /// user-defined locations in the code.
273 /// \note This is intended for testing only.
274 llvm::StringMap<ProgramPoint> getTestPoints() const;
275 /// Retrieves all the facts in the block containing Program Point P.
276 /// \note This is intended for testing only.
278
279 unsigned getNumFacts() const { return NextFactID.Value; }
280
281 LoanManager &getLoanMgr() { return LoanMgr; }
282 const LoanManager &getLoanMgr() const { return LoanMgr; }
283 OriginManager &getOriginMgr() { return OriginMgr; }
284 const OriginManager &getOriginMgr() const { return OriginMgr; }
285
286private:
287 FactID NextFactID{0};
288 LoanManager LoanMgr;
289 OriginManager OriginMgr;
290 /// Facts for each CFG block, indexed by block ID.
292 llvm::BumpPtrAllocator FactAllocator;
293};
294} // namespace clang::lifetimes::internal
295
296#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_FACTS_H
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a single basic block in a source-level CFG.
Definition CFG.h:605
unsigned getBlockID() const
Definition CFG.h:1107
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1218
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1411
This represents one expression.
Definition Expr.h:112
Represents a member of a struct/union/class.
Definition Decl.h:3160
Encodes a location in the source.
SourceLocation getExpiryLoc() const
Definition Facts.h:109
static bool classof(const Fact *F)
Definition Facts.h:103
ExpireFact(LoanID LID, SourceLocation ExpiryLoc)
Definition Facts.h:105
void dump(llvm::raw_ostream &OS, const LoanManager &LM, const OriginManager &) const override
Definition Facts.cpp:29
llvm::ArrayRef< const Fact * > getFacts(const CFGBlock *B) const
Definition Facts.h:246
FactType * createFact(Args &&...args)
Definition Facts.h:256
llvm::StringMap< ProgramPoint > getTestPoints() const
Retrieves program points that were specially marked in the source code for testing.
Definition Facts.cpp:81
void dump(const CFG &Cfg, AnalysisDeclContext &AC) const
Definition Facts.cpp:96
void addBlockFacts(const CFGBlock *B, llvm::ArrayRef< Fact * > NewFacts)
Definition Facts.h:250
const OriginManager & getOriginMgr() const
Definition Facts.h:284
const LoanManager & getLoanMgr() const
Definition Facts.h:282
llvm::ArrayRef< const Fact * > getBlockContaining(ProgramPoint P) const
Retrieves all the facts in the block containing Program Point P.
Definition Facts.cpp:115
FactManager(const AnalysisDeclContext &AC, const CFG &Cfg)
Definition Facts.h:241
An abstract base class for a single, atomic lifetime-relevant event.
Definition Facts.h:31
@ TestPoint
A marker for a specific point in the code, for testing.
Definition Facts.h:48
@ Expire
A loan expires as its underlying storage is freed (e.g., variable goes out of scope).
Definition Facts.h:39
@ Issue
A new loan is issued from a borrow expression (e.g., &x).
Definition Facts.h:36
@ OriginFlow
An origin is propagated from a source to a destination (e.g., p = q).
Definition Facts.h:44
@ Use
An origin is used (eg. appears as l-value expression like DeclRefExpr).
Definition Facts.h:46
@ OriginEscapes
An origin that escapes the function scope (e.g., via return).
Definition Facts.h:50
const T * getAs() const
Definition Facts.h:67
virtual void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &) const
Definition Facts.cpp:15
FieldEscapeFact(OriginID OID, const FieldDecl *FDecl)
Definition Facts.h:187
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM) const override
Definition Facts.cpp:55
const FieldDecl * getFieldDecl() const
Definition Facts.h:195
static bool classof(const Fact *F)
Definition Facts.h:190
void dump(llvm::raw_ostream &OS, const LoanManager &LM, const OriginManager &OM) const override
Definition Facts.cpp:20
IssueFact(LoanID LID, OriginID OID)
Definition Facts.h:91
static bool classof(const Fact *F)
Definition Facts.h:89
Manages the creation, storage and retrieval of loans.
Definition Loans.h:146
enum clang::lifetimes::internal::OriginEscapesFact::EscapeKind EscKind
EscapeKind
The way an origin can escape the current scope.
Definition Facts.h:146
static bool classof(const Fact *F)
Definition Facts.h:152
OriginEscapesFact(OriginID OID, EscapeKind EscKind)
Definition Facts.h:156
static bool classof(const Fact *F)
Definition Facts.h:123
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM) const override
Definition Facts.cpp:36
OriginFlowFact(OriginID OIDDest, OriginID OIDSrc, bool KillDest)
Definition Facts.h:127
A list of origins representing levels of indirection for pointer-like types.
Definition Origins.h:94
Manages the creation, storage, and retrieval of origins for pointer-like variables and expressions.
Definition Origins.h:126
static bool classof(const Fact *F)
Definition Facts.h:170
ReturnEscapeFact(OriginID OID, const Expr *ReturnExpr)
Definition Facts.h:167
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM) const override
Definition Facts.cpp:48
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &) const override
Definition Facts.cpp:76
static bool classof(const Fact *F)
Definition Facts.h:228
TestPointFact(StringRef Annotation)
Definition Facts.h:230
const Expr * getUseExpr() const
Definition Facts.h:214
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM) const override
Definition Facts.cpp:62
static bool classof(const Fact *F)
Definition Facts.h:208
UseFact(const Expr *UseExpr, const OriginList *OList)
Definition Facts.h:210
const OriginList * getUsedOrigins() const
Definition Facts.h:213
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
Definition Facts.h:82
utils::ID< struct LoanTag > LoanID
Definition Loans.h:25
utils::ID< struct OriginTag > OriginID
Definition Origins.h:27
utils::ID< struct FactTag > FactID
Definition Facts.h:28
const FunctionProtoType * T
A generic, type-safe wrapper for an ID, distinguished by its Tag type.
Definition Utils.h:21