clang: include/clang/Analysis/Analyses/ThreadSafetyCommon.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
22#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
23
32#include "llvm/ADT/DenseMap.h"
33#include "llvm/ADT/PointerIntPair.h"
34#include "llvm/ADT/PointerUnion.h"
35#include "llvm/ADT/SmallVector.h"
36#include "llvm/Support/Casting.h"
37#include
38#include
39#include
40#include
41
43
44class AbstractConditionalOperator;
45class ArraySubscriptExpr;
46class BinaryOperator;
47class CallExpr;
48class CastExpr;
49class CXXDestructorDecl;
50class CXXMemberCallExpr;
51class CXXOperatorCallExpr;
52class CXXThisExpr;
53class DeclRefExpr;
54class DeclStmt;
55class Expr;
56class MemberExpr;
57class Stmt;
58class UnaryOperator;
59
60namespace threadSafety {
61
62
63namespace sx {
64
67}
68
70
71
72
73 if (isatil::Wildcard(E1))
74 return isatil::Wildcard(E2);
75 if (isatil::Wildcard(E2))
76 return isatil::Wildcard(E1);
77
79}
80
82 const auto *PE1 = dyn_cast_or_nulltil::Project(E1);
83 if (!PE1)
84 return false;
85 const auto *PE2 = dyn_cast_or_nulltil::Project(E2);
86 if (!PE2)
87 return false;
88 return PE1->clangDecl() == PE2->clangDecl();
89}
90
92 std::stringstream ss;
94 return ss.str();
95}
96
97}
98
99
100
101
103
105
106
107 void enterCFGBlock(const CFGBlock *B) {}
108
109
110 bool visitPredecessors() { return true; }
111
112
113 void handlePredecessor(const CFGBlock *Pred) {}
114
115
116 void handlePredecessorBackEdge(const CFGBlock *Pred) {}
117
118
119 void enterCFGBlockBody(const CFGBlock *B) {}
120
121
122 void handleStatement(const Stmt *S) {}
123
124
126
127
128 void exitCFGBlockBody(const CFGBlock *B) {}
129
130
131 bool visitSuccessors() { return true; }
132
133
134 void handleSuccessor(const CFGBlock *Succ) {}
135
136
137 void handleSuccessorBackEdge(const CFGBlock *Succ) {}
138
139
140 void exitCFGBlock(const CFGBlock *B) {}
141
142
144};
145
146
148public:
150
151
152
154 ACtx = ∾
155 CFGraph = AC.getCFG();
156 if (!CFGraph)
157 return false;
158
159
160 if (!isa_and_nonnull(AC.getDecl()))
161 return false;
162
164 if (!SortedGraph)
165 return false;
166
167 return true;
168 }
169
170
171 template
174
176
177 for (const auto *CurrBlock : *SortedGraph) {
178 VisitedBlocks.insert(CurrBlock);
179
180 V.enterCFGBlock(CurrBlock);
181
182
183 if (V.visitPredecessors()) {
185
187 SE = CurrBlock->pred_end();
188 SI != SE; ++SI) {
189 if (*SI == nullptr)
190 continue;
191
192 if (!VisitedBlocks.alreadySet(*SI)) {
193 BackEdges.push_back(*SI);
194 continue;
195 }
196 V.handlePredecessor(*SI);
197 }
198
199 for (auto *Blk : BackEdges)
200 V.handlePredecessorBackEdge(Blk);
201 }
202
203 V.enterCFGBlockBody(CurrBlock);
204
205
206 for (const auto &BI : *CurrBlock) {
207 switch (BI.getKind()) {
210 break;
211
217 V.handleDestructorCall(VD, DD);
218 break;
219 }
220 default:
221 break;
222 }
223 }
224
225 V.exitCFGBlockBody(CurrBlock);
226
227
228 if (V.visitSuccessors()) {
230
231
233 SE = CurrBlock->succ_end();
234 SI != SE; ++SI) {
235 if (*SI == nullptr)
236 continue;
237
238 if (!VisitedBlocks.alreadySet(*SI)) {
239 ForwardEdges.push_back(*SI);
240 continue;
241 }
242 V.handleSuccessorBackEdge(*SI);
243 }
244
245 for (auto *Blk : ForwardEdges)
246 V.handleSuccessor(Blk);
247 }
248
249 V.exitCFGBlock(CurrBlock);
250 }
251 V.exitCFG(&CFGraph->getExit());
252 }
253
256
258 return dyn_cast(ACtx->getDecl());
259 }
260
262
263private:
264 CFG *CFGraph = nullptr;
267};
268
269
270
271
273private:
274
275 llvm::PointerIntPair<const til::SExpr *, 1, bool> CapExpr;
276
277
278 StringRef CapKind;
279
280public:
283 : CapExpr(E, Neg), CapKind(Kind) {}
284
285
287
289 StringRef getKind() const { return CapKind; }
290 bool negative() const { return CapExpr.getInt(); }
291
293 return CapabilityExpr(CapExpr.getPointer(), CapKind, !CapExpr.getInt());
294 }
295
299 }
300
304 }
305
308 }
309
313 }
314
317 return nullptr;
318 if (const auto *P = dyn_casttil::Project(sexpr()))
319 return P->clangDecl();
320 if (const auto *P = dyn_casttil::LiteralPtr(sexpr()))
321 return P->clangDecl();
322 return nullptr;
323 }
324
329 }
330
332
333 bool isInvalid() const { return isa_and_nonnulltil::Undefined(sexpr()); }
334
335 bool isUniversal() const { return isa_and_nonnulltil::Wildcard(sexpr()); }
336};
337
338
340public:
341
342
343
344
345
346
347
348
349
351
353
354
356
357
358 llvm::PointerUnion<const Expr *, til::SExpr *> SelfArg = nullptr;
359
360
362
363
364 llvm::PointerUnion<const Expr *const *, til::SExpr *> FunArgs = nullptr;
365
366
368
371 };
372
374
377 }
378
379
380
382 const Expr *DeclExp,
384
386
387
389
390
391 std::pair<til::LiteralPtr *, StringRef>
393
394
395
396
399
401
404 }
405
408
409private:
410
412
420 const Expr *SelfE = nullptr);
438 til::SExpr *translateAbstractConditionalOperator(
440
442
443
444 using StatementMap = llvm::DenseMap<const Stmt *, til::SExpr *>;
445
446
447 using LVarIndexMap = llvm::DenseMap<const ValueDecl *, unsigned>;
448
449
450 using NameVarPair = std::pair<const ValueDecl *, til::SExpr *>;
452
453 struct BlockInfo {
455 bool HasBackEdges = false;
456
457
458 unsigned UnprocessedSuccessors = 0;
459
460
461 unsigned ProcessedPredecessors = 0;
462
463 BlockInfo() = default;
464 BlockInfo(BlockInfo &&) = default;
465 BlockInfo &operator=(BlockInfo &&) = default;
466 };
467
469 void enterCFGBlock(const CFGBlock *B);
470 bool visitPredecessors() { return true; }
471 void handlePredecessor(const CFGBlock *Pred);
472 void handlePredecessorBackEdge(const CFGBlock *Pred);
473 void enterCFGBlockBody(const CFGBlock *B);
474 void handleStatement(const Stmt *S);
476 void exitCFGBlockBody(const CFGBlock *B);
477 bool visitSuccessors() { return true; }
478 void handleSuccessor(const CFGBlock *Succ);
479 void handleSuccessorBackEdge(const CFGBlock *Succ);
480 void exitCFGBlock(const CFGBlock *B);
481 void exitCFG(const CFGBlock *Last);
482
483 void insertStmt(const Stmt *S, til::SExpr *E) {
484 SMap.insert(std::make_pair(S, E));
485 }
486
487 til::SExpr *addStatement(til::SExpr *E, const Stmt *S,
488 const ValueDecl *VD = nullptr);
489 til::SExpr *lookupVarDecl(const ValueDecl *VD);
490 til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E);
491 til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E);
492
493 void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E);
494 void mergeEntryMap(LVarDefinitionMap Map);
495 void mergeEntryMapBackEdge();
496 void mergePhiNodesBackEdge(const CFGBlock *Blk);
497
498private:
499
500
501 static const bool CapabilityExprMode = true;
502
503 til::MemRegionRef Arena;
504
505
506 til::Variable *SelfVar = nullptr;
507
508 til::SCFG *Scfg = nullptr;
509
510
511 StatementMap SMap;
512
513
514 LVarIndexMap LVarIdxMap;
515
516
517 std::vector<til::BasicBlock *> BlockMap;
518
519
520 std::vector BBInfo;
521
522 LVarDefinitionMap CurrentLVarMap;
523 std::vector<til::Phi *> CurrentArguments;
524 std::vector<til::SExpr *> CurrentInstructions;
525 std::vector<til::Phi *> IncompleteArgs;
526 til::BasicBlock *CurrentBB = nullptr;
527 BlockInfo *CurrentBlockInfo = nullptr;
528};
529
530#ifndef NDEBUG
531
532void printSCFG(CFGWalker &Walker);
533#endif
534
535}
536}
537
538#endif
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
llvm::DenseMap< const Stmt *, CFGBlock * > SMap
enum clang::sema::@1725::IndirectLocalPathEntry::EntryKind Kind
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
SExprBuilder::CallingContext CallingContext
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const Decl * getDecl() const
ASTContext & getASTContext() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
A builtin binary operation expression such as "x + y" or "x <= y".
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
Represents a single basic block in a source-level CFG.
AdjacentBlocks::const_iterator const_pred_iterator
unsigned getBlockID() const
AdjacentBlocks::const_iterator const_succ_iterator
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
const Stmt * getStmt() const
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Represents a C++ destructor within a class.
Represents a call to a member function that may be written either with member call syntax (e....
A call to an overloaded operator written using operator syntax.
Represents the this expression in C++.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
This represents one expression.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
This represents a decl that may have a name.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Implements a set of CFGBlocks using a BitVector.
std::pair< std::nullopt_t, bool > insert(const CFGBlock *Block)
Set the bit associated with a particular CFGBlock.
bool alreadySet(const CFGBlock *Block)
Check if the bit for a CFGBlock has been already set.
Stmt - This represents one statement.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
const PostOrderCFGView * getSortedGraph() const
const NamedDecl * getDecl() const
bool init(AnalysisDeclContext &AC)
const CFG * getGraph() const
CapabilityExpr operator!() const
bool shouldIgnore() const
CapabilityExpr(const til::SExpr *E, StringRef Kind, bool Neg)
bool matches(const CapabilityExpr &other) const
bool partiallyMatches(const CapabilityExpr &other) const
CapabilityExpr(const til::SExpr *, T, bool)=delete
bool equals(const CapabilityExpr &other) const
const til::SExpr * sexpr() const
bool matchesUniv(const CapabilityExpr &CapE) const
std::string toString() const
const ValueDecl * valueDecl() const
StringRef getKind() const
const til::SCFG * getCFG() const
CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D, const Expr *DeclExp, til::SExpr *Self=nullptr)
Translate a clang expression in an attribute to a til::SExpr.
til::SExpr * translate(const Stmt *S, CallingContext *Ctx)
SExprBuilder(til::MemRegionRef A)
std::pair< til::LiteralPtr *, StringRef > createThisPlaceholder(const Expr *Exp)
til::SExpr * lookupStmt(const Stmt *S)
til::SCFG * buildCFG(CFGWalker &Walker)
til::LiteralPtr * createVariable(const VarDecl *VD)
til::BasicBlock * lookupBlock(const CFGBlock *B)
A basic block is part of an SCFG.
static bool compareExprs(const SExpr *E1, const SExpr *E2)
A Literal pointer to an object allocated in memory.
static bool compareExprs(const SExpr *E1, const SExpr *E2)
static void print(const SExpr *E, std::ostream &SS)
An SCFG is a control-flow graph.
Base class for AST nodes in the typed intermediate language.
@ VK_SFun
SFunction (self) parameter.
void setKind(VariableKind K)
bool matches(const til::SExpr *E1, const til::SExpr *E2)
bool equals(const til::SExpr *E1, const til::SExpr *E2)
std::string toString(const til::SExpr *E)
bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2)
TIL_BinaryOpcode
Opcode for binary arithmetic operations.
void printSCFG(CFGWalker &Walker)
The JSON file list parser is used to communicate input to InstallAPI.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
const FunctionProtoType * T
Encapsulates the lexical context of a function call.
llvm::PointerUnion< const Expr *const *, til::SExpr * > FunArgs
const NamedDecl * AttrDecl
CallingContext(CallingContext *P, const NamedDecl *D=nullptr)
llvm::PointerUnion< const Expr *, til::SExpr * > SelfArg