clang 22.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
20#include "clang/Analysis/CFG.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/Debug.h"
23#include <cstdint>
24
26/// An abstract base class for a single, atomic lifetime-relevant event.
27class Fact {
28
29public:
30 enum class Kind : uint8_t {
31 /// A new loan is issued from a borrow expression (e.g., &x).
33 /// A loan expires as its underlying storage is freed (e.g., variable goes
34 /// out of scope).
36 /// An origin is propagated from a source to a destination (e.g., p = q).
37 /// This can also optionally kill the destination origin before flowing into
38 /// it. Otherwise, the source's loan set is merged into the destination's
39 /// loan set.
41 /// An origin escapes the function by flowing into the return value.
43 /// An origin is used (eg. appears as l-value expression like DeclRefExpr).
45 /// A marker for a specific point in the code, for testing.
47 };
48
49private:
50 Kind K;
51
52protected:
53 Fact(Kind K) : K(K) {}
54
55public:
56 virtual ~Fact() = default;
57 Kind getKind() const { return K; }
58
59 template <typename T> const T *getAs() const {
60 if (T::classof(this))
61 return static_cast<const T *>(this);
62 return nullptr;
63 }
64
65 virtual void dump(llvm::raw_ostream &OS, const LoanManager &,
66 const OriginManager &) const;
67};
68
69/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific
70/// `Fact`. identified by a lifetime-related event (`Fact`).
71///
72/// A `ProgramPoint` has "after" semantics: it represents the location
73/// immediately after its corresponding `Fact`.
74using ProgramPoint = const Fact *;
75
76class IssueFact : public Fact {
77 LoanID LID;
78 OriginID OID;
79
80public:
81 static bool classof(const Fact *F) { return F->getKind() == Kind::Issue; }
82
83 IssueFact(LoanID LID, OriginID OID) : Fact(Kind::Issue), LID(LID), OID(OID) {}
84 LoanID getLoanID() const { return LID; }
85 OriginID getOriginID() const { return OID; }
86 void dump(llvm::raw_ostream &OS, const LoanManager &LM,
87 const OriginManager &OM) const override;
88};
89
90class ExpireFact : public Fact {
91 LoanID LID;
92 SourceLocation ExpiryLoc;
93
94public:
95 static bool classof(const Fact *F) { return F->getKind() == Kind::Expire; }
96
98 : Fact(Kind::Expire), LID(LID), ExpiryLoc(ExpiryLoc) {}
99
100 LoanID getLoanID() const { return LID; }
101 SourceLocation getExpiryLoc() const { return ExpiryLoc; }
102
103 void dump(llvm::raw_ostream &OS, const LoanManager &LM,
104 const OriginManager &) const override;
105};
106
107class OriginFlowFact : public Fact {
108 OriginID OIDDest;
109 OriginID OIDSrc;
110 // True if the destination origin should be killed (i.e., its current loans
111 // cleared) before the source origin's loans are flowed into it.
112 bool KillDest;
113
114public:
115 static bool classof(const Fact *F) {
116 return F->getKind() == Kind::OriginFlow;
117 }
118
119 OriginFlowFact(OriginID OIDDest, OriginID OIDSrc, bool KillDest)
120 : Fact(Kind::OriginFlow), OIDDest(OIDDest), OIDSrc(OIDSrc),
121 KillDest(KillDest) {}
122
123 OriginID getDestOriginID() const { return OIDDest; }
124 OriginID getSrcOriginID() const { return OIDSrc; }
125 bool getKillDest() const { return KillDest; }
126
127 void dump(llvm::raw_ostream &OS, const LoanManager &,
128 const OriginManager &OM) const override;
129};
130
131class ReturnOfOriginFact : public Fact {
132 OriginID OID;
133
134public:
135 static bool classof(const Fact *F) {
136 return F->getKind() == Kind::ReturnOfOrigin;
137 }
138
140 OriginID getReturnedOriginID() const { return OID; }
141 void dump(llvm::raw_ostream &OS, const LoanManager &,
142 const OriginManager &OM) const override;
143};
144
145class UseFact : public Fact {
146 const Expr *UseExpr;
147 // True if this use is a write operation (e.g., left-hand side of assignment).
148 // Write operations are exempted from use-after-free checks.
149 bool IsWritten = false;
150
151public:
152 static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
153
154 UseFact(const Expr *UseExpr) : Fact(Kind::Use), UseExpr(UseExpr) {}
155
157 // TODO: Remove const cast and make OriginManager::get as const.
158 return const_cast<OriginManager &>(OM).get(*UseExpr);
159 }
160 const Expr *getUseExpr() const { return UseExpr; }
161 void markAsWritten() { IsWritten = true; }
162 bool isWritten() const { return IsWritten; }
163
164 void dump(llvm::raw_ostream &OS, const LoanManager &,
165 const OriginManager &OM) const override;
166};
167
168/// A dummy-fact used to mark a specific point in the code for testing.
169/// It is generated by recognizing a `void("__lifetime_test_point_...")` cast.
170class TestPointFact : public Fact {
171 StringRef Annotation;
172
173public:
174 static bool classof(const Fact *F) { return F->getKind() == Kind::TestPoint; }
175
176 explicit TestPointFact(StringRef Annotation)
177 : Fact(Kind::TestPoint), Annotation(Annotation) {}
178
179 StringRef getAnnotation() const { return Annotation; }
180
181 void dump(llvm::raw_ostream &OS, const LoanManager &,
182 const OriginManager &) const override;
183};
184
186public:
188 auto It = BlockToFactsMap.find(B);
189 if (It != BlockToFactsMap.end())
190 return It->second;
191 return {};
192 }
193
195 if (!NewFacts.empty())
196 BlockToFactsMap[B].assign(NewFacts.begin(), NewFacts.end());
197 }
198
199 template <typename FactType, typename... Args>
200 FactType *createFact(Args &&...args) {
201 void *Mem = FactAllocator.Allocate<FactType>();
202 return new (Mem) FactType(std::forward<Args>(args)...);
203 }
204
205 void dump(const CFG &Cfg, AnalysisDeclContext &AC) const;
206
207 /// Retrieves program points that were specially marked in the source code
208 /// for testing.
209 ///
210 /// The analysis recognizes special function calls of the form
211 /// `void("__lifetime_test_point_<name>")` as test points. This method returns
212 /// a map from the annotation string (<name>) to the corresponding
213 /// `ProgramPoint`. This allows test harnesses to query the analysis state at
214 /// user-defined locations in the code.
215 /// \note This is intended for testing only.
216 llvm::StringMap<ProgramPoint> getTestPoints() const;
217
218 LoanManager &getLoanMgr() { return LoanMgr; }
219 const LoanManager &getLoanMgr() const { return LoanMgr; }
220 OriginManager &getOriginMgr() { return OriginMgr; }
221 const OriginManager &getOriginMgr() const { return OriginMgr; }
222
223private:
224 LoanManager LoanMgr;
225 OriginManager OriginMgr;
226 llvm::DenseMap<const clang::CFGBlock *, llvm::SmallVector<const Fact *>>
227 BlockToFactsMap;
228 llvm::BumpPtrAllocator FactAllocator;
229};
230} // namespace clang::lifetimes::internal
231
232#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
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1222
This represents one expression.
Definition Expr.h:112
Encodes a location in the source.
SourceLocation getExpiryLoc() const
Definition Facts.h:101
static bool classof(const Fact *F)
Definition Facts.h:95
ExpireFact(LoanID LID, SourceLocation ExpiryLoc)
Definition Facts.h:97
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:187
FactType * createFact(Args &&...args)
Definition Facts.h:200
llvm::StringMap< ProgramPoint > getTestPoints() const
Retrieves program points that were specially marked in the source code for testing.
Definition Facts.cpp:65
void dump(const CFG &Cfg, AnalysisDeclContext &AC) const
Definition Facts.cpp:81
void addBlockFacts(const CFGBlock *B, llvm::ArrayRef< Fact * > NewFacts)
Definition Facts.h:194
const OriginManager & getOriginMgr() const
Definition Facts.h:221
const LoanManager & getLoanMgr() const
Definition Facts.h:219
An abstract base class for a single, atomic lifetime-relevant event.
Definition Facts.h:27
@ TestPoint
A marker for a specific point in the code, for testing.
Definition Facts.h:46
@ Expire
A loan expires as its underlying storage is freed (e.g., variable goes out of scope).
Definition Facts.h:35
@ ReturnOfOrigin
An origin escapes the function by flowing into the return value.
Definition Facts.h:42
@ Issue
A new loan is issued from a borrow expression (e.g., &x).
Definition Facts.h:32
@ OriginFlow
An origin is propagated from a source to a destination (e.g., p = q).
Definition Facts.h:40
@ Use
An origin is used (eg. appears as l-value expression like DeclRefExpr).
Definition Facts.h:44
const T * getAs() const
Definition Facts.h:59
virtual void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &) const
Definition Facts.cpp:15
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:83
static bool classof(const Fact *F)
Definition Facts.h:81
Manages the creation, storage and retrieval of loans.
Definition Loans.h:55
static bool classof(const Fact *F)
Definition Facts.h:115
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:119
Manages the creation, storage, and retrieval of origins for pointer-like variables and expressions.
Definition Origins.h:57
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM) const override
Definition Facts.cpp:46
static bool classof(const Fact *F)
Definition Facts.h:135
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &) const override
Definition Facts.cpp:60
static bool classof(const Fact *F)
Definition Facts.h:174
TestPointFact(StringRef Annotation)
Definition Facts.h:176
const Expr * getUseExpr() const
Definition Facts.h:160
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM) const override
Definition Facts.cpp:53
OriginID getUsedOrigin(const OriginManager &OM) const
Definition Facts.h:156
UseFact(const Expr *UseExpr)
Definition Facts.h:154
static bool classof(const Fact *F)
Definition Facts.h:152
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
Definition Facts.h:74
utils::ID< struct LoanTag > LoanID
Definition Loans.h:23
utils::ID< struct OriginTag > OriginID
Definition Origins.h:23
const FunctionProtoType * T