clang: lib/Analysis/LifetimeSafety/FactsGenerator.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12#include "llvm/Support/Casting.h"
13#include "llvm/Support/TimeProfiler.h"
14
16using llvm::isa_and_present;
17
21
25
29
30
31
32
33
36 if (const auto *VD = dyn_cast(DRE->getDecl())) {
38
40 }
41 return nullptr;
42}
43
45 llvm::TimeTraceScope TimeProfile("FactGenerator");
46 const CFG &Cfg = *AC.getCFG();
48
49
51 CurrentBlockFacts.clear();
52 EscapesInCurrentBlock.clear();
54 CurrentBlockFacts.append(PlaceholderLoanFacts.begin(),
55 PlaceholderLoanFacts.end());
56 for (unsigned I = 0; I < Block->size(); ++I) {
58 if (std::optional CS = Element.getAs<CFGStmt>())
59 Visit(CS->getStmt());
60 else if (std::optional LifetimeEnds =
62 handleLifetimeEnds(*LifetimeEnds);
63 }
64 CurrentBlockFacts.append(EscapesInCurrentBlock.begin(),
65 EscapesInCurrentBlock.end());
66 FactMgr.addBlockFacts(Block, CurrentBlockFacts);
67 }
68}
69
72 if (const auto *VD = dyn_cast(D))
74 if (const Expr *InitExpr = VD->getInit())
75 killAndFlowOrigin(*VD, *InitExpr);
76}
77
79 handleUse(DRE);
80
81
82
83
84
85
86
87
88
89
92 OriginID ExprOID = FactMgr.getOriginMgr().getOrCreate(*DRE);
93 CurrentBlockFacts.push_back(
94 FactMgr.createFact<IssueFact>(L->getID(), ExprOID));
95 }
96 }
97}
98
101 handleGSLPointerConstruction(CCE);
102 return;
103 }
104}
105
107
108
110 isa_and_present(MCE->getCalleeDecl())) {
111
113 {MCE->getImplicitObjectArgument()},
114 true);
115 }
117
118
122
123 handleFunctionCall(MCE, Method, Args, false);
124 }
125}
126
129 {CE->getArgs(), CE->getNumArgs()});
130}
131
134
135
136 FactMgr.getOriginMgr().getOrCreate(*N);
137}
138
141 return;
142
143
144 killAndFlowOrigin(*ICE, *ICE->getSubExpr());
145}
146
148 if (UO->getOpcode() == UO_AddrOf) {
150
151
153 return;
154
155
156
157
158 killAndFlowOrigin(*UO, *SubExpr);
159 }
160}
161
165 OriginID OID = FactMgr.getOriginMgr().getOrCreate(*RetExpr);
166 EscapesInCurrentBlock.push_back(
168 }
169 }
170}
171
176
179
180
181 killAndFlowOrigin(*CO, *CO->getTrueExpr());
183 }
184}
185
187
188
190 handleAssignment(OCE->getArg(0), OCE->getArg(1));
191 return;
192 }
194 {OCE->getArgs(), OCE->getNumArgs()},
195 false);
196}
197
200
201
202 if (handleTestPoint(FCE))
203 return;
205 killAndFlowOrigin(*FCE, *FCE->getSubExpr());
206}
207
210 return;
211
212
214 killAndFlowOrigin(*ILE, *ILE->getInit(0));
215}
216
220 return;
221
222
223 killAndFlowOrigin(*MTE, *MTE->getSubExpr());
224}
225
226void FactsGenerator::handleLifetimeEnds(const CFGLifetimeEnds &LifetimeEnds) {
227
229 if (!LifetimeEndsVD)
230 return;
231
233 if (const auto *BL = dyn_cast(Loan)) {
234
235
236 if (BL->getAccessPath().D == LifetimeEndsVD)
239 }
240 }
241}
242
243void FactsGenerator::handleGSLPointerConstruction(const CXXConstructExpr *CCE) {
245 if (CCE->getNumArgs() != 1)
246 return;
248 killAndFlowOrigin(*CCE, *CCE->getArg(0));
249 else
250
251 handleFunctionCall(CCE, CCE->getConstructor(),
252 {CCE->getArgs(), CCE->getNumArgs()},
253 true);
254}
255
256
257
258
259
260void FactsGenerator::handleFunctionCall(const Expr *Call,
261 const FunctionDecl *FD,
262 ArrayRef<const Expr *> Args,
263 bool IsGslConstruction) {
264
266 return;
267 auto IsArgLifetimeBound = [FD](unsigned I) -> bool {
268 const ParmVarDecl *PVD = nullptr;
269 if (const auto *Method = dyn_cast(FD);
271 if (I == 0)
272
274 if ((I - 1) < Method->getNumParams())
275
276
277 PVD = Method->getParamDecl(I - 1);
278 } else if (I < FD->getNumParams())
279
280 PVD = FD->getParamDecl(I);
281 return PVD ? PVD->hasAttrclang::LifetimeBoundAttr() : false;
282 };
283 if (Args.empty())
284 return;
285 bool killedSrc = false;
286 for (unsigned I = 0; I < Args.size(); ++I)
287 if (IsGslConstruction || IsArgLifetimeBound(I)) {
288 if (!killedSrc) {
289 killedSrc = true;
290 killAndFlowOrigin(*Call, *Args[I]);
291 } else
292 flowOrigin(*Call, *Args[I]);
293 }
294}
295
296
297
298bool FactsGenerator::handleTestPoint(const CXXFunctionalCastExpr *FCE) {
299 if (!FCE->getType()->isVoidType())
300 return false;
301
302 const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();
303 if (const auto *SL = dyn_cast(SubExpr)) {
304 llvm::StringRef LiteralValue = SL->getString();
305 const std::string Prefix = "__lifetime_test_point_";
306
307 if (LiteralValue.starts_with(Prefix)) {
308 StringRef Annotation = LiteralValue.drop_front(Prefix.length());
309 CurrentBlockFacts.push_back(
310 FactMgr.createFact(Annotation));
311 return true;
312 }
313 }
314 return false;
315}
316
317void FactsGenerator::handleAssignment(const Expr *LHSExpr,
318 const Expr *RHSExpr) {
320 return;
321
322 if (const auto *DRE_LHS =
323 dyn_cast(LHSExpr->IgnoreParenImpCasts())) {
324 markUseAsWrite(DRE_LHS);
325 if (const auto *VD_LHS = dyn_cast(DRE_LHS->getDecl())) {
326
327
328 killAndFlowOrigin(*VD_LHS, *RHSExpr);
329 }
330 }
331}
332
333
334
335
336void FactsGenerator::handleUse(const DeclRefExpr *DRE) {
338 UseFact *UF = FactMgr.createFact(DRE, FactMgr.getOriginMgr());
339 CurrentBlockFacts.push_back(UF);
340 assert(!UseFacts.contains(DRE));
341 UseFacts[DRE] = UF;
342 }
343}
344
345void FactsGenerator::markUseAsWrite(const DeclRefExpr *DRE) {
347 return;
348 assert(UseFacts.contains(DRE));
349 UseFacts[DRE]->markAsWritten();
350}
351
352
353
354llvm::SmallVector<Fact *> FactsGenerator::issuePlaceholderLoans() {
355 const auto *FD = dyn_cast(AC.getDecl());
356 if (!FD)
357 return {};
358
359 llvm::SmallVector<Fact *> PlaceholderLoanFacts;
360 for (const ParmVarDecl *PVD : FD->parameters()) {
362 const PlaceholderLoan *L =
363 FactMgr.getLoanMgr().createLoan(PVD);
364 OriginID OID = FactMgr.getOriginMgr().getOrCreate(*PVD);
365 PlaceholderLoanFacts.push_back(
366 FactMgr.createFact(L->getID(), OID));
367 }
368 }
369 return PlaceholderLoanFacts;
370}
371
372}
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isAssignmentOp(Opcode Opc)
Represents a single basic block in a source-level CFG.
Represents a top-level expression in a basic block.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Represents the point where the lifetime of an automatic object ends.
const Stmt * getTriggerStmt() const
const VarDecl * getVarDecl() const
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Represents a call to a C++ constructor.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr....
Represents a call to a member function that may be written either with member call syntax (e....
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Represents a static or instance method of a struct/union/class.
The null pointer literal (C++11 [lex.nullptr])
A call to an overloaded operator written using operator syntax.
static bool isAssignmentOp(OverloadedOperatorKind Opc)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
ConditionalOperator - The ?
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Describes an C or C++ initializer list.
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
A (possibly-)qualified type.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
RetTy Visit(PTR(Stmt) S, ParamTys... P)
SourceLocation getEndLoc() const LLVM_READONLY
bool isPointerOrReferenceType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represents a variable declaration or definition.
FactType * createFact(Args &&...args)
LoanManager & getLoanMgr()
void VisitDeclRefExpr(const DeclRefExpr *DRE)
Definition FactsGenerator.cpp:78
void VisitBinaryOperator(const BinaryOperator *BO)
Definition FactsGenerator.cpp:172
void VisitCallExpr(const CallExpr *CE)
Definition FactsGenerator.cpp:127
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE)
Definition FactsGenerator.cpp:217
void VisitReturnStmt(const ReturnStmt *RS)
Definition FactsGenerator.cpp:162
void VisitCXXConstructExpr(const CXXConstructExpr *CCE)
Definition FactsGenerator.cpp:99
void VisitImplicitCastExpr(const ImplicitCastExpr *ICE)
Definition FactsGenerator.cpp:139
void run()
Definition FactsGenerator.cpp:44
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE)
Definition FactsGenerator.cpp:198
void VisitInitListExpr(const InitListExpr *ILE)
Definition FactsGenerator.cpp:208
void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N)
Definition FactsGenerator.cpp:132
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE)
Definition FactsGenerator.cpp:186
void VisitUnaryOperator(const UnaryOperator *UO)
Definition FactsGenerator.cpp:147
void VisitDeclStmt(const DeclStmt *DS)
Definition FactsGenerator.cpp:70
void VisitConditionalOperator(const ConditionalOperator *CO)
Definition FactsGenerator.cpp:177
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE)
Definition FactsGenerator.cpp:106
llvm::ArrayRef< const Loan * > getLoans() const
LoanType * createLoan(Args &&...args)
An abstract base class for a single "Loan" which represents lending a storage in memory.
PathLoan represents lending a storage location that is visible within the function's scope (e....
static const PathLoan * createLoan(FactManager &FactMgr, const DeclRefExpr *DRE)
Creates a loan for the storage path of a given declaration reference.
Definition FactsGenerator.cpp:34
static bool hasOrigin(const Expr *E)
Definition FactsGenerator.cpp:22
utils::ID< struct OriginTag > OriginID
static bool isPointerType(QualType QT)
Definition FactsGenerator.cpp:18
bool isGslPointerType(QualType QT)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
Represents the storage location being borrowed, e.g., a specific stack variable.