1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/Analysis/CFG.h" |
15 | #include "clang/AST/ASTContext.h" |
16 | #include "clang/AST/Attr.h" |
17 | #include "clang/AST/Decl.h" |
18 | #include "clang/AST/DeclBase.h" |
19 | #include "clang/AST/DeclCXX.h" |
20 | #include "clang/AST/DeclGroup.h" |
21 | #include "clang/AST/Expr.h" |
22 | #include "clang/AST/ExprCXX.h" |
23 | #include "clang/AST/OperationKinds.h" |
24 | #include "clang/AST/PrettyPrinter.h" |
25 | #include "clang/AST/Stmt.h" |
26 | #include "clang/AST/StmtCXX.h" |
27 | #include "clang/AST/StmtObjC.h" |
28 | #include "clang/AST/StmtVisitor.h" |
29 | #include "clang/AST/Type.h" |
30 | #include "clang/Analysis/Support/BumpVector.h" |
31 | #include "clang/Analysis/ConstructionContext.h" |
32 | #include "clang/Basic/Builtins.h" |
33 | #include "clang/Basic/ExceptionSpecificationType.h" |
34 | #include "clang/Basic/LLVM.h" |
35 | #include "clang/Basic/LangOptions.h" |
36 | #include "clang/Basic/SourceLocation.h" |
37 | #include "clang/Basic/Specifiers.h" |
38 | #include "llvm/ADT/APInt.h" |
39 | #include "llvm/ADT/APSInt.h" |
40 | #include "llvm/ADT/ArrayRef.h" |
41 | #include "llvm/ADT/DenseMap.h" |
42 | #include "llvm/ADT/Optional.h" |
43 | #include "llvm/ADT/STLExtras.h" |
44 | #include "llvm/ADT/SetVector.h" |
45 | #include "llvm/ADT/SmallPtrSet.h" |
46 | #include "llvm/ADT/SmallVector.h" |
47 | #include "llvm/Support/Allocator.h" |
48 | #include "llvm/Support/Casting.h" |
49 | #include "llvm/Support/Compiler.h" |
50 | #include "llvm/Support/DOTGraphTraits.h" |
51 | #include "llvm/Support/ErrorHandling.h" |
52 | #include "llvm/Support/Format.h" |
53 | #include "llvm/Support/GraphWriter.h" |
54 | #include "llvm/Support/SaveAndRestore.h" |
55 | #include "llvm/Support/raw_ostream.h" |
56 | #include <cassert> |
57 | #include <memory> |
58 | #include <string> |
59 | #include <tuple> |
60 | #include <utility> |
61 | #include <vector> |
62 | |
63 | using namespace clang; |
64 | |
65 | static SourceLocation GetEndLoc(Decl *D) { |
66 | if (VarDecl *VD = dyn_cast<VarDecl>(D)) |
67 | if (Expr *Ex = VD->getInit()) |
68 | return Ex->getSourceRange().getEnd(); |
69 | return D->getLocation(); |
70 | } |
71 | |
72 | |
73 | |
74 | static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) { |
75 | E = E->IgnoreParens(); |
76 | if (isa<IntegerLiteral>(E)) |
77 | return E; |
78 | if (auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) |
79 | return isa<EnumConstantDecl>(DR->getDecl()) ? DR : nullptr; |
80 | return nullptr; |
81 | } |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | static std::tuple<const DeclRefExpr *, BinaryOperatorKind, const Expr *> |
89 | tryNormalizeBinaryOperator(const BinaryOperator *B) { |
90 | BinaryOperatorKind Op = B->getOpcode(); |
91 | |
92 | const Expr *MaybeDecl = B->getLHS(); |
93 | const Expr *Constant = tryTransformToIntOrEnumConstant(B->getRHS()); |
94 | |
95 | if (Constant == nullptr) { |
96 | |
97 | if (Op == BO_GT) |
98 | Op = BO_LT; |
99 | else if (Op == BO_GE) |
100 | Op = BO_LE; |
101 | else if (Op == BO_LT) |
102 | Op = BO_GT; |
103 | else if (Op == BO_LE) |
104 | Op = BO_GE; |
105 | |
106 | MaybeDecl = B->getRHS(); |
107 | Constant = tryTransformToIntOrEnumConstant(B->getLHS()); |
108 | } |
109 | |
110 | auto *D = dyn_cast<DeclRefExpr>(MaybeDecl->IgnoreParenImpCasts()); |
111 | return std::make_tuple(D, Op, Constant); |
112 | } |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) { |
121 | |
122 | |
123 | if (isa<IntegerLiteral>(E1) != isa<IntegerLiteral>(E2)) |
124 | return false; |
125 | |
126 | |
127 | if (isa<IntegerLiteral>(E1)) |
128 | return true; |
129 | |
130 | |
131 | |
132 | (E1) && isa(E2)", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 132, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2)); |
133 | auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl(); |
134 | auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl(); |
135 | |
136 | (Decl1) && isa(Decl2)", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 136, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2)); |
137 | const DeclContext *DC1 = Decl1->getDeclContext(); |
138 | const DeclContext *DC2 = Decl2->getDeclContext(); |
139 | |
140 | (DC1) && isa(DC2)", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 140, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2)); |
141 | return DC1 == DC2; |
142 | } |
143 | |
144 | namespace { |
145 | |
146 | class CFGBuilder; |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | class AddStmtChoice { |
161 | public: |
162 | enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; |
163 | |
164 | AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} |
165 | |
166 | bool alwaysAdd(CFGBuilder &builder, |
167 | const Stmt *stmt) const; |
168 | |
169 | |
170 | |
171 | AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { |
172 | return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); |
173 | } |
174 | |
175 | private: |
176 | Kind kind; |
177 | }; |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | class LocalScope { |
201 | public: |
202 | friend class const_iterator; |
203 | |
204 | using AutomaticVarsTy = BumpVector<VarDecl *>; |
205 | |
206 | |
207 | |
208 | class const_iterator { |
209 | const LocalScope* Scope = nullptr; |
210 | |
211 | |
212 | |
213 | unsigned VarIter = 0; |
214 | |
215 | public: |
216 | |
217 | |
218 | |
219 | const_iterator() = default; |
220 | |
221 | |
222 | |
223 | const_iterator(const LocalScope& S, unsigned I) |
224 | : Scope(&S), VarIter(I) { |
225 | |
226 | |
227 | if (VarIter == 0 && Scope) |
228 | *this = Scope->Prev; |
229 | } |
230 | |
231 | VarDecl *const* operator->() const { |
232 | (0) . __assert_fail ("Scope && \"Dereferencing invalid iterator is not allowed\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 232, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Scope && "Dereferencing invalid iterator is not allowed"); |
233 | (0) . __assert_fail ("VarIter != 0 && \"Iterator has invalid value of VarIter member\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 233, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VarIter != 0 && "Iterator has invalid value of VarIter member"); |
234 | return &Scope->Vars[VarIter - 1]; |
235 | } |
236 | |
237 | const VarDecl *getFirstVarInScope() const { |
238 | (0) . __assert_fail ("Scope && \"Dereferencing invalid iterator is not allowed\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 238, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Scope && "Dereferencing invalid iterator is not allowed"); |
239 | (0) . __assert_fail ("VarIter != 0 && \"Iterator has invalid value of VarIter member\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 239, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VarIter != 0 && "Iterator has invalid value of VarIter member"); |
240 | return Scope->Vars[0]; |
241 | } |
242 | |
243 | VarDecl *operator*() const { |
244 | return *this->operator->(); |
245 | } |
246 | |
247 | const_iterator &operator++() { |
248 | if (!Scope) |
249 | return *this; |
250 | |
251 | (0) . __assert_fail ("VarIter != 0 && \"Iterator has invalid value of VarIter member\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 251, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VarIter != 0 && "Iterator has invalid value of VarIter member"); |
252 | --VarIter; |
253 | if (VarIter == 0) |
254 | *this = Scope->Prev; |
255 | return *this; |
256 | } |
257 | const_iterator operator++(int) { |
258 | const_iterator P = *this; |
259 | ++*this; |
260 | return P; |
261 | } |
262 | |
263 | bool operator==(const const_iterator &rhs) const { |
264 | return Scope == rhs.Scope && VarIter == rhs.VarIter; |
265 | } |
266 | bool operator!=(const const_iterator &rhs) const { |
267 | return !(*this == rhs); |
268 | } |
269 | |
270 | explicit operator bool() const { |
271 | return *this != const_iterator(); |
272 | } |
273 | |
274 | int distance(const_iterator L); |
275 | const_iterator shared_parent(const_iterator L); |
276 | bool pointsToFirstDeclaredVar() { return VarIter == 1; } |
277 | }; |
278 | |
279 | private: |
280 | BumpVectorContext ctx; |
281 | |
282 | |
283 | AutomaticVarsTy Vars; |
284 | |
285 | |
286 | |
287 | const_iterator Prev; |
288 | |
289 | public: |
290 | |
291 | LocalScope(BumpVectorContext ctx, const_iterator P) |
292 | : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {} |
293 | |
294 | |
295 | const_iterator begin() const { return const_iterator(*this, Vars.size()); } |
296 | |
297 | void addVar(VarDecl *VD) { |
298 | Vars.push_back(VD, ctx); |
299 | } |
300 | }; |
301 | |
302 | } |
303 | |
304 | |
305 | |
306 | |
307 | int LocalScope::const_iterator::distance(LocalScope::const_iterator L) { |
308 | int D = 0; |
309 | const_iterator F = *this; |
310 | while (F.Scope != L.Scope) { |
311 | (0) . __assert_fail ("F != const_iterator() && \"L iterator is not reachable from F iterator.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 312, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(F != const_iterator() && |
312 | (0) . __assert_fail ("F != const_iterator() && \"L iterator is not reachable from F iterator.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 312, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "L iterator is not reachable from F iterator."); |
313 | D += F.VarIter; |
314 | F = F.Scope->Prev; |
315 | } |
316 | D += F.VarIter - L.VarIter; |
317 | return D; |
318 | } |
319 | |
320 | |
321 | |
322 | |
323 | |
324 | LocalScope::const_iterator |
325 | LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) { |
326 | llvm::SmallPtrSet<const LocalScope *, 4> ScopesOfL; |
327 | while (true) { |
328 | ScopesOfL.insert(L.Scope); |
329 | if (L == const_iterator()) |
330 | break; |
331 | L = L.Scope->Prev; |
332 | } |
333 | |
334 | const_iterator F = *this; |
335 | while (true) { |
336 | if (ScopesOfL.count(F.Scope)) |
337 | return F; |
338 | (0) . __assert_fail ("F != const_iterator() && \"L iterator is not reachable from F iterator.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 339, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(F != const_iterator() && |
339 | (0) . __assert_fail ("F != const_iterator() && \"L iterator is not reachable from F iterator.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 339, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "L iterator is not reachable from F iterator."); |
340 | F = F.Scope->Prev; |
341 | } |
342 | } |
343 | |
344 | namespace { |
345 | |
346 | |
347 | |
348 | |
349 | struct BlockScopePosPair { |
350 | CFGBlock *block = nullptr; |
351 | LocalScope::const_iterator scopePosition; |
352 | |
353 | BlockScopePosPair() = default; |
354 | BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) |
355 | : block(b), scopePosition(scopePos) {} |
356 | }; |
357 | |
358 | |
359 | |
360 | |
361 | |
362 | class TryResult { |
363 | int X = -1; |
364 | |
365 | public: |
366 | TryResult() = default; |
367 | TryResult(bool b) : X(b ? 1 : 0) {} |
368 | |
369 | bool isTrue() const { return X == 1; } |
370 | bool isFalse() const { return X == 0; } |
371 | bool isKnown() const { return X >= 0; } |
372 | |
373 | void negate() { |
374 | assert(isKnown()); |
375 | X ^= 0x1; |
376 | } |
377 | }; |
378 | |
379 | } |
380 | |
381 | static TryResult bothKnownTrue(TryResult R1, TryResult R2) { |
382 | if (!R1.isKnown() || !R2.isKnown()) |
383 | return TryResult(); |
384 | return TryResult(R1.isTrue() && R2.isTrue()); |
385 | } |
386 | |
387 | namespace { |
388 | |
389 | class reverse_children { |
390 | llvm::SmallVector<Stmt *, 12> childrenBuf; |
391 | ArrayRef<Stmt *> children; |
392 | |
393 | public: |
394 | reverse_children(Stmt *S); |
395 | |
396 | using iterator = ArrayRef<Stmt *>::reverse_iterator; |
397 | |
398 | iterator begin() const { return children.rbegin(); } |
399 | iterator end() const { return children.rend(); } |
400 | }; |
401 | |
402 | } |
403 | |
404 | reverse_children::reverse_children(Stmt *S) { |
405 | if (CallExpr *CE = dyn_cast<CallExpr>(S)) { |
406 | children = CE->getRawSubExprs(); |
407 | return; |
408 | } |
409 | switch (S->getStmtClass()) { |
410 | |
411 | case Stmt::InitListExprClass: { |
412 | InitListExpr *IE = cast<InitListExpr>(S); |
413 | children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()), |
414 | IE->getNumInits()); |
415 | return; |
416 | } |
417 | default: |
418 | break; |
419 | } |
420 | |
421 | |
422 | for (Stmt *SubStmt : S->children()) |
423 | childrenBuf.push_back(SubStmt); |
424 | |
425 | |
426 | children = childrenBuf; |
427 | } |
428 | |
429 | namespace { |
430 | |
431 | |
432 | |
433 | |
434 | |
435 | |
436 | |
437 | |
438 | |
439 | |
440 | |
441 | |
442 | |
443 | |
444 | class CFGBuilder { |
445 | using JumpTarget = BlockScopePosPair; |
446 | using JumpSource = BlockScopePosPair; |
447 | |
448 | ASTContext *Context; |
449 | std::unique_ptr<CFG> cfg; |
450 | |
451 | |
452 | CFGBlock *Block = nullptr; |
453 | |
454 | |
455 | CFGBlock *Succ = nullptr; |
456 | |
457 | JumpTarget ContinueJumpTarget; |
458 | JumpTarget BreakJumpTarget; |
459 | JumpTarget SEHLeaveJumpTarget; |
460 | CFGBlock *SwitchTerminatedBlock = nullptr; |
461 | CFGBlock *DefaultCaseBlock = nullptr; |
462 | |
463 | |
464 | |
465 | CFGBlock *TryTerminatedBlock = nullptr; |
466 | |
467 | |
468 | LocalScope::const_iterator ScopePos; |
469 | |
470 | |
471 | using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>; |
472 | LabelMapTy LabelMap; |
473 | |
474 | |
475 | |
476 | using BackpatchBlocksTy = std::vector<JumpSource>; |
477 | BackpatchBlocksTy BackpatchBlocks; |
478 | |
479 | |
480 | using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>; |
481 | LabelSetTy AddressTakenLabels; |
482 | |
483 | |
484 | |
485 | |
486 | llvm::DenseMap<Expr *, const ConstructionContextLayer *> |
487 | ConstructionContextMap; |
488 | |
489 | using DeclsWithEndedScopeSetTy = llvm::SmallSetVector<VarDecl *, 16>; |
490 | DeclsWithEndedScopeSetTy DeclsWithEndedScope; |
491 | |
492 | bool badCFG = false; |
493 | const CFG::BuildOptions &BuildOpts; |
494 | |
495 | |
496 | bool switchExclusivelyCovered = false; |
497 | Expr::EvalResult *switchCond = nullptr; |
498 | |
499 | CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr; |
500 | const Stmt *lastLookup = nullptr; |
501 | |
502 | |
503 | |
504 | using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>; |
505 | CachedBoolEvalsTy CachedBoolEvals; |
506 | |
507 | public: |
508 | explicit CFGBuilder(ASTContext *astContext, |
509 | const CFG::BuildOptions &buildOpts) |
510 | : Context(astContext), cfg(new CFG()), |
511 | ConstructionContextMap(), BuildOpts(buildOpts) {} |
512 | |
513 | |
514 | |
515 | std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement); |
516 | |
517 | bool alwaysAdd(const Stmt *stmt); |
518 | |
519 | private: |
520 | |
521 | CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); |
522 | CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); |
523 | CFGBlock *VisitBreakStmt(BreakStmt *B); |
524 | CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); |
525 | CFGBlock *VisitCaseStmt(CaseStmt *C); |
526 | CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); |
527 | CFGBlock *VisitCompoundStmt(CompoundStmt *C); |
528 | CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, |
529 | AddStmtChoice asc); |
530 | CFGBlock *VisitContinueStmt(ContinueStmt *C); |
531 | CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, |
532 | AddStmtChoice asc); |
533 | CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); |
534 | CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); |
535 | CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc); |
536 | CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc); |
537 | CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); |
538 | CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, |
539 | AddStmtChoice asc); |
540 | CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, |
541 | AddStmtChoice asc); |
542 | CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); |
543 | CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); |
544 | CFGBlock *VisitDeclStmt(DeclStmt *DS); |
545 | CFGBlock *VisitDeclSubExpr(DeclStmt *DS); |
546 | CFGBlock *VisitDefaultStmt(DefaultStmt *D); |
547 | CFGBlock *VisitDoStmt(DoStmt *D); |
548 | CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); |
549 | CFGBlock *VisitForStmt(ForStmt *F); |
550 | CFGBlock *VisitGotoStmt(GotoStmt *G); |
551 | CFGBlock *VisitIfStmt(IfStmt *I); |
552 | CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); |
553 | CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc); |
554 | CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); |
555 | CFGBlock *VisitLabelStmt(LabelStmt *L); |
556 | CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc); |
557 | CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc); |
558 | CFGBlock *VisitLogicalOperator(BinaryOperator *B); |
559 | std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B, |
560 | Stmt *Term, |
561 | CFGBlock *TrueBlock, |
562 | CFGBlock *FalseBlock); |
563 | CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE, |
564 | AddStmtChoice asc); |
565 | CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); |
566 | CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); |
567 | CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); |
568 | CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); |
569 | CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); |
570 | CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); |
571 | CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); |
572 | CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc); |
573 | CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); |
574 | CFGBlock *VisitReturnStmt(Stmt *S); |
575 | CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S); |
576 | CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S); |
577 | CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S); |
578 | CFGBlock *VisitSEHTryStmt(SEHTryStmt *S); |
579 | CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); |
580 | CFGBlock *VisitSwitchStmt(SwitchStmt *S); |
581 | CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, |
582 | AddStmtChoice asc); |
583 | CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); |
584 | CFGBlock *VisitWhileStmt(WhileStmt *W); |
585 | |
586 | CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); |
587 | CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); |
588 | CFGBlock *VisitChildren(Stmt *S); |
589 | CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); |
590 | |
591 | void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD, |
592 | const Stmt *S) { |
593 | if (ScopePos && (VD == ScopePos.getFirstVarInScope())) |
594 | appendScopeBegin(B, VD, S); |
595 | } |
596 | |
597 | |
598 | |
599 | |
600 | |
601 | |
602 | |
603 | |
604 | |
605 | |
606 | |
607 | |
608 | |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | |
615 | |
616 | |
617 | |
618 | |
619 | |
620 | |
621 | |
622 | |
623 | |
624 | |
625 | struct TempDtorContext { |
626 | TempDtorContext() = default; |
627 | TempDtorContext(TryResult KnownExecuted) |
628 | : IsConditional(true), KnownExecuted(KnownExecuted) {} |
629 | |
630 | |
631 | |
632 | |
633 | |
634 | |
635 | |
636 | bool needsTempDtorBranch() const { |
637 | return IsConditional && !TerminatorExpr; |
638 | } |
639 | |
640 | |
641 | |
642 | void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) { |
643 | Succ = S; |
644 | TerminatorExpr = E; |
645 | } |
646 | |
647 | const bool IsConditional = false; |
648 | const TryResult KnownExecuted = true; |
649 | CFGBlock *Succ = nullptr; |
650 | CXXBindTemporaryExpr *TerminatorExpr = nullptr; |
651 | }; |
652 | |
653 | |
654 | |
655 | CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary, |
656 | TempDtorContext &Context); |
657 | CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E, TempDtorContext &Context); |
658 | CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E, |
659 | TempDtorContext &Context); |
660 | CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors( |
661 | CXXBindTemporaryExpr *E, bool BindToTemporary, TempDtorContext &Context); |
662 | CFGBlock *VisitConditionalOperatorForTemporaryDtors( |
663 | AbstractConditionalOperator *E, bool BindToTemporary, |
664 | TempDtorContext &Context); |
665 | void InsertTempDtorDecisionBlock(const TempDtorContext &Context, |
666 | CFGBlock *FalseSucc = nullptr); |
667 | |
668 | |
669 | CFGBlock *NYS() { |
670 | badCFG = true; |
671 | return Block; |
672 | } |
673 | |
674 | |
675 | |
676 | void consumeConstructionContext(const ConstructionContextLayer *Layer, |
677 | Expr *E); |
678 | |
679 | |
680 | |
681 | |
682 | |
683 | |
684 | void findConstructionContexts(const ConstructionContextLayer *Layer, |
685 | Stmt *Child); |
686 | |
687 | |
688 | |
689 | |
690 | template <typename CallLikeExpr, |
691 | typename = typename std::enable_if< |
692 | std::is_same<CallLikeExpr, CallExpr>::value || |
693 | std::is_same<CallLikeExpr, CXXConstructExpr>::value || |
694 | std::is_same<CallLikeExpr, ObjCMessageExpr>::value>> |
695 | void findConstructionContextsForArguments(CallLikeExpr *E) { |
696 | for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { |
697 | Expr *Arg = E->getArg(i); |
698 | if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue()) |
699 | findConstructionContexts( |
700 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), |
701 | ConstructionContextItem(E, i)), |
702 | Arg); |
703 | } |
704 | } |
705 | |
706 | |
707 | |
708 | |
709 | void cleanupConstructionContext(Expr *E); |
710 | |
711 | void autoCreateBlock() { if (!Block) Block = createBlock(); } |
712 | CFGBlock *createBlock(bool add_successor = true); |
713 | CFGBlock *createNoReturnBlock(); |
714 | |
715 | CFGBlock *addStmt(Stmt *S) { |
716 | return Visit(S, AddStmtChoice::AlwaysAdd); |
717 | } |
718 | |
719 | CFGBlock *addInitializer(CXXCtorInitializer *I); |
720 | void addLoopExit(const Stmt *LoopStmt); |
721 | void addAutomaticObjDtors(LocalScope::const_iterator B, |
722 | LocalScope::const_iterator E, Stmt *S); |
723 | void addLifetimeEnds(LocalScope::const_iterator B, |
724 | LocalScope::const_iterator E, Stmt *S); |
725 | void addAutomaticObjHandling(LocalScope::const_iterator B, |
726 | LocalScope::const_iterator E, Stmt *S); |
727 | void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); |
728 | void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E, |
729 | Stmt *S); |
730 | |
731 | void getDeclsWithEndedScope(LocalScope::const_iterator B, |
732 | LocalScope::const_iterator E, Stmt *S); |
733 | |
734 | |
735 | LocalScope* createOrReuseLocalScope(LocalScope* Scope); |
736 | |
737 | void addLocalScopeForStmt(Stmt *S); |
738 | LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, |
739 | LocalScope* Scope = nullptr); |
740 | LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr); |
741 | |
742 | void addLocalScopeAndDtors(Stmt *S); |
743 | |
744 | const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) { |
745 | if (!BuildOpts.AddRichCXXConstructors) |
746 | return nullptr; |
747 | |
748 | const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E); |
749 | if (!Layer) |
750 | return nullptr; |
751 | |
752 | cleanupConstructionContext(E); |
753 | return ConstructionContext::createFromLayers(cfg->getBumpVectorContext(), |
754 | Layer); |
755 | } |
756 | |
757 | |
758 | |
759 | void appendStmt(CFGBlock *B, const Stmt *S) { |
760 | if (alwaysAdd(S) && cachedEntry) |
761 | cachedEntry->second = B; |
762 | |
763 | |
764 | (S) || cast(S)->IgnoreParens() == S", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 764, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); |
765 | B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); |
766 | } |
767 | |
768 | void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) { |
769 | if (const ConstructionContext *CC = |
770 | retrieveAndCleanupConstructionContext(CE)) { |
771 | B->appendConstructor(CE, CC, cfg->getBumpVectorContext()); |
772 | return; |
773 | } |
774 | |
775 | |
776 | B->appendStmt(CE, cfg->getBumpVectorContext()); |
777 | } |
778 | |
779 | void appendCall(CFGBlock *B, CallExpr *CE) { |
780 | if (alwaysAdd(CE) && cachedEntry) |
781 | cachedEntry->second = B; |
782 | |
783 | if (const ConstructionContext *CC = |
784 | retrieveAndCleanupConstructionContext(CE)) { |
785 | B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext()); |
786 | return; |
787 | } |
788 | |
789 | |
790 | B->appendStmt(CE, cfg->getBumpVectorContext()); |
791 | } |
792 | |
793 | void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { |
794 | B->appendInitializer(I, cfg->getBumpVectorContext()); |
795 | } |
796 | |
797 | void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) { |
798 | B->appendNewAllocator(NE, cfg->getBumpVectorContext()); |
799 | } |
800 | |
801 | void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { |
802 | B->appendBaseDtor(BS, cfg->getBumpVectorContext()); |
803 | } |
804 | |
805 | void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { |
806 | B->appendMemberDtor(FD, cfg->getBumpVectorContext()); |
807 | } |
808 | |
809 | void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) { |
810 | if (alwaysAdd(ME) && cachedEntry) |
811 | cachedEntry->second = B; |
812 | |
813 | if (const ConstructionContext *CC = |
814 | retrieveAndCleanupConstructionContext(ME)) { |
815 | B->appendCXXRecordTypedCall(ME, CC, cfg->getBumpVectorContext()); |
816 | return; |
817 | } |
818 | |
819 | B->appendStmt(const_cast<ObjCMessageExpr *>(ME), |
820 | cfg->getBumpVectorContext()); |
821 | } |
822 | |
823 | void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { |
824 | B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); |
825 | } |
826 | |
827 | void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { |
828 | B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); |
829 | } |
830 | |
831 | void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) { |
832 | B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext()); |
833 | } |
834 | |
835 | void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) { |
836 | B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext()); |
837 | } |
838 | |
839 | void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) { |
840 | B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext()); |
841 | } |
842 | |
843 | void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, |
844 | LocalScope::const_iterator B, LocalScope::const_iterator E); |
845 | |
846 | void prependAutomaticObjLifetimeWithTerminator(CFGBlock *Blk, |
847 | LocalScope::const_iterator B, |
848 | LocalScope::const_iterator E); |
849 | |
850 | const VarDecl * |
851 | prependAutomaticObjScopeEndWithTerminator(CFGBlock *Blk, |
852 | LocalScope::const_iterator B, |
853 | LocalScope::const_iterator E); |
854 | |
855 | void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) { |
856 | B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable), |
857 | cfg->getBumpVectorContext()); |
858 | } |
859 | |
860 | |
861 | |
862 | void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) { |
863 | B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock), |
864 | cfg->getBumpVectorContext()); |
865 | } |
866 | |
867 | void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) { |
868 | if (BuildOpts.AddScopes) |
869 | B->appendScopeBegin(VD, S, cfg->getBumpVectorContext()); |
870 | } |
871 | |
872 | void prependScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) { |
873 | if (BuildOpts.AddScopes) |
874 | B->prependScopeBegin(VD, S, cfg->getBumpVectorContext()); |
875 | } |
876 | |
877 | void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) { |
878 | if (BuildOpts.AddScopes) |
879 | B->appendScopeEnd(VD, S, cfg->getBumpVectorContext()); |
880 | } |
881 | |
882 | void prependScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) { |
883 | if (BuildOpts.AddScopes) |
884 | B->prependScopeEnd(VD, S, cfg->getBumpVectorContext()); |
885 | } |
886 | |
887 | |
888 | |
889 | |
890 | TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) { |
891 | const Expr *LHSExpr = B->getLHS()->IgnoreParens(); |
892 | const Expr *RHSExpr = B->getRHS()->IgnoreParens(); |
893 | |
894 | const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr); |
895 | const Expr *BoolExpr = RHSExpr; |
896 | bool IntFirst = true; |
897 | if (!IntLiteral) { |
898 | IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr); |
899 | BoolExpr = LHSExpr; |
900 | IntFirst = false; |
901 | } |
902 | |
903 | if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue()) |
904 | return TryResult(); |
905 | |
906 | llvm::APInt IntValue = IntLiteral->getValue(); |
907 | if ((IntValue == 1) || (IntValue == 0)) |
908 | return TryResult(); |
909 | |
910 | bool IntLarger = IntLiteral->getType()->isUnsignedIntegerType() || |
911 | !IntValue.isNegative(); |
912 | |
913 | BinaryOperatorKind Bok = B->getOpcode(); |
914 | if (Bok == BO_GT || Bok == BO_GE) { |
915 | |
916 | |
917 | return TryResult(IntFirst == IntLarger); |
918 | } else { |
919 | |
920 | |
921 | return TryResult(IntFirst != IntLarger); |
922 | } |
923 | } |
924 | |
925 | |
926 | |
927 | |
928 | |
929 | TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) { |
930 | const Expr *LHSExpr = B->getLHS()->IgnoreParens(); |
931 | const Expr *RHSExpr = B->getRHS()->IgnoreParens(); |
932 | |
933 | const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr); |
934 | const Expr *BoolExpr = RHSExpr; |
935 | |
936 | if (!IntLiteral) { |
937 | IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr); |
938 | BoolExpr = LHSExpr; |
939 | } |
940 | |
941 | if (!IntLiteral) |
942 | return TryResult(); |
943 | |
944 | const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr); |
945 | if (BitOp && (BitOp->getOpcode() == BO_And || |
946 | BitOp->getOpcode() == BO_Or)) { |
947 | const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens(); |
948 | const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens(); |
949 | |
950 | const IntegerLiteral *IntLiteral2 = dyn_cast<IntegerLiteral>(LHSExpr2); |
951 | |
952 | if (!IntLiteral2) |
953 | IntLiteral2 = dyn_cast<IntegerLiteral>(RHSExpr2); |
954 | |
955 | if (!IntLiteral2) |
956 | return TryResult(); |
957 | |
958 | llvm::APInt L1 = IntLiteral->getValue(); |
959 | llvm::APInt L2 = IntLiteral2->getValue(); |
960 | if ((BitOp->getOpcode() == BO_And && (L2 & L1) != L1) || |
961 | (BitOp->getOpcode() == BO_Or && (L2 | L1) != L1)) { |
962 | if (BuildOpts.Observer) |
963 | BuildOpts.Observer->compareBitwiseEquality(B, |
964 | B->getOpcode() != BO_EQ); |
965 | TryResult(B->getOpcode() != BO_EQ); |
966 | } |
967 | } else if (BoolExpr->isKnownToHaveBooleanValue()) { |
968 | llvm::APInt IntValue = IntLiteral->getValue(); |
969 | if ((IntValue == 1) || (IntValue == 0)) { |
970 | return TryResult(); |
971 | } |
972 | return TryResult(B->getOpcode() != BO_EQ); |
973 | } |
974 | |
975 | return TryResult(); |
976 | } |
977 | |
978 | TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation, |
979 | const llvm::APSInt &Value1, |
980 | const llvm::APSInt &Value2) { |
981 | assert(Value1.isSigned() == Value2.isSigned()); |
982 | switch (Relation) { |
983 | default: |
984 | return TryResult(); |
985 | case BO_EQ: |
986 | return TryResult(Value1 == Value2); |
987 | case BO_NE: |
988 | return TryResult(Value1 != Value2); |
989 | case BO_LT: |
990 | return TryResult(Value1 < Value2); |
991 | case BO_LE: |
992 | return TryResult(Value1 <= Value2); |
993 | case BO_GT: |
994 | return TryResult(Value1 > Value2); |
995 | case BO_GE: |
996 | return TryResult(Value1 >= Value2); |
997 | } |
998 | } |
999 | |
1000 | |
1001 | |
1002 | |
1003 | |
1004 | TryResult checkIncorrectLogicOperator(const BinaryOperator *B) { |
1005 | isLogicalOp()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1005, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(B->isLogicalOp()); |
1006 | const BinaryOperator *LHS = |
1007 | dyn_cast<BinaryOperator>(B->getLHS()->IgnoreParens()); |
1008 | const BinaryOperator *RHS = |
1009 | dyn_cast<BinaryOperator>(B->getRHS()->IgnoreParens()); |
1010 | if (!LHS || !RHS) |
1011 | return {}; |
1012 | |
1013 | if (!LHS->isComparisonOp() || !RHS->isComparisonOp()) |
1014 | return {}; |
1015 | |
1016 | const DeclRefExpr *Decl1; |
1017 | const Expr *Expr1; |
1018 | BinaryOperatorKind BO1; |
1019 | std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS); |
1020 | |
1021 | if (!Decl1 || !Expr1) |
1022 | return {}; |
1023 | |
1024 | const DeclRefExpr *Decl2; |
1025 | const Expr *Expr2; |
1026 | BinaryOperatorKind BO2; |
1027 | std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS); |
1028 | |
1029 | if (!Decl2 || !Expr2) |
1030 | return {}; |
1031 | |
1032 | |
1033 | if (Decl1->getDecl() != Decl2->getDecl()) |
1034 | return {}; |
1035 | |
1036 | |
1037 | |
1038 | if (!areExprTypesCompatible(Expr1, Expr2)) |
1039 | return {}; |
1040 | |
1041 | Expr::EvalResult L1Result, L2Result; |
1042 | if (!Expr1->EvaluateAsInt(L1Result, *Context) || |
1043 | !Expr2->EvaluateAsInt(L2Result, *Context)) |
1044 | return {}; |
1045 | |
1046 | llvm::APSInt L1 = L1Result.Val.getInt(); |
1047 | llvm::APSInt L2 = L2Result.Val.getInt(); |
1048 | |
1049 | |
1050 | if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth()) |
1051 | return {}; |
1052 | |
1053 | |
1054 | |
1055 | const llvm::APSInt Values[] = { |
1056 | |
1057 | llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()), |
1058 | |
1059 | L1, |
1060 | |
1061 | ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1), |
1062 | L1.isUnsigned()), |
1063 | |
1064 | L2, |
1065 | |
1066 | llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()), |
1067 | }; |
1068 | |
1069 | |
1070 | |
1071 | |
1072 | |
1073 | |
1074 | |
1075 | bool AlwaysTrue = true, AlwaysFalse = true; |
1076 | for (const llvm::APSInt &Value : Values) { |
1077 | TryResult Res1, Res2; |
1078 | Res1 = analyzeLogicOperatorCondition(BO1, Value, L1); |
1079 | Res2 = analyzeLogicOperatorCondition(BO2, Value, L2); |
1080 | |
1081 | if (!Res1.isKnown() || !Res2.isKnown()) |
1082 | return {}; |
1083 | |
1084 | if (B->getOpcode() == BO_LAnd) { |
1085 | AlwaysTrue &= (Res1.isTrue() && Res2.isTrue()); |
1086 | AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue()); |
1087 | } else { |
1088 | AlwaysTrue &= (Res1.isTrue() || Res2.isTrue()); |
1089 | AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue()); |
1090 | } |
1091 | } |
1092 | |
1093 | if (AlwaysTrue || AlwaysFalse) { |
1094 | if (BuildOpts.Observer) |
1095 | BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue); |
1096 | return TryResult(AlwaysTrue); |
1097 | } |
1098 | return {}; |
1099 | } |
1100 | |
1101 | |
1102 | bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { |
1103 | if (!BuildOpts.PruneTriviallyFalseEdges) |
1104 | return false; |
1105 | return !S->isTypeDependent() && |
1106 | !S->isValueDependent() && |
1107 | S->EvaluateAsRValue(outResult, *Context); |
1108 | } |
1109 | |
1110 | |
1111 | |
1112 | TryResult tryEvaluateBool(Expr *S) { |
1113 | if (!BuildOpts.PruneTriviallyFalseEdges || |
1114 | S->isTypeDependent() || S->isValueDependent()) |
1115 | return {}; |
1116 | |
1117 | if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { |
1118 | if (Bop->isLogicalOp()) { |
1119 | |
1120 | CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S); |
1121 | if (I != CachedBoolEvals.end()) |
1122 | return I->second; |
1123 | |
1124 | |
1125 | TryResult Result = evaluateAsBooleanConditionNoCache(S); |
1126 | CachedBoolEvals[S] = Result; |
1127 | return Result; |
1128 | } |
1129 | else { |
1130 | switch (Bop->getOpcode()) { |
1131 | default: break; |
1132 | |
1133 | |
1134 | case BO_Mul: |
1135 | case BO_And: { |
1136 | |
1137 | |
1138 | Expr::EvalResult LHSResult; |
1139 | if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) { |
1140 | llvm::APSInt IntVal = LHSResult.Val.getInt(); |
1141 | if (!IntVal.getBoolValue()) { |
1142 | return TryResult(false); |
1143 | } |
1144 | } |
1145 | Expr::EvalResult RHSResult; |
1146 | if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) { |
1147 | llvm::APSInt IntVal = RHSResult.Val.getInt(); |
1148 | if (!IntVal.getBoolValue()) { |
1149 | return TryResult(false); |
1150 | } |
1151 | } |
1152 | } |
1153 | break; |
1154 | } |
1155 | } |
1156 | } |
1157 | |
1158 | return evaluateAsBooleanConditionNoCache(S); |
1159 | } |
1160 | |
1161 | |
1162 | TryResult evaluateAsBooleanConditionNoCache(Expr *E) { |
1163 | if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) { |
1164 | if (Bop->isLogicalOp()) { |
1165 | TryResult LHS = tryEvaluateBool(Bop->getLHS()); |
1166 | if (LHS.isKnown()) { |
1167 | |
1168 | |
1169 | if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr)) |
1170 | return LHS.isTrue(); |
1171 | |
1172 | TryResult RHS = tryEvaluateBool(Bop->getRHS()); |
1173 | if (RHS.isKnown()) { |
1174 | if (Bop->getOpcode() == BO_LOr) |
1175 | return LHS.isTrue() || RHS.isTrue(); |
1176 | else |
1177 | return LHS.isTrue() && RHS.isTrue(); |
1178 | } |
1179 | } else { |
1180 | TryResult RHS = tryEvaluateBool(Bop->getRHS()); |
1181 | if (RHS.isKnown()) { |
1182 | |
1183 | |
1184 | if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr)) |
1185 | return RHS.isTrue(); |
1186 | } else { |
1187 | TryResult BopRes = checkIncorrectLogicOperator(Bop); |
1188 | if (BopRes.isKnown()) |
1189 | return BopRes.isTrue(); |
1190 | } |
1191 | } |
1192 | |
1193 | return {}; |
1194 | } else if (Bop->isEqualityOp()) { |
1195 | TryResult BopRes = checkIncorrectEqualityOperator(Bop); |
1196 | if (BopRes.isKnown()) |
1197 | return BopRes.isTrue(); |
1198 | } else if (Bop->isRelationalOp()) { |
1199 | TryResult BopRes = checkIncorrectRelationalOperator(Bop); |
1200 | if (BopRes.isKnown()) |
1201 | return BopRes.isTrue(); |
1202 | } |
1203 | } |
1204 | |
1205 | bool Result; |
1206 | if (E->EvaluateAsBooleanCondition(Result, *Context)) |
1207 | return Result; |
1208 | |
1209 | return {}; |
1210 | } |
1211 | |
1212 | bool hasTrivialDestructor(VarDecl *VD); |
1213 | }; |
1214 | |
1215 | } |
1216 | |
1217 | inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, |
1218 | const Stmt *stmt) const { |
1219 | return builder.alwaysAdd(stmt) || kind == AlwaysAdd; |
1220 | } |
1221 | |
1222 | bool CFGBuilder::alwaysAdd(const Stmt *stmt) { |
1223 | bool shouldAdd = BuildOpts.alwaysAdd(stmt); |
1224 | |
1225 | if (!BuildOpts.forcedBlkExprs) |
1226 | return shouldAdd; |
1227 | |
1228 | if (lastLookup == stmt) { |
1229 | if (cachedEntry) { |
1230 | first == stmt", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1230, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(cachedEntry->first == stmt); |
1231 | return true; |
1232 | } |
1233 | return shouldAdd; |
1234 | } |
1235 | |
1236 | lastLookup = stmt; |
1237 | |
1238 | |
1239 | CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; |
1240 | |
1241 | if (!fb) { |
1242 | |
1243 | assert(!cachedEntry); |
1244 | return shouldAdd; |
1245 | } |
1246 | |
1247 | CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); |
1248 | if (itr == fb->end()) { |
1249 | cachedEntry = nullptr; |
1250 | return shouldAdd; |
1251 | } |
1252 | |
1253 | cachedEntry = &*itr; |
1254 | return true; |
1255 | } |
1256 | |
1257 | |
1258 | |
1259 | static const VariableArrayType *FindVA(const Type *t) { |
1260 | while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { |
1261 | if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) |
1262 | if (vat->getSizeExpr()) |
1263 | return vat; |
1264 | |
1265 | t = vt->getElementType().getTypePtr(); |
1266 | } |
1267 | |
1268 | return nullptr; |
1269 | } |
1270 | |
1271 | void CFGBuilder::consumeConstructionContext( |
1272 | const ConstructionContextLayer *Layer, Expr *E) { |
1273 | (0) . __assert_fail ("(isa(E) || isa(E) || isa(E)) && \"Expression cannot construct an object!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1274, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || |
1274 | (0) . __assert_fail ("(isa(E) || isa(E) || isa(E)) && \"Expression cannot construct an object!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1274, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> isa<ObjCMessageExpr>(E)) && "Expression cannot construct an object!"); |
1275 | if (const ConstructionContextLayer *PreviouslyStoredLayer = |
1276 | ConstructionContextMap.lookup(E)) { |
1277 | (void)PreviouslyStoredLayer; |
1278 | |
1279 | |
1280 | (0) . __assert_fail ("PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) && \"Already within a different construction context!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1281, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) && |
1281 | (0) . __assert_fail ("PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) && \"Already within a different construction context!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1281, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Already within a different construction context!"); |
1282 | } else { |
1283 | ConstructionContextMap[E] = Layer; |
1284 | } |
1285 | } |
1286 | |
1287 | void CFGBuilder::findConstructionContexts( |
1288 | const ConstructionContextLayer *Layer, Stmt *Child) { |
1289 | if (!BuildOpts.AddRichCXXConstructors) |
1290 | return; |
1291 | |
1292 | if (!Child) |
1293 | return; |
1294 | |
1295 | auto = [this, Layer](const ConstructionContextItem &Item) { |
1296 | return ConstructionContextLayer::create(cfg->getBumpVectorContext(), Item, |
1297 | Layer); |
1298 | }; |
1299 | |
1300 | switch(Child->getStmtClass()) { |
1301 | case Stmt::CXXConstructExprClass: |
1302 | case Stmt::CXXTemporaryObjectExprClass: { |
1303 | |
1304 | auto *CE = cast<CXXConstructExpr>(Child); |
1305 | if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) { |
1306 | findConstructionContexts(withExtraLayer(CE), CE->getArg(0)); |
1307 | } |
1308 | |
1309 | consumeConstructionContext(Layer, CE); |
1310 | break; |
1311 | } |
1312 | |
1313 | |
1314 | |
1315 | case Stmt::CallExprClass: |
1316 | case Stmt::CXXMemberCallExprClass: |
1317 | case Stmt::CXXOperatorCallExprClass: |
1318 | case Stmt::UserDefinedLiteralClass: |
1319 | case Stmt::ObjCMessageExprClass: { |
1320 | auto *E = cast<Expr>(Child); |
1321 | if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(E)) |
1322 | consumeConstructionContext(Layer, E); |
1323 | break; |
1324 | } |
1325 | case Stmt::ExprWithCleanupsClass: { |
1326 | auto *Cleanups = cast<ExprWithCleanups>(Child); |
1327 | findConstructionContexts(Layer, Cleanups->getSubExpr()); |
1328 | break; |
1329 | } |
1330 | case Stmt::CXXFunctionalCastExprClass: { |
1331 | auto *Cast = cast<CXXFunctionalCastExpr>(Child); |
1332 | findConstructionContexts(Layer, Cast->getSubExpr()); |
1333 | break; |
1334 | } |
1335 | case Stmt::ImplicitCastExprClass: { |
1336 | auto *Cast = cast<ImplicitCastExpr>(Child); |
1337 | |
1338 | switch (Cast->getCastKind()) { |
1339 | case CK_NoOp: |
1340 | case CK_ConstructorConversion: |
1341 | findConstructionContexts(Layer, Cast->getSubExpr()); |
1342 | break; |
1343 | default: |
1344 | break; |
1345 | } |
1346 | break; |
1347 | } |
1348 | case Stmt::CXXBindTemporaryExprClass: { |
1349 | auto *BTE = cast<CXXBindTemporaryExpr>(Child); |
1350 | findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr()); |
1351 | break; |
1352 | } |
1353 | case Stmt::MaterializeTemporaryExprClass: { |
1354 | |
1355 | |
1356 | |
1357 | |
1358 | if (Layer->getItem().getKind() == |
1359 | ConstructionContextItem::ElidableConstructorKind) { |
1360 | auto *MTE = cast<MaterializeTemporaryExpr>(Child); |
1361 | findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr()); |
1362 | } |
1363 | break; |
1364 | } |
1365 | case Stmt::ConditionalOperatorClass: { |
1366 | auto *CO = cast<ConditionalOperator>(Child); |
1367 | if (Layer->getItem().getKind() != |
1368 | ConstructionContextItem::MaterializationKind) { |
1369 | |
1370 | |
1371 | |
1372 | |
1373 | getType()->getAsCXXRecordDecl() || CO->isGLValue() || Context->getLangOpts().CPlusPlus17", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1374, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() || |
1374 | getType()->getAsCXXRecordDecl() || CO->isGLValue() || Context->getLangOpts().CPlusPlus17", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1374, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> Context->getLangOpts().CPlusPlus17); |
1375 | break; |
1376 | } |
1377 | findConstructionContexts(Layer, CO->getLHS()); |
1378 | findConstructionContexts(Layer, CO->getRHS()); |
1379 | break; |
1380 | } |
1381 | case Stmt::InitListExprClass: { |
1382 | auto *ILE = cast<InitListExpr>(Child); |
1383 | if (ILE->isTransparent()) { |
1384 | findConstructionContexts(Layer, ILE->getInit(0)); |
1385 | break; |
1386 | } |
1387 | |
1388 | break; |
1389 | } |
1390 | default: |
1391 | break; |
1392 | } |
1393 | } |
1394 | |
1395 | void CFGBuilder::cleanupConstructionContext(Expr *E) { |
1396 | (0) . __assert_fail ("BuildOpts.AddRichCXXConstructors && \"We should not be managing construction contexts!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1397, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BuildOpts.AddRichCXXConstructors && |
1397 | (0) . __assert_fail ("BuildOpts.AddRichCXXConstructors && \"We should not be managing construction contexts!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1397, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "We should not be managing construction contexts!"); |
1398 | (0) . __assert_fail ("ConstructionContextMap.count(E) && \"Cannot exit construction context without the context!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1399, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(ConstructionContextMap.count(E) && |
1399 | (0) . __assert_fail ("ConstructionContextMap.count(E) && \"Cannot exit construction context without the context!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1399, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Cannot exit construction context without the context!"); |
1400 | ConstructionContextMap.erase(E); |
1401 | } |
1402 | |
1403 | |
1404 | |
1405 | |
1406 | |
1407 | |
1408 | |
1409 | std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { |
1410 | assert(cfg.get()); |
1411 | if (!Statement) |
1412 | return nullptr; |
1413 | |
1414 | |
1415 | |
1416 | |
1417 | Succ = createBlock(); |
1418 | getExit()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1418, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Succ == &cfg->getExit()); |
1419 | Block = nullptr; |
1420 | |
1421 | (0) . __assert_fail ("!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && \"AddImplicitDtors and AddLifetime cannot be used at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1422, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && |
1422 | (0) . __assert_fail ("!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && \"AddImplicitDtors and AddLifetime cannot be used at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1422, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "AddImplicitDtors and AddLifetime cannot be used at the same time"); |
1423 | |
1424 | if (BuildOpts.AddImplicitDtors) |
1425 | if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) |
1426 | addImplicitDtorsForDestructor(DD); |
1427 | |
1428 | |
1429 | CFGBlock *B = addStmt(Statement); |
1430 | |
1431 | if (badCFG) |
1432 | return nullptr; |
1433 | |
1434 | |
1435 | if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { |
1436 | for (auto *I : llvm::reverse(CD->inits())) { |
1437 | B = addInitializer(I); |
1438 | if (badCFG) |
1439 | return nullptr; |
1440 | } |
1441 | } |
1442 | |
1443 | if (B) |
1444 | Succ = B; |
1445 | |
1446 | |
1447 | |
1448 | for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), |
1449 | E = BackpatchBlocks.end(); I != E; ++I ) { |
1450 | |
1451 | CFGBlock *B = I->block; |
1452 | const GotoStmt *G = cast<GotoStmt>(B->getTerminator()); |
1453 | LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); |
1454 | |
1455 | |
1456 | |
1457 | if (LI == LabelMap.end()) continue; |
1458 | |
1459 | JumpTarget JT = LI->second; |
1460 | prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition, |
1461 | JT.scopePosition); |
1462 | prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, |
1463 | JT.scopePosition); |
1464 | const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator( |
1465 | B, I->scopePosition, JT.scopePosition); |
1466 | appendScopeBegin(JT.block, VD, G); |
1467 | addSuccessor(B, JT.block); |
1468 | } |
1469 | |
1470 | |
1471 | if (CFGBlock *B = cfg->getIndirectGotoBlock()) |
1472 | for (LabelSetTy::iterator I = AddressTakenLabels.begin(), |
1473 | E = AddressTakenLabels.end(); I != E; ++I ) { |
1474 | |
1475 | LabelMapTy::iterator LI = LabelMap.find(*I); |
1476 | |
1477 | |
1478 | |
1479 | if (LI == LabelMap.end()) continue; |
1480 | |
1481 | addSuccessor(B, LI->second.block); |
1482 | } |
1483 | |
1484 | |
1485 | cfg->setEntry(createBlock()); |
1486 | |
1487 | if (BuildOpts.AddRichCXXConstructors) |
1488 | (0) . __assert_fail ("ConstructionContextMap.empty() && \"Not all construction contexts were cleaned up!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1489, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(ConstructionContextMap.empty() && |
1489 | (0) . __assert_fail ("ConstructionContextMap.empty() && \"Not all construction contexts were cleaned up!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1489, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Not all construction contexts were cleaned up!"); |
1490 | |
1491 | return std::move(cfg); |
1492 | } |
1493 | |
1494 | |
1495 | |
1496 | CFGBlock *CFGBuilder::createBlock(bool add_successor) { |
1497 | CFGBlock *B = cfg->createBlock(); |
1498 | if (add_successor && Succ) |
1499 | addSuccessor(B, Succ); |
1500 | return B; |
1501 | } |
1502 | |
1503 | |
1504 | |
1505 | |
1506 | CFGBlock *CFGBuilder::createNoReturnBlock() { |
1507 | CFGBlock *B = createBlock(false); |
1508 | B->setHasNoReturnElement(); |
1509 | addSuccessor(B, &cfg->getExit(), Succ); |
1510 | return B; |
1511 | } |
1512 | |
1513 | |
1514 | CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { |
1515 | if (!BuildOpts.AddInitializers) |
1516 | return Block; |
1517 | |
1518 | bool HasTemporaries = false; |
1519 | |
1520 | |
1521 | |
1522 | Expr *Init = I->getInit(); |
1523 | if (Init) { |
1524 | HasTemporaries = isa<ExprWithCleanups>(Init); |
1525 | |
1526 | if (BuildOpts.AddTemporaryDtors && HasTemporaries) { |
1527 | |
1528 | TempDtorContext Context; |
1529 | VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), |
1530 | , Context); |
1531 | } |
1532 | } |
1533 | |
1534 | autoCreateBlock(); |
1535 | appendInitializer(Block, I); |
1536 | |
1537 | if (Init) { |
1538 | findConstructionContexts( |
1539 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), I), |
1540 | Init); |
1541 | |
1542 | if (HasTemporaries) { |
1543 | |
1544 | |
1545 | return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); |
1546 | } |
1547 | if (BuildOpts.AddCXXDefaultInitExprInCtors) { |
1548 | if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(Init)) { |
1549 | |
1550 | |
1551 | |
1552 | autoCreateBlock(); |
1553 | appendStmt(Block, Default); |
1554 | if (Stmt *Child = Default->getExpr()) |
1555 | if (CFGBlock *R = Visit(Child)) |
1556 | Block = R; |
1557 | return Block; |
1558 | } |
1559 | } |
1560 | return Visit(Init); |
1561 | } |
1562 | |
1563 | return Block; |
1564 | } |
1565 | |
1566 | |
1567 | |
1568 | static QualType getReferenceInitTemporaryType(const Expr *Init, |
1569 | bool *FoundMTE = nullptr) { |
1570 | while (true) { |
1571 | |
1572 | Init = Init->IgnoreParens(); |
1573 | |
1574 | |
1575 | if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) { |
1576 | Init = EWC->getSubExpr(); |
1577 | continue; |
1578 | } |
1579 | |
1580 | |
1581 | if (const MaterializeTemporaryExpr *MTE |
1582 | = dyn_cast<MaterializeTemporaryExpr>(Init)) { |
1583 | Init = MTE->GetTemporaryExpr(); |
1584 | if (FoundMTE) |
1585 | *FoundMTE = true; |
1586 | continue; |
1587 | } |
1588 | |
1589 | |
1590 | SmallVector<const Expr *, 2> CommaLHSs; |
1591 | SmallVector<SubobjectAdjustment, 2> Adjustments; |
1592 | const Expr *SkippedInit = |
1593 | Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); |
1594 | if (SkippedInit != Init) { |
1595 | Init = SkippedInit; |
1596 | continue; |
1597 | } |
1598 | |
1599 | break; |
1600 | } |
1601 | |
1602 | return Init->getType(); |
1603 | } |
1604 | |
1605 | |
1606 | |
1607 | void CFGBuilder::addLoopExit(const Stmt *LoopStmt){ |
1608 | if(!BuildOpts.AddLoopExit) |
1609 | return; |
1610 | autoCreateBlock(); |
1611 | appendLoopExit(Block, LoopStmt); |
1612 | } |
1613 | |
1614 | void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B, |
1615 | LocalScope::const_iterator E, Stmt *S) { |
1616 | if (!BuildOpts.AddScopes) |
1617 | return; |
1618 | |
1619 | if (B == E) |
1620 | return; |
1621 | |
1622 | |
1623 | |
1624 | |
1625 | |
1626 | LocalScope::const_iterator P = B.shared_parent(E); |
1627 | int Dist = B.distance(P); |
1628 | if (Dist <= 0) |
1629 | return; |
1630 | |
1631 | for (LocalScope::const_iterator I = B; I != P; ++I) |
1632 | if (I.pointsToFirstDeclaredVar()) |
1633 | DeclsWithEndedScope.insert(*I); |
1634 | } |
1635 | |
1636 | void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B, |
1637 | LocalScope::const_iterator E, |
1638 | Stmt *S) { |
1639 | getDeclsWithEndedScope(B, E, S); |
1640 | if (BuildOpts.AddScopes) |
1641 | addScopesEnd(B, E, S); |
1642 | if (BuildOpts.AddImplicitDtors) |
1643 | addAutomaticObjDtors(B, E, S); |
1644 | if (BuildOpts.AddLifetime) |
1645 | addLifetimeEnds(B, E, S); |
1646 | } |
1647 | |
1648 | |
1649 | void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B, |
1650 | LocalScope::const_iterator E, Stmt *S) { |
1651 | if (!BuildOpts.AddLifetime) |
1652 | return; |
1653 | |
1654 | if (B == E) |
1655 | return; |
1656 | |
1657 | |
1658 | |
1659 | |
1660 | |
1661 | LocalScope::const_iterator P = B.shared_parent(E); |
1662 | int dist = B.distance(P); |
1663 | if (dist <= 0) |
1664 | return; |
1665 | |
1666 | |
1667 | SmallVector<VarDecl *, 10> DeclsTrivial; |
1668 | SmallVector<VarDecl *, 10> DeclsNonTrivial; |
1669 | DeclsTrivial.reserve(dist); |
1670 | DeclsNonTrivial.reserve(dist); |
1671 | |
1672 | for (LocalScope::const_iterator I = B; I != P; ++I) |
1673 | if (hasTrivialDestructor(*I)) |
1674 | DeclsTrivial.push_back(*I); |
1675 | else |
1676 | DeclsNonTrivial.push_back(*I); |
1677 | |
1678 | autoCreateBlock(); |
1679 | |
1680 | |
1681 | for (SmallVectorImpl<VarDecl *>::reverse_iterator I = DeclsTrivial.rbegin(), |
1682 | E = DeclsTrivial.rend(); |
1683 | I != E; ++I) |
1684 | appendLifetimeEnds(Block, *I, S); |
1685 | |
1686 | for (SmallVectorImpl<VarDecl *>::reverse_iterator |
1687 | I = DeclsNonTrivial.rbegin(), |
1688 | E = DeclsNonTrivial.rend(); |
1689 | I != E; ++I) |
1690 | appendLifetimeEnds(Block, *I, S); |
1691 | } |
1692 | |
1693 | |
1694 | void CFGBuilder::addScopesEnd(LocalScope::const_iterator B, |
1695 | LocalScope::const_iterator E, Stmt *S) { |
1696 | |
1697 | |
1698 | if (BuildOpts.AddImplicitDtors) |
1699 | return; |
1700 | |
1701 | autoCreateBlock(); |
1702 | |
1703 | for (auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend(); |
1704 | I != E; ++I) |
1705 | appendScopeEnd(Block, *I, S); |
1706 | |
1707 | return; |
1708 | } |
1709 | |
1710 | |
1711 | |
1712 | |
1713 | void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, |
1714 | LocalScope::const_iterator E, Stmt *S) { |
1715 | if (!BuildOpts.AddImplicitDtors) |
1716 | return; |
1717 | |
1718 | if (B == E) |
1719 | return; |
1720 | |
1721 | |
1722 | |
1723 | |
1724 | |
1725 | SmallVector<VarDecl*, 10> Decls; |
1726 | Decls.reserve(B.distance(E)); |
1727 | for (LocalScope::const_iterator I = B; I != E; ++I) |
1728 | Decls.push_back(*I); |
1729 | |
1730 | for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(), |
1731 | E = Decls.rend(); |
1732 | I != E; ++I) { |
1733 | if (hasTrivialDestructor(*I)) { |
1734 | |
1735 | |
1736 | if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) { |
1737 | autoCreateBlock(); |
1738 | appendScopeEnd(Block, *I, S); |
1739 | } |
1740 | continue; |
1741 | } |
1742 | |
1743 | |
1744 | |
1745 | QualType Ty = (*I)->getType(); |
1746 | if (Ty->isReferenceType()) { |
1747 | Ty = getReferenceInitTemporaryType((*I)->getInit()); |
1748 | } |
1749 | Ty = Context->getBaseElementType(Ty); |
1750 | |
1751 | if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn()) |
1752 | Block = createNoReturnBlock(); |
1753 | else |
1754 | autoCreateBlock(); |
1755 | |
1756 | |
1757 | if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) |
1758 | appendScopeEnd(Block, *I, S); |
1759 | appendAutomaticObjDtor(Block, *I, S); |
1760 | } |
1761 | } |
1762 | |
1763 | |
1764 | |
1765 | void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { |
1766 | (0) . __assert_fail ("BuildOpts.AddImplicitDtors && \"Can be called only when dtors should be added\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1767, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BuildOpts.AddImplicitDtors && |
1767 | (0) . __assert_fail ("BuildOpts.AddImplicitDtors && \"Can be called only when dtors should be added\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1767, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Can be called only when dtors should be added"); |
1768 | const CXXRecordDecl *RD = DD->getParent(); |
1769 | |
1770 | |
1771 | for (const auto &VI : RD->vbases()) { |
1772 | const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl(); |
1773 | if (!CD->hasTrivialDestructor()) { |
1774 | autoCreateBlock(); |
1775 | appendBaseDtor(Block, &VI); |
1776 | } |
1777 | } |
1778 | |
1779 | |
1780 | for (const auto &BI : RD->bases()) { |
1781 | if (!BI.isVirtual()) { |
1782 | const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl(); |
1783 | if (!CD->hasTrivialDestructor()) { |
1784 | autoCreateBlock(); |
1785 | appendBaseDtor(Block, &BI); |
1786 | } |
1787 | } |
1788 | } |
1789 | |
1790 | |
1791 | for (auto *FI : RD->fields()) { |
1792 | |
1793 | QualType QT = FI->getType(); |
1794 | if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { |
1795 | if (AT->getSize() == 0) |
1796 | continue; |
1797 | QT = AT->getElementType(); |
1798 | } |
1799 | |
1800 | if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) |
1801 | if (!CD->hasTrivialDestructor()) { |
1802 | autoCreateBlock(); |
1803 | appendMemberDtor(Block, FI); |
1804 | } |
1805 | } |
1806 | } |
1807 | |
1808 | |
1809 | |
1810 | LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { |
1811 | if (Scope) |
1812 | return Scope; |
1813 | llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); |
1814 | return new (alloc.Allocate<LocalScope>()) |
1815 | LocalScope(BumpVectorContext(alloc), ScopePos); |
1816 | } |
1817 | |
1818 | |
1819 | |
1820 | void CFGBuilder::addLocalScopeForStmt(Stmt *S) { |
1821 | if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime && |
1822 | !BuildOpts.AddScopes) |
1823 | return; |
1824 | |
1825 | LocalScope *Scope = nullptr; |
1826 | |
1827 | |
1828 | if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { |
1829 | for (auto *BI : CS->body()) { |
1830 | Stmt *SI = BI->stripLabelLikeStatements(); |
1831 | if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) |
1832 | Scope = addLocalScopeForDeclStmt(DS, Scope); |
1833 | } |
1834 | return; |
1835 | } |
1836 | |
1837 | |
1838 | |
1839 | if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements())) |
1840 | addLocalScopeForDeclStmt(DS); |
1841 | } |
1842 | |
1843 | |
1844 | |
1845 | LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, |
1846 | LocalScope* Scope) { |
1847 | if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime && |
1848 | !BuildOpts.AddScopes) |
1849 | return Scope; |
1850 | |
1851 | for (auto *DI : DS->decls()) |
1852 | if (VarDecl *VD = dyn_cast<VarDecl>(DI)) |
1853 | Scope = addLocalScopeForVarDecl(VD, Scope); |
1854 | return Scope; |
1855 | } |
1856 | |
1857 | bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) { |
1858 | |
1859 | QualType QT = VD->getType(); |
1860 | if (QT->isReferenceType()) { |
1861 | |
1862 | |
1863 | |
1864 | |
1865 | |
1866 | |
1867 | |
1868 | |
1869 | const Expr *Init = VD->getInit(); |
1870 | if (!Init) { |
1871 | |
1872 | |
1873 | |
1874 | return true; |
1875 | } |
1876 | |
1877 | |
1878 | bool FoundMTE = false; |
1879 | QT = getReferenceInitTemporaryType(Init, &FoundMTE); |
1880 | if (!FoundMTE) |
1881 | return true; |
1882 | } |
1883 | |
1884 | |
1885 | while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { |
1886 | if (AT->getSize() == 0) |
1887 | return true; |
1888 | QT = AT->getElementType(); |
1889 | } |
1890 | |
1891 | |
1892 | if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) |
1893 | return !CD->hasDefinition() || CD->hasTrivialDestructor(); |
1894 | return true; |
1895 | } |
1896 | |
1897 | |
1898 | |
1899 | |
1900 | LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, |
1901 | LocalScope* Scope) { |
1902 | (0) . __assert_fail ("!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && \"AddImplicitDtors and AddLifetime cannot be used at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1903, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && |
1903 | (0) . __assert_fail ("!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && \"AddImplicitDtors and AddLifetime cannot be used at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 1903, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "AddImplicitDtors and AddLifetime cannot be used at the same time"); |
1904 | if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime && |
1905 | !BuildOpts.AddScopes) |
1906 | return Scope; |
1907 | |
1908 | |
1909 | switch (VD->getStorageClass()) { |
1910 | case SC_None: |
1911 | case SC_Auto: |
1912 | case SC_Register: |
1913 | break; |
1914 | default: return Scope; |
1915 | } |
1916 | |
1917 | if (BuildOpts.AddImplicitDtors) { |
1918 | if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) { |
1919 | |
1920 | Scope = createOrReuseLocalScope(Scope); |
1921 | Scope->addVar(VD); |
1922 | ScopePos = Scope->begin(); |
1923 | } |
1924 | return Scope; |
1925 | } |
1926 | |
1927 | assert(BuildOpts.AddLifetime); |
1928 | |
1929 | Scope = createOrReuseLocalScope(Scope); |
1930 | Scope->addVar(VD); |
1931 | ScopePos = Scope->begin(); |
1932 | return Scope; |
1933 | } |
1934 | |
1935 | |
1936 | |
1937 | void CFGBuilder::addLocalScopeAndDtors(Stmt *S) { |
1938 | LocalScope::const_iterator scopeBeginPos = ScopePos; |
1939 | addLocalScopeForStmt(S); |
1940 | addAutomaticObjHandling(ScopePos, scopeBeginPos, S); |
1941 | } |
1942 | |
1943 | |
1944 | |
1945 | |
1946 | |
1947 | |
1948 | |
1949 | |
1950 | void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, |
1951 | LocalScope::const_iterator B, LocalScope::const_iterator E) { |
1952 | if (!BuildOpts.AddImplicitDtors) |
1953 | return; |
1954 | BumpVectorContext &C = cfg->getBumpVectorContext(); |
1955 | CFGBlock::iterator InsertPos |
1956 | = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); |
1957 | for (LocalScope::const_iterator I = B; I != E; ++I) |
1958 | InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, |
1959 | Blk->getTerminator()); |
1960 | } |
1961 | |
1962 | |
1963 | |
1964 | |
1965 | |
1966 | |
1967 | void CFGBuilder::prependAutomaticObjLifetimeWithTerminator( |
1968 | CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) { |
1969 | if (!BuildOpts.AddLifetime) |
1970 | return; |
1971 | BumpVectorContext &C = cfg->getBumpVectorContext(); |
1972 | CFGBlock::iterator InsertPos = |
1973 | Blk->beginLifetimeEndsInsert(Blk->end(), B.distance(E), C); |
1974 | for (LocalScope::const_iterator I = B; I != E; ++I) |
1975 | InsertPos = Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminator()); |
1976 | } |
1977 | |
1978 | |
1979 | |
1980 | |
1981 | |
1982 | |
1983 | const VarDecl * |
1984 | CFGBuilder::prependAutomaticObjScopeEndWithTerminator( |
1985 | CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) { |
1986 | if (!BuildOpts.AddScopes) |
1987 | return nullptr; |
1988 | BumpVectorContext &C = cfg->getBumpVectorContext(); |
1989 | CFGBlock::iterator InsertPos = |
1990 | Blk->beginScopeEndInsert(Blk->end(), 1, C); |
1991 | LocalScope::const_iterator PlaceToInsert = B; |
1992 | for (LocalScope::const_iterator I = B; I != E; ++I) |
1993 | PlaceToInsert = I; |
1994 | Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminator()); |
1995 | return *PlaceToInsert; |
1996 | } |
1997 | |
1998 | |
1999 | |
2000 | |
2001 | CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { |
2002 | if (!S) { |
2003 | badCFG = true; |
2004 | return nullptr; |
2005 | } |
2006 | |
2007 | if (Expr *E = dyn_cast<Expr>(S)) |
2008 | S = E->IgnoreParens(); |
2009 | |
2010 | switch (S->getStmtClass()) { |
2011 | default: |
2012 | return VisitStmt(S, asc); |
2013 | |
2014 | case Stmt::AddrLabelExprClass: |
2015 | return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); |
2016 | |
2017 | case Stmt::BinaryConditionalOperatorClass: |
2018 | return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); |
2019 | |
2020 | case Stmt::BinaryOperatorClass: |
2021 | return VisitBinaryOperator(cast<BinaryOperator>(S), asc); |
2022 | |
2023 | case Stmt::BlockExprClass: |
2024 | return VisitBlockExpr(cast<BlockExpr>(S), asc); |
2025 | |
2026 | case Stmt::BreakStmtClass: |
2027 | return VisitBreakStmt(cast<BreakStmt>(S)); |
2028 | |
2029 | case Stmt::CallExprClass: |
2030 | case Stmt::CXXOperatorCallExprClass: |
2031 | case Stmt::CXXMemberCallExprClass: |
2032 | case Stmt::UserDefinedLiteralClass: |
2033 | return VisitCallExpr(cast<CallExpr>(S), asc); |
2034 | |
2035 | case Stmt::CaseStmtClass: |
2036 | return VisitCaseStmt(cast<CaseStmt>(S)); |
2037 | |
2038 | case Stmt::ChooseExprClass: |
2039 | return VisitChooseExpr(cast<ChooseExpr>(S), asc); |
2040 | |
2041 | case Stmt::CompoundStmtClass: |
2042 | return VisitCompoundStmt(cast<CompoundStmt>(S)); |
2043 | |
2044 | case Stmt::ConditionalOperatorClass: |
2045 | return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); |
2046 | |
2047 | case Stmt::ContinueStmtClass: |
2048 | return VisitContinueStmt(cast<ContinueStmt>(S)); |
2049 | |
2050 | case Stmt::CXXCatchStmtClass: |
2051 | return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); |
2052 | |
2053 | case Stmt::ExprWithCleanupsClass: |
2054 | return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); |
2055 | |
2056 | case Stmt::CXXDefaultArgExprClass: |
2057 | case Stmt::CXXDefaultInitExprClass: |
2058 | |
2059 | |
2060 | |
2061 | |
2062 | |
2063 | |
2064 | |
2065 | |
2066 | |
2067 | return VisitStmt(S, asc); |
2068 | |
2069 | case Stmt::CXXBindTemporaryExprClass: |
2070 | return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); |
2071 | |
2072 | case Stmt::CXXConstructExprClass: |
2073 | return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); |
2074 | |
2075 | case Stmt::CXXNewExprClass: |
2076 | return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc); |
2077 | |
2078 | case Stmt::CXXDeleteExprClass: |
2079 | return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc); |
2080 | |
2081 | case Stmt::CXXFunctionalCastExprClass: |
2082 | return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); |
2083 | |
2084 | case Stmt::CXXTemporaryObjectExprClass: |
2085 | return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); |
2086 | |
2087 | case Stmt::CXXThrowExprClass: |
2088 | return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); |
2089 | |
2090 | case Stmt::CXXTryStmtClass: |
2091 | return VisitCXXTryStmt(cast<CXXTryStmt>(S)); |
2092 | |
2093 | case Stmt::CXXForRangeStmtClass: |
2094 | return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); |
2095 | |
2096 | case Stmt::DeclStmtClass: |
2097 | return VisitDeclStmt(cast<DeclStmt>(S)); |
2098 | |
2099 | case Stmt::DefaultStmtClass: |
2100 | return VisitDefaultStmt(cast<DefaultStmt>(S)); |
2101 | |
2102 | case Stmt::DoStmtClass: |
2103 | return VisitDoStmt(cast<DoStmt>(S)); |
2104 | |
2105 | case Stmt::ForStmtClass: |
2106 | return VisitForStmt(cast<ForStmt>(S)); |
2107 | |
2108 | case Stmt::GotoStmtClass: |
2109 | return VisitGotoStmt(cast<GotoStmt>(S)); |
2110 | |
2111 | case Stmt::IfStmtClass: |
2112 | return VisitIfStmt(cast<IfStmt>(S)); |
2113 | |
2114 | case Stmt::ImplicitCastExprClass: |
2115 | return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); |
2116 | |
2117 | case Stmt::ConstantExprClass: |
2118 | return VisitConstantExpr(cast<ConstantExpr>(S), asc); |
2119 | |
2120 | case Stmt::IndirectGotoStmtClass: |
2121 | return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); |
2122 | |
2123 | case Stmt::LabelStmtClass: |
2124 | return VisitLabelStmt(cast<LabelStmt>(S)); |
2125 | |
2126 | case Stmt::LambdaExprClass: |
2127 | return VisitLambdaExpr(cast<LambdaExpr>(S), asc); |
2128 | |
2129 | case Stmt::MaterializeTemporaryExprClass: |
2130 | return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S), |
2131 | asc); |
2132 | |
2133 | case Stmt::MemberExprClass: |
2134 | return VisitMemberExpr(cast<MemberExpr>(S), asc); |
2135 | |
2136 | case Stmt::NullStmtClass: |
2137 | return Block; |
2138 | |
2139 | case Stmt::ObjCAtCatchStmtClass: |
2140 | return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); |
2141 | |
2142 | case Stmt::ObjCAutoreleasePoolStmtClass: |
2143 | return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S)); |
2144 | |
2145 | case Stmt::ObjCAtSynchronizedStmtClass: |
2146 | return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); |
2147 | |
2148 | case Stmt::ObjCAtThrowStmtClass: |
2149 | return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); |
2150 | |
2151 | case Stmt::ObjCAtTryStmtClass: |
2152 | return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); |
2153 | |
2154 | case Stmt::ObjCForCollectionStmtClass: |
2155 | return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); |
2156 | |
2157 | case Stmt::ObjCMessageExprClass: |
2158 | return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc); |
2159 | |
2160 | case Stmt::OpaqueValueExprClass: |
2161 | return Block; |
2162 | |
2163 | case Stmt::PseudoObjectExprClass: |
2164 | return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); |
2165 | |
2166 | case Stmt::ReturnStmtClass: |
2167 | case Stmt::CoreturnStmtClass: |
2168 | return VisitReturnStmt(S); |
2169 | |
2170 | case Stmt::SEHExceptStmtClass: |
2171 | return VisitSEHExceptStmt(cast<SEHExceptStmt>(S)); |
2172 | |
2173 | case Stmt::SEHFinallyStmtClass: |
2174 | return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S)); |
2175 | |
2176 | case Stmt::SEHLeaveStmtClass: |
2177 | return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S)); |
2178 | |
2179 | case Stmt::SEHTryStmtClass: |
2180 | return VisitSEHTryStmt(cast<SEHTryStmt>(S)); |
2181 | |
2182 | case Stmt::UnaryExprOrTypeTraitExprClass: |
2183 | return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), |
2184 | asc); |
2185 | |
2186 | case Stmt::StmtExprClass: |
2187 | return VisitStmtExpr(cast<StmtExpr>(S), asc); |
2188 | |
2189 | case Stmt::SwitchStmtClass: |
2190 | return VisitSwitchStmt(cast<SwitchStmt>(S)); |
2191 | |
2192 | case Stmt::UnaryOperatorClass: |
2193 | return VisitUnaryOperator(cast<UnaryOperator>(S), asc); |
2194 | |
2195 | case Stmt::WhileStmtClass: |
2196 | return VisitWhileStmt(cast<WhileStmt>(S)); |
2197 | } |
2198 | } |
2199 | |
2200 | CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { |
2201 | if (asc.alwaysAdd(*this, S)) { |
2202 | autoCreateBlock(); |
2203 | appendStmt(Block, S); |
2204 | } |
2205 | |
2206 | return VisitChildren(S); |
2207 | } |
2208 | |
2209 | |
2210 | CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { |
2211 | CFGBlock *B = Block; |
2212 | |
2213 | |
2214 | |
2215 | reverse_children RChildren(S); |
2216 | for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end(); |
2217 | I != E; ++I) { |
2218 | if (Stmt *Child = *I) |
2219 | if (CFGBlock *R = Visit(Child)) |
2220 | B = R; |
2221 | } |
2222 | return B; |
2223 | } |
2224 | |
2225 | CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, |
2226 | AddStmtChoice asc) { |
2227 | AddressTakenLabels.insert(A->getLabel()); |
2228 | |
2229 | if (asc.alwaysAdd(*this, A)) { |
2230 | autoCreateBlock(); |
2231 | appendStmt(Block, A); |
2232 | } |
2233 | |
2234 | return Block; |
2235 | } |
2236 | |
2237 | CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, |
2238 | AddStmtChoice asc) { |
2239 | if (asc.alwaysAdd(*this, U)) { |
2240 | autoCreateBlock(); |
2241 | appendStmt(Block, U); |
2242 | } |
2243 | |
2244 | return Visit(U->getSubExpr(), AddStmtChoice()); |
2245 | } |
2246 | |
2247 | CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) { |
2248 | CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); |
2249 | appendStmt(ConfluenceBlock, B); |
2250 | |
2251 | if (badCFG) |
2252 | return nullptr; |
2253 | |
2254 | return VisitLogicalOperator(B, nullptr, ConfluenceBlock, |
2255 | ConfluenceBlock).first; |
2256 | } |
2257 | |
2258 | std::pair<CFGBlock*, CFGBlock*> |
2259 | CFGBuilder::VisitLogicalOperator(BinaryOperator *B, |
2260 | Stmt *Term, |
2261 | CFGBlock *TrueBlock, |
2262 | CFGBlock *FalseBlock) { |
2263 | |
2264 | |
2265 | |
2266 | Expr *RHS = B->getRHS()->IgnoreParens(); |
2267 | CFGBlock *RHSBlock, *ExitBlock; |
2268 | |
2269 | do { |
2270 | if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS)) |
2271 | if (B_RHS->isLogicalOp()) { |
2272 | std::tie(RHSBlock, ExitBlock) = |
2273 | VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock); |
2274 | break; |
2275 | } |
2276 | |
2277 | |
2278 | |
2279 | |
2280 | |
2281 | ExitBlock = RHSBlock = createBlock(false); |
2282 | |
2283 | |
2284 | |
2285 | |
2286 | TryResult KnownVal = tryEvaluateBool(RHS); |
2287 | if (!KnownVal.isKnown()) |
2288 | KnownVal = tryEvaluateBool(B); |
2289 | |
2290 | if (!Term) { |
2291 | assert(TrueBlock == FalseBlock); |
2292 | addSuccessor(RHSBlock, TrueBlock); |
2293 | } |
2294 | else { |
2295 | RHSBlock->setTerminator(Term); |
2296 | addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse()); |
2297 | addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue()); |
2298 | } |
2299 | |
2300 | Block = RHSBlock; |
2301 | RHSBlock = addStmt(RHS); |
2302 | } |
2303 | while (false); |
2304 | |
2305 | if (badCFG) |
2306 | return std::make_pair(nullptr, nullptr); |
2307 | |
2308 | |
2309 | Expr *LHS = B->getLHS()->IgnoreParens(); |
2310 | |
2311 | if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS)) |
2312 | if (B_LHS->isLogicalOp()) { |
2313 | if (B->getOpcode() == BO_LOr) |
2314 | FalseBlock = RHSBlock; |
2315 | else |
2316 | TrueBlock = RHSBlock; |
2317 | |
2318 | |
2319 | |
2320 | |
2321 | return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock); |
2322 | } |
2323 | |
2324 | |
2325 | |
2326 | CFGBlock *LHSBlock = createBlock(false); |
2327 | LHSBlock->setTerminator(B); |
2328 | |
2329 | Block = LHSBlock; |
2330 | CFGBlock *EntryLHSBlock = addStmt(LHS); |
2331 | |
2332 | if (badCFG) |
2333 | return std::make_pair(nullptr, nullptr); |
2334 | |
2335 | |
2336 | TryResult KnownVal = tryEvaluateBool(LHS); |
2337 | |
2338 | |
2339 | if (B->getOpcode() == BO_LOr) { |
2340 | addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse()); |
2341 | addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue()); |
2342 | } else { |
2343 | getOpcode() == BO_LAnd", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 2343, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(B->getOpcode() == BO_LAnd); |
2344 | addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse()); |
2345 | addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue()); |
2346 | } |
2347 | |
2348 | return std::make_pair(EntryLHSBlock, ExitBlock); |
2349 | } |
2350 | |
2351 | CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, |
2352 | AddStmtChoice asc) { |
2353 | |
2354 | if (B->isLogicalOp()) |
2355 | return VisitLogicalOperator(B); |
2356 | |
2357 | if (B->getOpcode() == BO_Comma) { |
2358 | autoCreateBlock(); |
2359 | appendStmt(Block, B); |
2360 | addStmt(B->getRHS()); |
2361 | return addStmt(B->getLHS()); |
2362 | } |
2363 | |
2364 | if (B->isAssignmentOp()) { |
2365 | if (asc.alwaysAdd(*this, B)) { |
2366 | autoCreateBlock(); |
2367 | appendStmt(Block, B); |
2368 | } |
2369 | Visit(B->getLHS()); |
2370 | return Visit(B->getRHS()); |
2371 | } |
2372 | |
2373 | if (asc.alwaysAdd(*this, B)) { |
2374 | autoCreateBlock(); |
2375 | appendStmt(Block, B); |
2376 | } |
2377 | |
2378 | CFGBlock *RBlock = Visit(B->getRHS()); |
2379 | CFGBlock *LBlock = Visit(B->getLHS()); |
2380 | |
2381 | |
2382 | |
2383 | return (LBlock ? LBlock : RBlock); |
2384 | } |
2385 | |
2386 | CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) { |
2387 | if (asc.alwaysAdd(*this, E)) { |
2388 | autoCreateBlock(); |
2389 | appendStmt(Block, E); |
2390 | } |
2391 | return Block; |
2392 | } |
2393 | |
2394 | CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { |
2395 | |
2396 | |
2397 | if (badCFG) |
2398 | return nullptr; |
2399 | |
2400 | |
2401 | Block = createBlock(false); |
2402 | Block->setTerminator(B); |
2403 | |
2404 | |
2405 | |
2406 | if (BreakJumpTarget.block) { |
2407 | addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B); |
2408 | addSuccessor(Block, BreakJumpTarget.block); |
2409 | } else |
2410 | badCFG = true; |
2411 | |
2412 | return Block; |
2413 | } |
2414 | |
2415 | static bool CanThrow(Expr *E, ASTContext &Ctx) { |
2416 | QualType Ty = E->getType(); |
2417 | if (Ty->isFunctionPointerType()) |
2418 | Ty = Ty->getAs<PointerType>()->getPointeeType(); |
2419 | else if (Ty->isBlockPointerType()) |
2420 | Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); |
2421 | |
2422 | const FunctionType *FT = Ty->getAs<FunctionType>(); |
2423 | if (FT) { |
2424 | if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) |
2425 | if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) && |
2426 | Proto->isNothrow()) |
2427 | return false; |
2428 | } |
2429 | return true; |
2430 | } |
2431 | |
2432 | CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { |
2433 | |
2434 | QualType calleeType = C->getCallee()->getType(); |
2435 | if (calleeType == Context->BoundMemberTy) { |
2436 | QualType boundType = Expr::findBoundMemberType(C->getCallee()); |
2437 | |
2438 | |
2439 | |
2440 | if (!boundType.isNull()) calleeType = boundType; |
2441 | } |
2442 | |
2443 | |
2444 | bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); |
2445 | |
2446 | bool AddEHEdge = false; |
2447 | |
2448 | |
2449 | if (Context->getLangOpts().Exceptions) { |
2450 | if (BuildOpts.AddEHEdges) |
2451 | AddEHEdge = true; |
2452 | } |
2453 | |
2454 | |
2455 | |
2456 | bool OmitArguments = false; |
2457 | |
2458 | if (FunctionDecl *FD = C->getDirectCallee()) { |
2459 | |
2460 | |
2461 | |
2462 | |
2463 | if (!FD->isVariadic()) |
2464 | findConstructionContextsForArguments(C); |
2465 | |
2466 | if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context)) |
2467 | NoReturn = true; |
2468 | if (FD->hasAttr<NoThrowAttr>()) |
2469 | AddEHEdge = false; |
2470 | if (FD->getBuiltinID() == Builtin::BI__builtin_object_size || |
2471 | FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size) |
2472 | OmitArguments = true; |
2473 | } |
2474 | |
2475 | if (!CanThrow(C->getCallee(), *Context)) |
2476 | AddEHEdge = false; |
2477 | |
2478 | if (OmitArguments) { |
2479 | (0) . __assert_fail ("!NoReturn && \"noreturn calls with unevaluated args not implemented\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 2479, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!NoReturn && "noreturn calls with unevaluated args not implemented"); |
2480 | (0) . __assert_fail ("!AddEHEdge && \"EH calls with unevaluated args not implemented\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 2480, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!AddEHEdge && "EH calls with unevaluated args not implemented"); |
2481 | autoCreateBlock(); |
2482 | appendStmt(Block, C); |
2483 | return Visit(C->getCallee()); |
2484 | } |
2485 | |
2486 | if (!NoReturn && !AddEHEdge) { |
2487 | autoCreateBlock(); |
2488 | appendCall(Block, C); |
2489 | |
2490 | return VisitChildren(C); |
2491 | } |
2492 | |
2493 | if (Block) { |
2494 | Succ = Block; |
2495 | if (badCFG) |
2496 | return nullptr; |
2497 | } |
2498 | |
2499 | if (NoReturn) |
2500 | Block = createNoReturnBlock(); |
2501 | else |
2502 | Block = createBlock(); |
2503 | |
2504 | appendCall(Block, C); |
2505 | |
2506 | if (AddEHEdge) { |
2507 | |
2508 | if (TryTerminatedBlock) |
2509 | addSuccessor(Block, TryTerminatedBlock); |
2510 | else |
2511 | addSuccessor(Block, &cfg->getExit()); |
2512 | } |
2513 | |
2514 | return VisitChildren(C); |
2515 | } |
2516 | |
2517 | CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, |
2518 | AddStmtChoice asc) { |
2519 | CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); |
2520 | appendStmt(ConfluenceBlock, C); |
2521 | if (badCFG) |
2522 | return nullptr; |
2523 | |
2524 | AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); |
2525 | Succ = ConfluenceBlock; |
2526 | Block = nullptr; |
2527 | CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd); |
2528 | if (badCFG) |
2529 | return nullptr; |
2530 | |
2531 | Succ = ConfluenceBlock; |
2532 | Block = nullptr; |
2533 | CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd); |
2534 | if (badCFG) |
2535 | return nullptr; |
2536 | |
2537 | Block = createBlock(false); |
2538 | |
2539 | const TryResult& KnownVal = tryEvaluateBool(C->getCond()); |
2540 | addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock); |
2541 | addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock); |
2542 | Block->setTerminator(C); |
2543 | return addStmt(C->getCond()); |
2544 | } |
2545 | |
2546 | CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { |
2547 | LocalScope::const_iterator scopeBeginPos = ScopePos; |
2548 | addLocalScopeForStmt(C); |
2549 | |
2550 | if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) { |
2551 | |
2552 | |
2553 | addAutomaticObjHandling(ScopePos, scopeBeginPos, C); |
2554 | } |
2555 | |
2556 | CFGBlock *LastBlock = Block; |
2557 | |
2558 | for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); |
2559 | I != E; ++I ) { |
2560 | |
2561 | |
2562 | if (CFGBlock *newBlock = addStmt(*I)) |
2563 | LastBlock = newBlock; |
2564 | |
2565 | if (badCFG) |
2566 | return nullptr; |
2567 | } |
2568 | |
2569 | return LastBlock; |
2570 | } |
2571 | |
2572 | CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, |
2573 | AddStmtChoice asc) { |
2574 | const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); |
2575 | const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr); |
2576 | |
2577 | |
2578 | |
2579 | CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); |
2580 | appendStmt(ConfluenceBlock, C); |
2581 | if (badCFG) |
2582 | return nullptr; |
2583 | |
2584 | AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); |
2585 | |
2586 | |
2587 | |
2588 | |
2589 | |
2590 | Succ = ConfluenceBlock; |
2591 | Block = nullptr; |
2592 | CFGBlock *LHSBlock = nullptr; |
2593 | const Expr *trueExpr = C->getTrueExpr(); |
2594 | if (trueExpr != opaqueValue) { |
2595 | LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); |
2596 | if (badCFG) |
2597 | return nullptr; |
2598 | Block = nullptr; |
2599 | } |
2600 | else |
2601 | LHSBlock = ConfluenceBlock; |
2602 | |
2603 | |
2604 | Succ = ConfluenceBlock; |
2605 | CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); |
2606 | if (badCFG) |
2607 | return nullptr; |
2608 | |
2609 | |
2610 | if (BinaryOperator *Cond = |
2611 | dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens())) |
2612 | if (Cond->isLogicalOp()) |
2613 | return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first; |
2614 | |
2615 | |
2616 | Block = createBlock(false); |
2617 | |
2618 | |
2619 | const TryResult& KnownVal = tryEvaluateBool(C->getCond()); |
2620 | addSuccessor(Block, LHSBlock, !KnownVal.isFalse()); |
2621 | addSuccessor(Block, RHSBlock, !KnownVal.isTrue()); |
2622 | Block->setTerminator(C); |
2623 | Expr *condExpr = C->getCond(); |
2624 | |
2625 | if (opaqueValue) { |
2626 | |
2627 | |
2628 | if (condExpr != opaqueValue) |
2629 | addStmt(condExpr); |
2630 | |
2631 | |
2632 | |
2633 | return addStmt(BCO->getCommon()); |
2634 | } |
2635 | |
2636 | return addStmt(condExpr); |
2637 | } |
2638 | |
2639 | CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { |
2640 | |
2641 | |
2642 | if (isa<LabelDecl>(*DS->decl_begin())) |
2643 | return Block; |
2644 | |
2645 | |
2646 | if (DS->isSingleDecl()) |
2647 | return VisitDeclSubExpr(DS); |
2648 | |
2649 | CFGBlock *B = nullptr; |
2650 | |
2651 | |
2652 | for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(), |
2653 | E = DS->decl_rend(); |
2654 | I != E; ++I) { |
2655 | |
2656 | |
2657 | |
2658 | DeclGroupRef DG(*I); |
2659 | Decl *D = *I; |
2660 | DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); |
2661 | cfg->addSyntheticDeclStmt(DSNew, DS); |
2662 | |
2663 | |
2664 | B = VisitDeclSubExpr(DSNew); |
2665 | } |
2666 | |
2667 | return B; |
2668 | } |
2669 | |
2670 | |
2671 | |
2672 | CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { |
2673 | (0) . __assert_fail ("DS->isSingleDecl() && \"Can handle single declarations only.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 2673, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(DS->isSingleDecl() && "Can handle single declarations only."); |
2674 | VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); |
2675 | |
2676 | if (!VD) { |
2677 | |
2678 | |
2679 | return Block; |
2680 | } |
2681 | |
2682 | bool HasTemporaries = false; |
2683 | |
2684 | |
2685 | CFGBlock *blockAfterStaticInit = nullptr; |
2686 | |
2687 | if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) { |
2688 | |
2689 | |
2690 | if (Block) { |
2691 | Succ = Block; |
2692 | Block = nullptr; |
2693 | if (badCFG) |
2694 | return nullptr; |
2695 | } |
2696 | blockAfterStaticInit = Succ; |
2697 | } |
2698 | |
2699 | |
2700 | |
2701 | Expr *Init = VD->getInit(); |
2702 | if (Init) { |
2703 | HasTemporaries = isa<ExprWithCleanups>(Init); |
2704 | |
2705 | if (BuildOpts.AddTemporaryDtors && HasTemporaries) { |
2706 | |
2707 | TempDtorContext Context; |
2708 | VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), |
2709 | , Context); |
2710 | } |
2711 | } |
2712 | |
2713 | autoCreateBlock(); |
2714 | appendStmt(Block, DS); |
2715 | |
2716 | findConstructionContexts( |
2717 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS), |
2718 | Init); |
2719 | |
2720 | |
2721 | |
2722 | |
2723 | CFGBlock *LastBlock = Block; |
2724 | |
2725 | if (Init) { |
2726 | if (HasTemporaries) { |
2727 | |
2728 | |
2729 | ExprWithCleanups *EC = cast<ExprWithCleanups>(Init); |
2730 | if (CFGBlock *newBlock = Visit(EC->getSubExpr())) |
2731 | LastBlock = newBlock; |
2732 | } |
2733 | else { |
2734 | if (CFGBlock *newBlock = Visit(Init)) |
2735 | LastBlock = newBlock; |
2736 | } |
2737 | } |
2738 | |
2739 | |
2740 | for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); |
2741 | VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) { |
2742 | if (CFGBlock *newBlock = addStmt(VA->getSizeExpr())) |
2743 | LastBlock = newBlock; |
2744 | } |
2745 | |
2746 | maybeAddScopeBeginForVarDecl(Block, VD, DS); |
2747 | |
2748 | |
2749 | if (ScopePos && VD == *ScopePos) |
2750 | ++ScopePos; |
2751 | |
2752 | CFGBlock *B = LastBlock; |
2753 | if (blockAfterStaticInit) { |
2754 | Succ = B; |
2755 | Block = createBlock(false); |
2756 | Block->setTerminator(DS); |
2757 | addSuccessor(Block, blockAfterStaticInit); |
2758 | addSuccessor(Block, B); |
2759 | B = Block; |
2760 | } |
2761 | |
2762 | return B; |
2763 | } |
2764 | |
2765 | CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { |
2766 | |
2767 | |
2768 | |
2769 | |
2770 | |
2771 | |
2772 | |
2773 | |
2774 | |
2775 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
2776 | |
2777 | |
2778 | if (Stmt *Init = I->getInit()) |
2779 | addLocalScopeForStmt(Init); |
2780 | |
2781 | |
2782 | |
2783 | if (VarDecl *VD = I->getConditionVariable()) |
2784 | addLocalScopeForVarDecl(VD); |
2785 | |
2786 | addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I); |
2787 | |
2788 | |
2789 | |
2790 | if (Block) { |
2791 | Succ = Block; |
2792 | if (badCFG) |
2793 | return nullptr; |
2794 | } |
2795 | |
2796 | |
2797 | CFGBlock *ElseBlock = Succ; |
2798 | |
2799 | if (Stmt *Else = I->getElse()) { |
2800 | SaveAndRestore<CFGBlock*> sv(Succ); |
2801 | |
2802 | |
2803 | |
2804 | Block = nullptr; |
2805 | |
2806 | |
2807 | |
2808 | if (!isa<CompoundStmt>(Else)) |
2809 | addLocalScopeAndDtors(Else); |
2810 | |
2811 | ElseBlock = addStmt(Else); |
2812 | |
2813 | if (!ElseBlock) |
2814 | ElseBlock = sv.get(); |
2815 | else if (Block) { |
2816 | if (badCFG) |
2817 | return nullptr; |
2818 | } |
2819 | } |
2820 | |
2821 | |
2822 | CFGBlock *ThenBlock; |
2823 | { |
2824 | Stmt *Then = I->getThen(); |
2825 | assert(Then); |
2826 | SaveAndRestore<CFGBlock*> sv(Succ); |
2827 | Block = nullptr; |
2828 | |
2829 | |
2830 | |
2831 | if (!isa<CompoundStmt>(Then)) |
2832 | addLocalScopeAndDtors(Then); |
2833 | |
2834 | ThenBlock = addStmt(Then); |
2835 | |
2836 | if (!ThenBlock) { |
2837 | |
2838 | |
2839 | |
2840 | ThenBlock = createBlock(false); |
2841 | addSuccessor(ThenBlock, sv.get()); |
2842 | } else if (Block) { |
2843 | if (badCFG) |
2844 | return nullptr; |
2845 | } |
2846 | } |
2847 | |
2848 | |
2849 | |
2850 | |
2851 | |
2852 | |
2853 | |
2854 | |
2855 | BinaryOperator *Cond = |
2856 | I->getConditionVariable() |
2857 | ? nullptr |
2858 | : dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens()); |
2859 | CFGBlock *LastBlock; |
2860 | if (Cond && Cond->isLogicalOp()) |
2861 | LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first; |
2862 | else { |
2863 | |
2864 | Block = createBlock(false); |
2865 | |
2866 | |
2867 | Block->setTerminator(I); |
2868 | |
2869 | |
2870 | const TryResult &KnownVal = tryEvaluateBool(I->getCond()); |
2871 | |
2872 | |
2873 | |
2874 | addSuccessor(Block, ThenBlock, !KnownVal.isFalse()); |
2875 | addSuccessor(Block, ElseBlock, !KnownVal.isTrue()); |
2876 | |
2877 | |
2878 | |
2879 | |
2880 | LastBlock = addStmt(I->getCond()); |
2881 | |
2882 | |
2883 | |
2884 | if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) { |
2885 | autoCreateBlock(); |
2886 | LastBlock = addStmt(const_cast<DeclStmt *>(DS)); |
2887 | } |
2888 | } |
2889 | |
2890 | |
2891 | if (Stmt *Init = I->getInit()) { |
2892 | autoCreateBlock(); |
2893 | LastBlock = addStmt(Init); |
2894 | } |
2895 | |
2896 | return LastBlock; |
2897 | } |
2898 | |
2899 | CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) { |
2900 | |
2901 | |
2902 | |
2903 | |
2904 | |
2905 | |
2906 | (S) || isa(S)", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 2906, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)); |
2907 | |
2908 | |
2909 | Block = createBlock(false); |
2910 | |
2911 | addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S); |
2912 | |
2913 | if (auto *R = dyn_cast<ReturnStmt>(S)) |
2914 | findConstructionContexts( |
2915 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), R), |
2916 | R->getRetValue()); |
2917 | |
2918 | |
2919 | |
2920 | if (!Block->hasNoReturnElement()) |
2921 | addSuccessor(Block, &cfg->getExit()); |
2922 | |
2923 | |
2924 | |
2925 | return VisitStmt(S, AddStmtChoice::AlwaysAdd); |
2926 | } |
2927 | |
2928 | CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) { |
2929 | |
2930 | |
2931 | |
2932 | |
2933 | |
2934 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
2935 | |
2936 | addStmt(ES->getBlock()); |
2937 | CFGBlock *SEHExceptBlock = Block; |
2938 | if (!SEHExceptBlock) |
2939 | SEHExceptBlock = createBlock(); |
2940 | |
2941 | appendStmt(SEHExceptBlock, ES); |
2942 | |
2943 | |
2944 | SEHExceptBlock->setLabel(ES); |
2945 | |
2946 | |
2947 | if (badCFG) |
2948 | return nullptr; |
2949 | |
2950 | |
2951 | Block = nullptr; |
2952 | |
2953 | return SEHExceptBlock; |
2954 | } |
2955 | |
2956 | CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) { |
2957 | return VisitCompoundStmt(FS->getBlock()); |
2958 | } |
2959 | |
2960 | CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) { |
2961 | |
2962 | |
2963 | if (badCFG) |
2964 | return nullptr; |
2965 | |
2966 | |
2967 | Block = createBlock(false); |
2968 | Block->setTerminator(LS); |
2969 | |
2970 | |
2971 | |
2972 | if (SEHLeaveJumpTarget.block) { |
2973 | addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS); |
2974 | addSuccessor(Block, SEHLeaveJumpTarget.block); |
2975 | } else |
2976 | badCFG = true; |
2977 | |
2978 | return Block; |
2979 | } |
2980 | |
2981 | CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) { |
2982 | |
2983 | |
2984 | CFGBlock *SEHTrySuccessor = nullptr; |
2985 | |
2986 | if (Block) { |
2987 | if (badCFG) |
2988 | return nullptr; |
2989 | SEHTrySuccessor = Block; |
2990 | } else SEHTrySuccessor = Succ; |
2991 | |
2992 | |
2993 | if (Terminator->getFinallyHandler()) |
2994 | return NYS(); |
2995 | |
2996 | CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock; |
2997 | |
2998 | |
2999 | CFGBlock *NewTryTerminatedBlock = createBlock(false); |
3000 | |
3001 | |
3002 | NewTryTerminatedBlock->setTerminator(Terminator); |
3003 | |
3004 | if (SEHExceptStmt *Except = Terminator->getExceptHandler()) { |
3005 | |
3006 | Succ = SEHTrySuccessor; |
3007 | Block = nullptr; |
3008 | CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except); |
3009 | if (!ExceptBlock) |
3010 | return nullptr; |
3011 | |
3012 | |
3013 | addSuccessor(NewTryTerminatedBlock, ExceptBlock); |
3014 | } |
3015 | if (PrevSEHTryTerminatedBlock) |
3016 | addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock); |
3017 | else |
3018 | addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); |
3019 | |
3020 | |
3021 | Succ = SEHTrySuccessor; |
3022 | |
3023 | |
3024 | SaveAndRestore<CFGBlock *> save_try(TryTerminatedBlock, |
3025 | NewTryTerminatedBlock); |
3026 | cfg->addTryDispatchBlock(TryTerminatedBlock); |
3027 | |
3028 | |
3029 | |
3030 | |
3031 | SaveAndRestore<JumpTarget> save_break(SEHLeaveJumpTarget); |
3032 | SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos); |
3033 | |
3034 | (0) . __assert_fail ("Terminator->getTryBlock() && \"__try must contain a non-NULL body\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3034, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Terminator->getTryBlock() && "__try must contain a non-NULL body"); |
3035 | Block = nullptr; |
3036 | return addStmt(Terminator->getTryBlock()); |
3037 | } |
3038 | |
3039 | CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { |
3040 | |
3041 | addStmt(L->getSubStmt()); |
3042 | CFGBlock *LabelBlock = Block; |
3043 | |
3044 | if (!LabelBlock) |
3045 | LabelBlock = createBlock(); |
3046 | |
3047 | (0) . __assert_fail ("LabelMap.find(L->getDecl()) == LabelMap.end() && \"label already in map\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3048, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(LabelMap.find(L->getDecl()) == LabelMap.end() && |
3048 | (0) . __assert_fail ("LabelMap.find(L->getDecl()) == LabelMap.end() && \"label already in map\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3048, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "label already in map"); |
3049 | LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); |
3050 | |
3051 | |
3052 | |
3053 | |
3054 | |
3055 | LabelBlock->setLabel(L); |
3056 | if (badCFG) |
3057 | return nullptr; |
3058 | |
3059 | |
3060 | Block = nullptr; |
3061 | |
3062 | |
3063 | Succ = LabelBlock; |
3064 | |
3065 | return LabelBlock; |
3066 | } |
3067 | |
3068 | CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { |
3069 | CFGBlock *LastBlock = VisitNoRecurse(E, asc); |
3070 | for (const BlockDecl::Capture &CI : E->getBlockDecl()->captures()) { |
3071 | if (Expr *CopyExpr = CI.getCopyExpr()) { |
3072 | CFGBlock *Tmp = Visit(CopyExpr); |
3073 | if (Tmp) |
3074 | LastBlock = Tmp; |
3075 | } |
3076 | } |
3077 | return LastBlock; |
3078 | } |
3079 | |
3080 | CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { |
3081 | CFGBlock *LastBlock = VisitNoRecurse(E, asc); |
3082 | for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), |
3083 | et = E->capture_init_end(); it != et; ++it) { |
3084 | if (Expr *Init = *it) { |
3085 | CFGBlock *Tmp = Visit(Init); |
3086 | if (Tmp) |
3087 | LastBlock = Tmp; |
3088 | } |
3089 | } |
3090 | return LastBlock; |
3091 | } |
3092 | |
3093 | CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { |
3094 | |
3095 | |
3096 | |
3097 | Block = createBlock(false); |
3098 | Block->setTerminator(G); |
3099 | |
3100 | |
3101 | LabelMapTy::iterator I = LabelMap.find(G->getLabel()); |
3102 | |
3103 | if (I == LabelMap.end()) |
3104 | |
3105 | BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); |
3106 | else { |
3107 | JumpTarget JT = I->second; |
3108 | addAutomaticObjHandling(ScopePos, JT.scopePosition, G); |
3109 | addSuccessor(Block, JT.block); |
3110 | } |
3111 | |
3112 | return Block; |
3113 | } |
3114 | |
3115 | CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { |
3116 | CFGBlock *LoopSuccessor = nullptr; |
3117 | |
3118 | |
3119 | |
3120 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
3121 | |
3122 | |
3123 | |
3124 | |
3125 | if (Stmt *Init = F->getInit()) |
3126 | addLocalScopeForStmt(Init); |
3127 | LocalScope::const_iterator LoopBeginScopePos = ScopePos; |
3128 | |
3129 | if (VarDecl *VD = F->getConditionVariable()) |
3130 | addLocalScopeForVarDecl(VD); |
3131 | LocalScope::const_iterator ContinueScopePos = ScopePos; |
3132 | |
3133 | addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F); |
3134 | |
3135 | addLoopExit(F); |
3136 | |
3137 | |
3138 | |
3139 | if (Block) { |
3140 | if (badCFG) |
3141 | return nullptr; |
3142 | LoopSuccessor = Block; |
3143 | } else |
3144 | LoopSuccessor = Succ; |
3145 | |
3146 | |
3147 | |
3148 | SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); |
3149 | BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); |
3150 | |
3151 | CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr; |
3152 | |
3153 | |
3154 | { |
3155 | getBody()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3155, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(F->getBody()); |
3156 | |
3157 | |
3158 | SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); |
3159 | SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); |
3160 | |
3161 | |
3162 | |
3163 | |
3164 | Block = Succ = TransitionBlock = createBlock(false); |
3165 | TransitionBlock->setLoopTarget(F); |
3166 | |
3167 | if (Stmt *I = F->getInc()) { |
3168 | |
3169 | |
3170 | Succ = addStmt(I); |
3171 | } |
3172 | |
3173 | |
3174 | if (Block) { |
3175 | assert(Block == Succ); |
3176 | if (badCFG) |
3177 | return nullptr; |
3178 | Block = nullptr; |
3179 | } |
3180 | |
3181 | |
3182 | |
3183 | ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); |
3184 | ContinueJumpTarget.block->setLoopTarget(F); |
3185 | |
3186 | |
3187 | addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F); |
3188 | |
3189 | |
3190 | |
3191 | if (!isa<CompoundStmt>(F->getBody())) |
3192 | addLocalScopeAndDtors(F->getBody()); |
3193 | |
3194 | |
3195 | |
3196 | BodyBlock = addStmt(F->getBody()); |
3197 | |
3198 | if (!BodyBlock) { |
3199 | |
3200 | |
3201 | BodyBlock = ContinueJumpTarget.block; |
3202 | } |
3203 | else if (badCFG) |
3204 | return nullptr; |
3205 | } |
3206 | |
3207 | |
3208 | |
3209 | |
3210 | CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr; |
3211 | |
3212 | do { |
3213 | Expr *C = F->getCond(); |
3214 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
3215 | |
3216 | |
3217 | |
3218 | if (BinaryOperator *Cond = |
3219 | dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : nullptr)) |
3220 | if (Cond->isLogicalOp()) { |
3221 | std::tie(EntryConditionBlock, ExitConditionBlock) = |
3222 | VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor); |
3223 | break; |
3224 | } |
3225 | |
3226 | |
3227 | EntryConditionBlock = ExitConditionBlock = createBlock(false); |
3228 | ExitConditionBlock->setTerminator(F); |
3229 | |
3230 | |
3231 | TryResult KnownVal(true); |
3232 | |
3233 | if (C) { |
3234 | |
3235 | |
3236 | |
3237 | Block = ExitConditionBlock; |
3238 | EntryConditionBlock = addStmt(C); |
3239 | |
3240 | |
3241 | |
3242 | if (VarDecl *VD = F->getConditionVariable()) { |
3243 | if (Expr *Init = VD->getInit()) { |
3244 | autoCreateBlock(); |
3245 | const DeclStmt *DS = F->getConditionVariableDeclStmt(); |
3246 | isSingleDecl()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3246, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(DS->isSingleDecl()); |
3247 | findConstructionContexts( |
3248 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS), |
3249 | Init); |
3250 | appendStmt(Block, DS); |
3251 | EntryConditionBlock = addStmt(Init); |
3252 | assert(Block == EntryConditionBlock); |
3253 | maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C); |
3254 | } |
3255 | } |
3256 | |
3257 | if (Block && badCFG) |
3258 | return nullptr; |
3259 | |
3260 | KnownVal = tryEvaluateBool(C); |
3261 | } |
3262 | |
3263 | |
3264 | addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock); |
3265 | |
3266 | |
3267 | addSuccessor(ExitConditionBlock, |
3268 | KnownVal.isTrue() ? nullptr : LoopSuccessor); |
3269 | } while (false); |
3270 | |
3271 | |
3272 | addSuccessor(TransitionBlock, EntryConditionBlock); |
3273 | |
3274 | |
3275 | Succ = EntryConditionBlock; |
3276 | |
3277 | |
3278 | |
3279 | if (Stmt *I = F->getInit()) { |
3280 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
3281 | ScopePos = LoopBeginScopePos; |
3282 | Block = createBlock(); |
3283 | return addStmt(I); |
3284 | } |
3285 | |
3286 | |
3287 | |
3288 | Block = nullptr; |
3289 | Succ = EntryConditionBlock; |
3290 | return EntryConditionBlock; |
3291 | } |
3292 | |
3293 | CFGBlock * |
3294 | CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE, |
3295 | AddStmtChoice asc) { |
3296 | findConstructionContexts( |
3297 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE), |
3298 | MTE->getTemporary()); |
3299 | |
3300 | return VisitStmt(MTE, asc); |
3301 | } |
3302 | |
3303 | CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { |
3304 | if (asc.alwaysAdd(*this, M)) { |
3305 | autoCreateBlock(); |
3306 | appendStmt(Block, M); |
3307 | } |
3308 | return Visit(M->getBase()); |
3309 | } |
3310 | |
3311 | CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { |
3312 | |
3313 | |
3314 | |
3315 | |
3316 | |
3317 | |
3318 | |
3319 | |
3320 | |
3321 | |
3322 | |
3323 | |
3324 | |
3325 | |
3326 | |
3327 | |
3328 | |
3329 | |
3330 | |
3331 | |
3332 | |
3333 | |
3334 | |
3335 | |
3336 | |
3337 | |
3338 | |
3339 | |
3340 | |
3341 | |
3342 | |
3343 | CFGBlock *LoopSuccessor = nullptr; |
3344 | |
3345 | if (Block) { |
3346 | if (badCFG) |
3347 | return nullptr; |
3348 | LoopSuccessor = Block; |
3349 | Block = nullptr; |
3350 | } else |
3351 | LoopSuccessor = Succ; |
3352 | |
3353 | |
3354 | CFGBlock *ExitConditionBlock = createBlock(false); |
3355 | |
3356 | |
3357 | ExitConditionBlock->setTerminator(S); |
3358 | |
3359 | |
3360 | |
3361 | |
3362 | appendStmt(ExitConditionBlock, S); |
3363 | Block = ExitConditionBlock; |
3364 | |
3365 | |
3366 | |
3367 | |
3368 | CFGBlock *EntryConditionBlock = Visit(S->getElement(), |
3369 | AddStmtChoice::NotAlwaysAdd); |
3370 | if (Block) { |
3371 | if (badCFG) |
3372 | return nullptr; |
3373 | Block = nullptr; |
3374 | } |
3375 | |
3376 | |
3377 | |
3378 | Succ = EntryConditionBlock; |
3379 | |
3380 | |
3381 | { |
3382 | |
3383 | SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); |
3384 | SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), |
3385 | save_break(BreakJumpTarget); |
3386 | |
3387 | |
3388 | |
3389 | |
3390 | CFGBlock *LoopBackBlock = nullptr; |
3391 | Succ = LoopBackBlock = createBlock(); |
3392 | LoopBackBlock->setLoopTarget(S); |
3393 | |
3394 | BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); |
3395 | ContinueJumpTarget = JumpTarget(Succ, ScopePos); |
3396 | |
3397 | CFGBlock *BodyBlock = addStmt(S->getBody()); |
3398 | |
3399 | if (!BodyBlock) |
3400 | BodyBlock = ContinueJumpTarget.block; |
3401 | else if (Block) { |
3402 | if (badCFG) |
3403 | return nullptr; |
3404 | } |
3405 | |
3406 | |
3407 | addSuccessor(ExitConditionBlock, BodyBlock); |
3408 | } |
3409 | |
3410 | |
3411 | |
3412 | addSuccessor(ExitConditionBlock, LoopSuccessor); |
3413 | |
3414 | |
3415 | Block = createBlock(); |
3416 | return addStmt(S->getCollection()); |
3417 | } |
3418 | |
3419 | CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { |
3420 | |
3421 | return addStmt(S->getSubStmt()); |
3422 | |
3423 | } |
3424 | |
3425 | CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { |
3426 | |
3427 | |
3428 | |
3429 | CFGBlock *SyncBlock = addStmt(S->getSynchBody()); |
3430 | |
3431 | |
3432 | |
3433 | if (SyncBlock) { |
3434 | if (badCFG) |
3435 | return nullptr; |
3436 | |
3437 | Block = nullptr; |
3438 | Succ = SyncBlock; |
3439 | } |
3440 | |
3441 | |
3442 | autoCreateBlock(); |
3443 | appendStmt(Block, S); |
3444 | |
3445 | |
3446 | return addStmt(S->getSynchExpr()); |
3447 | } |
3448 | |
3449 | CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { |
3450 | |
3451 | return NYS(); |
3452 | } |
3453 | |
3454 | CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { |
3455 | autoCreateBlock(); |
3456 | |
3457 | |
3458 | appendStmt(Block, E); |
3459 | |
3460 | CFGBlock *lastBlock = Block; |
3461 | |
3462 | |
3463 | |
3464 | for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { |
3465 | Expr *Semantic = E->getSemanticExpr(--i); |
3466 | |
3467 | |
3468 | |
3469 | if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) |
3470 | Semantic = OVE->getSourceExpr(); |
3471 | |
3472 | if (CFGBlock *B = Visit(Semantic)) |
3473 | lastBlock = B; |
3474 | } |
3475 | |
3476 | return lastBlock; |
3477 | } |
3478 | |
3479 | CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { |
3480 | CFGBlock *LoopSuccessor = nullptr; |
3481 | |
3482 | |
3483 | |
3484 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
3485 | |
3486 | |
3487 | |
3488 | LocalScope::const_iterator LoopBeginScopePos = ScopePos; |
3489 | if (VarDecl *VD = W->getConditionVariable()) { |
3490 | addLocalScopeForVarDecl(VD); |
3491 | addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W); |
3492 | } |
3493 | addLoopExit(W); |
3494 | |
3495 | |
3496 | |
3497 | if (Block) { |
3498 | if (badCFG) |
3499 | return nullptr; |
3500 | LoopSuccessor = Block; |
3501 | Block = nullptr; |
3502 | } else { |
3503 | LoopSuccessor = Succ; |
3504 | } |
3505 | |
3506 | CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr; |
3507 | |
3508 | |
3509 | { |
3510 | getBody()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3510, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(W->getBody()); |
3511 | |
3512 | |
3513 | SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); |
3514 | SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), |
3515 | save_break(BreakJumpTarget); |
3516 | |
3517 | |
3518 | |
3519 | Succ = TransitionBlock = createBlock(false); |
3520 | TransitionBlock->setLoopTarget(W); |
3521 | ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); |
3522 | |
3523 | |
3524 | BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); |
3525 | |
3526 | |
3527 | addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W); |
3528 | |
3529 | |
3530 | |
3531 | if (!isa<CompoundStmt>(W->getBody())) |
3532 | addLocalScopeAndDtors(W->getBody()); |
3533 | |
3534 | |
3535 | BodyBlock = addStmt(W->getBody()); |
3536 | |
3537 | if (!BodyBlock) |
3538 | BodyBlock = ContinueJumpTarget.block; |
3539 | else if (Block && badCFG) |
3540 | return nullptr; |
3541 | } |
3542 | |
3543 | |
3544 | |
3545 | |
3546 | CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr; |
3547 | |
3548 | do { |
3549 | Expr *C = W->getCond(); |
3550 | |
3551 | |
3552 | |
3553 | if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens())) |
3554 | if (Cond->isLogicalOp()) { |
3555 | std::tie(EntryConditionBlock, ExitConditionBlock) = |
3556 | VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor); |
3557 | break; |
3558 | } |
3559 | |
3560 | |
3561 | ExitConditionBlock = createBlock(false); |
3562 | ExitConditionBlock->setTerminator(W); |
3563 | |
3564 | |
3565 | |
3566 | |
3567 | Block = ExitConditionBlock; |
3568 | Block = EntryConditionBlock = addStmt(C); |
3569 | |
3570 | |
3571 | |
3572 | if (VarDecl *VD = W->getConditionVariable()) { |
3573 | if (Expr *Init = VD->getInit()) { |
3574 | autoCreateBlock(); |
3575 | const DeclStmt *DS = W->getConditionVariableDeclStmt(); |
3576 | isSingleDecl()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3576, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(DS->isSingleDecl()); |
3577 | findConstructionContexts( |
3578 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), |
3579 | const_cast<DeclStmt *>(DS)), |
3580 | Init); |
3581 | appendStmt(Block, DS); |
3582 | EntryConditionBlock = addStmt(Init); |
3583 | assert(Block == EntryConditionBlock); |
3584 | maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C); |
3585 | } |
3586 | } |
3587 | |
3588 | if (Block && badCFG) |
3589 | return nullptr; |
3590 | |
3591 | |
3592 | const TryResult& KnownVal = tryEvaluateBool(C); |
3593 | |
3594 | |
3595 | addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock); |
3596 | |
3597 | |
3598 | addSuccessor(ExitConditionBlock, |
3599 | KnownVal.isTrue() ? nullptr : LoopSuccessor); |
3600 | } while(false); |
3601 | |
3602 | |
3603 | addSuccessor(TransitionBlock, EntryConditionBlock); |
3604 | |
3605 | |
3606 | |
3607 | Block = nullptr; |
3608 | |
3609 | |
3610 | Succ = EntryConditionBlock; |
3611 | return EntryConditionBlock; |
3612 | } |
3613 | |
3614 | CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { |
3615 | |
3616 | |
3617 | return Block; |
3618 | } |
3619 | |
3620 | CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { |
3621 | |
3622 | |
3623 | |
3624 | |
3625 | if (badCFG) |
3626 | return nullptr; |
3627 | |
3628 | |
3629 | Block = createBlock(false); |
3630 | |
3631 | |
3632 | addSuccessor(Block, &cfg->getExit()); |
3633 | |
3634 | |
3635 | |
3636 | return VisitStmt(S, AddStmtChoice::AlwaysAdd); |
3637 | } |
3638 | |
3639 | CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME, |
3640 | AddStmtChoice asc) { |
3641 | findConstructionContextsForArguments(ME); |
3642 | |
3643 | autoCreateBlock(); |
3644 | appendObjCMessage(Block, ME); |
3645 | |
3646 | return VisitChildren(ME); |
3647 | } |
3648 | |
3649 | CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { |
3650 | |
3651 | if (badCFG) |
3652 | return nullptr; |
3653 | |
3654 | |
3655 | Block = createBlock(false); |
3656 | |
3657 | if (TryTerminatedBlock) |
3658 | |
3659 | addSuccessor(Block, TryTerminatedBlock); |
3660 | else |
3661 | |
3662 | addSuccessor(Block, &cfg->getExit()); |
3663 | |
3664 | |
3665 | |
3666 | return VisitStmt(T, AddStmtChoice::AlwaysAdd); |
3667 | } |
3668 | |
3669 | CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { |
3670 | CFGBlock *LoopSuccessor = nullptr; |
3671 | |
3672 | addLoopExit(D); |
3673 | |
3674 | |
3675 | |
3676 | if (Block) { |
3677 | if (badCFG) |
3678 | return nullptr; |
3679 | LoopSuccessor = Block; |
3680 | } else |
3681 | LoopSuccessor = Succ; |
3682 | |
3683 | |
3684 | |
3685 | |
3686 | CFGBlock *ExitConditionBlock = createBlock(false); |
3687 | CFGBlock *EntryConditionBlock = ExitConditionBlock; |
3688 | |
3689 | |
3690 | ExitConditionBlock->setTerminator(D); |
3691 | |
3692 | |
3693 | |
3694 | if (Stmt *C = D->getCond()) { |
3695 | Block = ExitConditionBlock; |
3696 | EntryConditionBlock = addStmt(C); |
3697 | if (Block) { |
3698 | if (badCFG) |
3699 | return nullptr; |
3700 | } |
3701 | } |
3702 | |
3703 | |
3704 | Succ = EntryConditionBlock; |
3705 | |
3706 | |
3707 | const TryResult &KnownVal = tryEvaluateBool(D->getCond()); |
3708 | |
3709 | |
3710 | CFGBlock *BodyBlock = nullptr; |
3711 | { |
3712 | getBody()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3712, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(D->getBody()); |
3713 | |
3714 | |
3715 | SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); |
3716 | SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), |
3717 | save_break(BreakJumpTarget); |
3718 | |
3719 | |
3720 | ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); |
3721 | |
3722 | |
3723 | BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); |
3724 | |
3725 | |
3726 | Block = nullptr; |
3727 | |
3728 | |
3729 | |
3730 | if (!isa<CompoundStmt>(D->getBody())) |
3731 | addLocalScopeAndDtors(D->getBody()); |
3732 | |
3733 | |
3734 | BodyBlock = addStmt(D->getBody()); |
3735 | |
3736 | if (!BodyBlock) |
3737 | BodyBlock = EntryConditionBlock; |
3738 | else if (Block) { |
3739 | if (badCFG) |
3740 | return nullptr; |
3741 | } |
3742 | |
3743 | |
3744 | |
3745 | |
3746 | |
3747 | |
3748 | Block = nullptr; |
3749 | Succ = BodyBlock; |
3750 | CFGBlock *LoopBackBlock = createBlock(); |
3751 | LoopBackBlock->setLoopTarget(D); |
3752 | |
3753 | if (!KnownVal.isFalse()) |
3754 | |
3755 | addSuccessor(ExitConditionBlock, LoopBackBlock); |
3756 | else |
3757 | addSuccessor(ExitConditionBlock, nullptr); |
3758 | } |
3759 | |
3760 | |
3761 | |
3762 | addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor); |
3763 | |
3764 | |
3765 | |
3766 | Block = nullptr; |
3767 | |
3768 | |
3769 | Succ = BodyBlock; |
3770 | return BodyBlock; |
3771 | } |
3772 | |
3773 | CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { |
3774 | |
3775 | |
3776 | if (badCFG) |
3777 | return nullptr; |
3778 | |
3779 | |
3780 | Block = createBlock(false); |
3781 | Block->setTerminator(C); |
3782 | |
3783 | |
3784 | |
3785 | if (ContinueJumpTarget.block) { |
3786 | addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C); |
3787 | addSuccessor(Block, ContinueJumpTarget.block); |
3788 | } else |
3789 | badCFG = true; |
3790 | |
3791 | return Block; |
3792 | } |
3793 | |
3794 | CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, |
3795 | AddStmtChoice asc) { |
3796 | if (asc.alwaysAdd(*this, E)) { |
3797 | autoCreateBlock(); |
3798 | appendStmt(Block, E); |
3799 | } |
3800 | |
3801 | |
3802 | CFGBlock *lastBlock = Block; |
3803 | |
3804 | if (E->isArgumentType()) { |
3805 | for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); |
3806 | VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) |
3807 | lastBlock = addStmt(VA->getSizeExpr()); |
3808 | } |
3809 | return lastBlock; |
3810 | } |
3811 | |
3812 | |
3813 | |
3814 | CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { |
3815 | if (asc.alwaysAdd(*this, SE)) { |
3816 | autoCreateBlock(); |
3817 | appendStmt(Block, SE); |
3818 | } |
3819 | return VisitCompoundStmt(SE->getSubStmt()); |
3820 | } |
3821 | |
3822 | CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { |
3823 | |
3824 | |
3825 | CFGBlock *SwitchSuccessor = nullptr; |
3826 | |
3827 | |
3828 | |
3829 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
3830 | |
3831 | |
3832 | if (Stmt *Init = Terminator->getInit()) |
3833 | addLocalScopeForStmt(Init); |
3834 | |
3835 | |
3836 | |
3837 | if (VarDecl *VD = Terminator->getConditionVariable()) |
3838 | addLocalScopeForVarDecl(VD); |
3839 | |
3840 | addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator); |
3841 | |
3842 | if (Block) { |
3843 | if (badCFG) |
3844 | return nullptr; |
3845 | SwitchSuccessor = Block; |
3846 | } else SwitchSuccessor = Succ; |
3847 | |
3848 | |
3849 | SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), |
3850 | save_default(DefaultCaseBlock); |
3851 | SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); |
3852 | |
3853 | |
3854 | |
3855 | |
3856 | DefaultCaseBlock = SwitchSuccessor; |
3857 | |
3858 | |
3859 | SwitchTerminatedBlock = createBlock(false); |
3860 | |
3861 | |
3862 | |
3863 | Succ = SwitchSuccessor; |
3864 | BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); |
3865 | |
3866 | |
3867 | |
3868 | |
3869 | (0) . __assert_fail ("Terminator->getBody() && \"switch must contain a non-NULL body\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3869, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Terminator->getBody() && "switch must contain a non-NULL body"); |
3870 | Block = nullptr; |
3871 | |
3872 | |
3873 | |
3874 | SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, |
3875 | false); |
3876 | |
3877 | |
3878 | (0) . __assert_fail ("Terminator->getCond() && \"switch condition must be non-NULL\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 3878, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Terminator->getCond() && "switch condition must be non-NULL"); |
3879 | Expr::EvalResult result; |
3880 | bool b = tryEvaluate(Terminator->getCond(), result); |
3881 | SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, |
3882 | b ? &result : nullptr); |
3883 | |
3884 | |
3885 | |
3886 | if (!isa<CompoundStmt>(Terminator->getBody())) |
3887 | addLocalScopeAndDtors(Terminator->getBody()); |
3888 | |
3889 | addStmt(Terminator->getBody()); |
3890 | if (Block) { |
3891 | if (badCFG) |
3892 | return nullptr; |
3893 | } |
3894 | |
3895 | |
3896 | |
3897 | |
3898 | |
3899 | |
3900 | |
3901 | bool SwitchAlwaysHasSuccessor = false; |
3902 | SwitchAlwaysHasSuccessor |= switchExclusivelyCovered; |
3903 | SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() && |
3904 | Terminator->getSwitchCaseList(); |
3905 | addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock, |
3906 | !SwitchAlwaysHasSuccessor); |
3907 | |
3908 | |
3909 | SwitchTerminatedBlock->setTerminator(Terminator); |
3910 | Block = SwitchTerminatedBlock; |
3911 | CFGBlock *LastBlock = addStmt(Terminator->getCond()); |
3912 | |
3913 | |
3914 | |
3915 | if (VarDecl *VD = Terminator->getConditionVariable()) { |
3916 | if (Expr *Init = VD->getInit()) { |
3917 | autoCreateBlock(); |
3918 | appendStmt(Block, Terminator->getConditionVariableDeclStmt()); |
3919 | LastBlock = addStmt(Init); |
3920 | maybeAddScopeBeginForVarDecl(LastBlock, VD, Init); |
3921 | } |
3922 | } |
3923 | |
3924 | |
3925 | if (Stmt *Init = Terminator->getInit()) { |
3926 | autoCreateBlock(); |
3927 | LastBlock = addStmt(Init); |
3928 | } |
3929 | |
3930 | return LastBlock; |
3931 | } |
3932 | |
3933 | static bool shouldAddCase(bool &switchExclusivelyCovered, |
3934 | const Expr::EvalResult *switchCond, |
3935 | const CaseStmt *CS, |
3936 | ASTContext &Ctx) { |
3937 | if (!switchCond) |
3938 | return true; |
3939 | |
3940 | bool addCase = false; |
3941 | |
3942 | if (!switchExclusivelyCovered) { |
3943 | if (switchCond->Val.isInt()) { |
3944 | |
3945 | const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx); |
3946 | const llvm::APSInt &condInt = switchCond->Val.getInt(); |
3947 | |
3948 | if (condInt == lhsInt) { |
3949 | addCase = true; |
3950 | switchExclusivelyCovered = true; |
3951 | } |
3952 | else if (condInt > lhsInt) { |
3953 | if (const Expr *RHS = CS->getRHS()) { |
3954 | |
3955 | const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx); |
3956 | if (V2 >= condInt) { |
3957 | addCase = true; |
3958 | switchExclusivelyCovered = true; |
3959 | } |
3960 | } |
3961 | } |
3962 | } |
3963 | else |
3964 | addCase = true; |
3965 | } |
3966 | return addCase; |
3967 | } |
3968 | |
3969 | CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { |
3970 | |
3971 | |
3972 | CFGBlock *TopBlock = nullptr, *LastBlock = nullptr; |
3973 | |
3974 | if (Stmt *Sub = CS->getSubStmt()) { |
3975 | |
3976 | |
3977 | |
3978 | while (isa<CaseStmt>(Sub)) { |
3979 | CFGBlock *currentBlock = createBlock(false); |
3980 | currentBlock->setLabel(CS); |
3981 | |
3982 | if (TopBlock) |
3983 | addSuccessor(LastBlock, currentBlock); |
3984 | else |
3985 | TopBlock = currentBlock; |
3986 | |
3987 | addSuccessor(SwitchTerminatedBlock, |
3988 | shouldAddCase(switchExclusivelyCovered, switchCond, |
3989 | CS, *Context) |
3990 | ? currentBlock : nullptr); |
3991 | |
3992 | LastBlock = currentBlock; |
3993 | CS = cast<CaseStmt>(Sub); |
3994 | Sub = CS->getSubStmt(); |
3995 | } |
3996 | |
3997 | addStmt(Sub); |
3998 | } |
3999 | |
4000 | CFGBlock *CaseBlock = Block; |
4001 | if (!CaseBlock) |
4002 | CaseBlock = createBlock(); |
4003 | |
4004 | |
4005 | |
4006 | CaseBlock->setLabel(CS); |
4007 | |
4008 | if (badCFG) |
4009 | return nullptr; |
4010 | |
4011 | |
4012 | |
4013 | assert(SwitchTerminatedBlock); |
4014 | addSuccessor(SwitchTerminatedBlock, CaseBlock, |
4015 | shouldAddCase(switchExclusivelyCovered, switchCond, |
4016 | CS, *Context)); |
4017 | |
4018 | |
4019 | Block = nullptr; |
4020 | |
4021 | if (TopBlock) { |
4022 | addSuccessor(LastBlock, CaseBlock); |
4023 | Succ = TopBlock; |
4024 | } else { |
4025 | |
4026 | Succ = CaseBlock; |
4027 | } |
4028 | |
4029 | return Succ; |
4030 | } |
4031 | |
4032 | CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { |
4033 | if (Terminator->getSubStmt()) |
4034 | addStmt(Terminator->getSubStmt()); |
4035 | |
4036 | DefaultCaseBlock = Block; |
4037 | |
4038 | if (!DefaultCaseBlock) |
4039 | DefaultCaseBlock = createBlock(); |
4040 | |
4041 | |
4042 | |
4043 | DefaultCaseBlock->setLabel(Terminator); |
4044 | |
4045 | if (badCFG) |
4046 | return nullptr; |
4047 | |
4048 | |
4049 | |
4050 | |
4051 | |
4052 | |
4053 | |
4054 | |
4055 | Block = nullptr; |
4056 | |
4057 | |
4058 | Succ = DefaultCaseBlock; |
4059 | |
4060 | return DefaultCaseBlock; |
4061 | } |
4062 | |
4063 | CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { |
4064 | |
4065 | |
4066 | CFGBlock *TrySuccessor = nullptr; |
4067 | |
4068 | if (Block) { |
4069 | if (badCFG) |
4070 | return nullptr; |
4071 | TrySuccessor = Block; |
4072 | } else TrySuccessor = Succ; |
4073 | |
4074 | CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; |
4075 | |
4076 | |
4077 | CFGBlock *NewTryTerminatedBlock = createBlock(false); |
4078 | |
4079 | NewTryTerminatedBlock->setTerminator(Terminator); |
4080 | |
4081 | bool HasCatchAll = false; |
4082 | for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { |
4083 | |
4084 | Succ = TrySuccessor; |
4085 | CXXCatchStmt *CS = Terminator->getHandler(h); |
4086 | if (CS->getExceptionDecl() == nullptr) { |
4087 | HasCatchAll = true; |
4088 | } |
4089 | Block = nullptr; |
4090 | CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); |
4091 | if (!CatchBlock) |
4092 | return nullptr; |
4093 | |
4094 | |
4095 | addSuccessor(NewTryTerminatedBlock, CatchBlock); |
4096 | } |
4097 | if (!HasCatchAll) { |
4098 | if (PrevTryTerminatedBlock) |
4099 | addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); |
4100 | else |
4101 | addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); |
4102 | } |
4103 | |
4104 | |
4105 | Succ = TrySuccessor; |
4106 | |
4107 | |
4108 | SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock); |
4109 | cfg->addTryDispatchBlock(TryTerminatedBlock); |
4110 | |
4111 | (0) . __assert_fail ("Terminator->getTryBlock() && \"try must contain a non-NULL body\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 4111, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); |
4112 | Block = nullptr; |
4113 | return addStmt(Terminator->getTryBlock()); |
4114 | } |
4115 | |
4116 | CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { |
4117 | |
4118 | |
4119 | |
4120 | |
4121 | |
4122 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
4123 | |
4124 | |
4125 | |
4126 | if (VarDecl *VD = CS->getExceptionDecl()) { |
4127 | LocalScope::const_iterator BeginScopePos = ScopePos; |
4128 | addLocalScopeForVarDecl(VD); |
4129 | addAutomaticObjHandling(ScopePos, BeginScopePos, CS); |
4130 | } |
4131 | |
4132 | if (CS->getHandlerBlock()) |
4133 | addStmt(CS->getHandlerBlock()); |
4134 | |
4135 | CFGBlock *CatchBlock = Block; |
4136 | if (!CatchBlock) |
4137 | CatchBlock = createBlock(); |
4138 | |
4139 | |
4140 | |
4141 | |
4142 | |
4143 | appendStmt(CatchBlock, CS); |
4144 | |
4145 | |
4146 | |
4147 | CatchBlock->setLabel(CS); |
4148 | |
4149 | |
4150 | if (badCFG) |
4151 | return nullptr; |
4152 | |
4153 | |
4154 | Block = nullptr; |
4155 | |
4156 | return CatchBlock; |
4157 | } |
4158 | |
4159 | CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { |
4160 | |
4161 | |
4162 | |
4163 | |
4164 | |
4165 | |
4166 | |
4167 | |
4168 | |
4169 | |
4170 | |
4171 | |
4172 | |
4173 | |
4174 | SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); |
4175 | |
4176 | |
4177 | if (Stmt *Range = S->getRangeStmt()) |
4178 | addLocalScopeForStmt(Range); |
4179 | if (Stmt *Begin = S->getBeginStmt()) |
4180 | addLocalScopeForStmt(Begin); |
4181 | if (Stmt *End = S->getEndStmt()) |
4182 | addLocalScopeForStmt(End); |
4183 | addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S); |
4184 | |
4185 | LocalScope::const_iterator ContinueScopePos = ScopePos; |
4186 | |
4187 | |
4188 | |
4189 | CFGBlock *LoopSuccessor = nullptr; |
4190 | if (Block) { |
4191 | if (badCFG) |
4192 | return nullptr; |
4193 | LoopSuccessor = Block; |
4194 | } else |
4195 | LoopSuccessor = Succ; |
4196 | |
4197 | |
4198 | |
4199 | SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); |
4200 | BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); |
4201 | |
4202 | |
4203 | CFGBlock *ConditionBlock = createBlock(false); |
4204 | ConditionBlock->setTerminator(S); |
4205 | |
4206 | |
4207 | if (Expr *C = S->getCond()) { |
4208 | Block = ConditionBlock; |
4209 | CFGBlock *BeginConditionBlock = addStmt(C); |
4210 | if (badCFG) |
4211 | return nullptr; |
4212 | (0) . __assert_fail ("BeginConditionBlock == ConditionBlock && \"condition block in for-range was unexpectedly complex\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 4213, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BeginConditionBlock == ConditionBlock && |
4213 | (0) . __assert_fail ("BeginConditionBlock == ConditionBlock && \"condition block in for-range was unexpectedly complex\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 4213, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "condition block in for-range was unexpectedly complex"); |
4214 | (void)BeginConditionBlock; |
4215 | } |
4216 | |
4217 | |
4218 | |
4219 | Succ = ConditionBlock; |
4220 | |
4221 | |
4222 | TryResult KnownVal(true); |
4223 | |
4224 | if (S->getCond()) |
4225 | KnownVal = tryEvaluateBool(S->getCond()); |
4226 | |
4227 | |
4228 | { |
4229 | getBody()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 4229, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(S->getBody()); |
4230 | |
4231 | |
4232 | SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); |
4233 | SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); |
4234 | |
4235 | |
4236 | |
4237 | Block = nullptr; |
4238 | Succ = addStmt(S->getInc()); |
4239 | if (badCFG) |
4240 | return nullptr; |
4241 | ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); |
4242 | |
4243 | |
4244 | |
4245 | ContinueJumpTarget.block->setLoopTarget(S); |
4246 | |
4247 | |
4248 | assert(Block); |
4249 | if (badCFG) |
4250 | return nullptr; |
4251 | Block = nullptr; |
4252 | |
4253 | |
4254 | addLocalScopeAndDtors(S->getLoopVarStmt()); |
4255 | |
4256 | |
4257 | addStmt(S->getBody()); |
4258 | if (badCFG) |
4259 | return nullptr; |
4260 | CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt()); |
4261 | if (badCFG) |
4262 | return nullptr; |
4263 | |
4264 | |
4265 | addSuccessor(ConditionBlock, |
4266 | KnownVal.isFalse() ? nullptr : LoopVarStmtBlock); |
4267 | } |
4268 | |
4269 | |
4270 | |
4271 | addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor); |
4272 | |
4273 | |
4274 | Block = createBlock(); |
4275 | addStmt(S->getBeginStmt()); |
4276 | addStmt(S->getEndStmt()); |
4277 | CFGBlock *Head = addStmt(S->getRangeStmt()); |
4278 | if (S->getInit()) |
4279 | Head = addStmt(S->getInit()); |
4280 | return Head; |
4281 | } |
4282 | |
4283 | CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, |
4284 | AddStmtChoice asc) { |
4285 | if (BuildOpts.AddTemporaryDtors) { |
4286 | |
4287 | |
4288 | TempDtorContext Context; |
4289 | VisitForTemporaryDtors(E->getSubExpr(), false, Context); |
4290 | |
4291 | |
4292 | |
4293 | asc = asc.withAlwaysAdd(true); |
4294 | } |
4295 | return Visit(E->getSubExpr(), asc); |
4296 | } |
4297 | |
4298 | CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, |
4299 | AddStmtChoice asc) { |
4300 | if (asc.alwaysAdd(*this, E)) { |
4301 | autoCreateBlock(); |
4302 | appendStmt(Block, E); |
4303 | |
4304 | findConstructionContexts( |
4305 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), E), |
4306 | E->getSubExpr()); |
4307 | |
4308 | |
4309 | asc = asc.withAlwaysAdd(false); |
4310 | } |
4311 | return Visit(E->getSubExpr(), asc); |
4312 | } |
4313 | |
4314 | CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, |
4315 | AddStmtChoice asc) { |
4316 | |
4317 | |
4318 | |
4319 | findConstructionContextsForArguments(C); |
4320 | |
4321 | autoCreateBlock(); |
4322 | appendConstructor(Block, C); |
4323 | |
4324 | return VisitChildren(C); |
4325 | } |
4326 | |
4327 | CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE, |
4328 | AddStmtChoice asc) { |
4329 | autoCreateBlock(); |
4330 | appendStmt(Block, NE); |
4331 | |
4332 | findConstructionContexts( |
4333 | ConstructionContextLayer::create(cfg->getBumpVectorContext(), NE), |
4334 | const_cast<CXXConstructExpr *>(NE->getConstructExpr())); |
4335 | |
4336 | if (NE->getInitializer()) |
4337 | Block = Visit(NE->getInitializer()); |
4338 | |
4339 | if (BuildOpts.AddCXXNewAllocator) |
4340 | appendNewAllocator(Block, NE); |
4341 | |
4342 | if (NE->isArray()) |
4343 | Block = Visit(NE->getArraySize()); |
4344 | |
4345 | for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(), |
4346 | E = NE->placement_arg_end(); I != E; ++I) |
4347 | Block = Visit(*I); |
4348 | |
4349 | return Block; |
4350 | } |
4351 | |
4352 | CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE, |
4353 | AddStmtChoice asc) { |
4354 | autoCreateBlock(); |
4355 | appendStmt(Block, DE); |
4356 | QualType DTy = DE->getDestroyedType(); |
4357 | if (!DTy.isNull()) { |
4358 | DTy = DTy.getNonReferenceType(); |
4359 | CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl(); |
4360 | if (RD) { |
4361 | if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor()) |
4362 | appendDeleteDtor(Block, RD, DE); |
4363 | } |
4364 | } |
4365 | |
4366 | return VisitChildren(DE); |
4367 | } |
4368 | |
4369 | CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, |
4370 | AddStmtChoice asc) { |
4371 | if (asc.alwaysAdd(*this, E)) { |
4372 | autoCreateBlock(); |
4373 | appendStmt(Block, E); |
4374 | |
4375 | asc = asc.withAlwaysAdd(false); |
4376 | } |
4377 | return Visit(E->getSubExpr(), asc); |
4378 | } |
4379 | |
4380 | CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, |
4381 | AddStmtChoice asc) { |
4382 | |
4383 | |
4384 | |
4385 | findConstructionContextsForArguments(C); |
4386 | |
4387 | autoCreateBlock(); |
4388 | appendConstructor(Block, C); |
4389 | return VisitChildren(C); |
4390 | } |
4391 | |
4392 | CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, |
4393 | AddStmtChoice asc) { |
4394 | if (asc.alwaysAdd(*this, E)) { |
4395 | autoCreateBlock(); |
4396 | appendStmt(Block, E); |
4397 | } |
4398 | return Visit(E->getSubExpr(), AddStmtChoice()); |
4399 | } |
4400 | |
4401 | CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) { |
4402 | return Visit(E->getSubExpr(), AddStmtChoice()); |
4403 | } |
4404 | |
4405 | CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { |
4406 | |
4407 | CFGBlock *IBlock = cfg->getIndirectGotoBlock(); |
4408 | |
4409 | if (!IBlock) { |
4410 | IBlock = createBlock(false); |
4411 | cfg->setIndirectGotoBlock(IBlock); |
4412 | } |
4413 | |
4414 | |
4415 | |
4416 | if (badCFG) |
4417 | return nullptr; |
4418 | |
4419 | Block = createBlock(false); |
4420 | Block->setTerminator(I); |
4421 | addSuccessor(Block, IBlock); |
4422 | return addStmt(I->getTarget()); |
4423 | } |
4424 | |
4425 | CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary, |
4426 | TempDtorContext &Context) { |
4427 | assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors); |
4428 | |
4429 | tryAgain: |
4430 | if (!E) { |
4431 | badCFG = true; |
4432 | return nullptr; |
4433 | } |
4434 | switch (E->getStmtClass()) { |
4435 | default: |
4436 | return VisitChildrenForTemporaryDtors(E, Context); |
4437 | |
4438 | case Stmt::BinaryOperatorClass: |
4439 | return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E), |
4440 | Context); |
4441 | |
4442 | case Stmt::CXXBindTemporaryExprClass: |
4443 | return VisitCXXBindTemporaryExprForTemporaryDtors( |
4444 | cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context); |
4445 | |
4446 | case Stmt::BinaryConditionalOperatorClass: |
4447 | case Stmt::ConditionalOperatorClass: |
4448 | return VisitConditionalOperatorForTemporaryDtors( |
4449 | cast<AbstractConditionalOperator>(E), BindToTemporary, Context); |
4450 | |
4451 | case Stmt::ImplicitCastExprClass: |
4452 | |
4453 | E = cast<CastExpr>(E)->getSubExpr(); |
4454 | goto tryAgain; |
4455 | |
4456 | case Stmt::CXXFunctionalCastExprClass: |
4457 | |
4458 | E = cast<CXXFunctionalCastExpr>(E)->getSubExpr(); |
4459 | goto tryAgain; |
4460 | |
4461 | case Stmt::ConstantExprClass: |
4462 | E = cast<ConstantExpr>(E)->getSubExpr(); |
4463 | goto tryAgain; |
4464 | |
4465 | case Stmt::ParenExprClass: |
4466 | E = cast<ParenExpr>(E)->getSubExpr(); |
4467 | goto tryAgain; |
4468 | |
4469 | case Stmt::MaterializeTemporaryExprClass: { |
4470 | const MaterializeTemporaryExpr* MTE = cast<MaterializeTemporaryExpr>(E); |
4471 | BindToTemporary = (MTE->getStorageDuration() != SD_FullExpression); |
4472 | SmallVector<const Expr *, 2> CommaLHSs; |
4473 | SmallVector<SubobjectAdjustment, 2> Adjustments; |
4474 | |
4475 | E = const_cast<Expr *>( |
4476 | cast<MaterializeTemporaryExpr>(E) |
4477 | ->GetTemporaryExpr() |
4478 | ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments)); |
4479 | |
4480 | for (const Expr *CommaLHS : CommaLHSs) { |
4481 | VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS), |
4482 | , Context); |
4483 | } |
4484 | goto tryAgain; |
4485 | } |
4486 | |
4487 | case Stmt::BlockExprClass: |
4488 | |
4489 | |
4490 | return Block; |
4491 | |
4492 | case Stmt::LambdaExprClass: { |
4493 | |
4494 | |
4495 | auto *LE = cast<LambdaExpr>(E); |
4496 | CFGBlock *B = Block; |
4497 | for (Expr *Init : LE->capture_inits()) { |
4498 | if (Init) { |
4499 | if (CFGBlock *R = VisitForTemporaryDtors( |
4500 | Init, , Context)) |
4501 | B = R; |
4502 | } |
4503 | } |
4504 | return B; |
4505 | } |
4506 | |
4507 | case Stmt::CXXDefaultArgExprClass: |
4508 | E = cast<CXXDefaultArgExpr>(E)->getExpr(); |
4509 | goto tryAgain; |
4510 | |
4511 | case Stmt::CXXDefaultInitExprClass: |
4512 | E = cast<CXXDefaultInitExpr>(E)->getExpr(); |
4513 | goto tryAgain; |
4514 | } |
4515 | } |
4516 | |
4517 | CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E, |
4518 | TempDtorContext &Context) { |
4519 | if (isa<LambdaExpr>(E)) { |
4520 | |
4521 | return Block; |
4522 | } |
4523 | |
4524 | |
4525 | |
4526 | |
4527 | |
4528 | CFGBlock *B = Block; |
4529 | for (Stmt *Child : E->children()) |
4530 | if (Child) |
4531 | if (CFGBlock *R = VisitForTemporaryDtors(Child, false, Context)) |
4532 | B = R; |
4533 | |
4534 | return B; |
4535 | } |
4536 | |
4537 | CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors( |
4538 | BinaryOperator *E, TempDtorContext &Context) { |
4539 | if (E->isLogicalOp()) { |
4540 | VisitForTemporaryDtors(E->getLHS(), false, Context); |
4541 | TryResult RHSExecuted = tryEvaluateBool(E->getLHS()); |
4542 | if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr) |
4543 | RHSExecuted.negate(); |
4544 | |
4545 | |
4546 | |
4547 | |
4548 | TempDtorContext RHSContext( |
4549 | bothKnownTrue(Context.KnownExecuted, RHSExecuted)); |
4550 | VisitForTemporaryDtors(E->getRHS(), false, RHSContext); |
4551 | InsertTempDtorDecisionBlock(RHSContext); |
4552 | |
4553 | return Block; |
4554 | } |
4555 | |
4556 | if (E->isAssignmentOp()) { |
4557 | |
4558 | |
4559 | CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context); |
4560 | CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context); |
4561 | return LHSBlock ? LHSBlock : RHSBlock; |
4562 | } |
4563 | |
4564 | |
4565 | |
4566 | |
4567 | CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context); |
4568 | CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context); |
4569 | return RHSBlock ? RHSBlock : LHSBlock; |
4570 | } |
4571 | |
4572 | CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( |
4573 | CXXBindTemporaryExpr *E, bool BindToTemporary, TempDtorContext &Context) { |
4574 | |
4575 | CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), false, Context); |
4576 | if (!BindToTemporary) { |
4577 | |
4578 | |
4579 | |
4580 | const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); |
4581 | |
4582 | if (Dtor->getParent()->isAnyDestructorNoReturn()) { |
4583 | |
4584 | |
4585 | |
4586 | |
4587 | if (B) Succ = B; |
4588 | Block = createNoReturnBlock(); |
4589 | } else if (Context.needsTempDtorBranch()) { |
4590 | |
4591 | |
4592 | if (B) Succ = B; |
4593 | Block = createBlock(); |
4594 | } else { |
4595 | autoCreateBlock(); |
4596 | } |
4597 | if (Context.needsTempDtorBranch()) { |
4598 | Context.setDecisionPoint(Succ, E); |
4599 | } |
4600 | appendTemporaryDtor(Block, E); |
4601 | |
4602 | B = Block; |
4603 | } |
4604 | return B; |
4605 | } |
4606 | |
4607 | void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context, |
4608 | CFGBlock *FalseSucc) { |
4609 | if (!Context.TerminatorExpr) { |
4610 | |
4611 | return; |
4612 | } |
4613 | assert(Context.TerminatorExpr); |
4614 | CFGBlock *Decision = createBlock(false); |
4615 | Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true)); |
4616 | addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse()); |
4617 | addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ, |
4618 | !Context.KnownExecuted.isTrue()); |
4619 | Block = Decision; |
4620 | } |
4621 | |
4622 | CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( |
4623 | AbstractConditionalOperator *E, bool BindToTemporary, |
4624 | TempDtorContext &Context) { |
4625 | VisitForTemporaryDtors(E->getCond(), false, Context); |
4626 | CFGBlock *ConditionBlock = Block; |
4627 | CFGBlock *ConditionSucc = Succ; |
4628 | TryResult ConditionVal = tryEvaluateBool(E->getCond()); |
4629 | TryResult NegatedVal = ConditionVal; |
4630 | if (NegatedVal.isKnown()) NegatedVal.negate(); |
4631 | |
4632 | TempDtorContext TrueContext( |
4633 | bothKnownTrue(Context.KnownExecuted, ConditionVal)); |
4634 | VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext); |
4635 | CFGBlock *TrueBlock = Block; |
4636 | |
4637 | Block = ConditionBlock; |
4638 | Succ = ConditionSucc; |
4639 | TempDtorContext FalseContext( |
4640 | bothKnownTrue(Context.KnownExecuted, NegatedVal)); |
4641 | VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext); |
4642 | |
4643 | if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) { |
4644 | InsertTempDtorDecisionBlock(FalseContext, TrueBlock); |
4645 | } else if (TrueContext.TerminatorExpr) { |
4646 | Block = TrueBlock; |
4647 | InsertTempDtorDecisionBlock(TrueContext); |
4648 | } else { |
4649 | InsertTempDtorDecisionBlock(FalseContext); |
4650 | } |
4651 | return Block; |
4652 | } |
4653 | |
4654 | |
4655 | |
4656 | |
4657 | CFGBlock *CFG::createBlock() { |
4658 | bool first_block = begin() == end(); |
4659 | |
4660 | |
4661 | CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); |
4662 | new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); |
4663 | Blocks.push_back(Mem, BlkBVC); |
4664 | |
4665 | |
4666 | if (first_block) |
4667 | Entry = Exit = &back(); |
4668 | |
4669 | |
4670 | return &back(); |
4671 | } |
4672 | |
4673 | |
4674 | std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement, |
4675 | ASTContext *C, const BuildOptions &BO) { |
4676 | CFGBuilder Builder(C, BO); |
4677 | return Builder.buildCFG(D, Statement); |
4678 | } |
4679 | |
4680 | const CXXDestructorDecl * |
4681 | CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { |
4682 | switch (getKind()) { |
4683 | case CFGElement::Initializer: |
4684 | case CFGElement::NewAllocator: |
4685 | case CFGElement::LoopExit: |
4686 | case CFGElement::LifetimeEnds: |
4687 | case CFGElement::Statement: |
4688 | case CFGElement::Constructor: |
4689 | case CFGElement::CXXRecordTypedCall: |
4690 | case CFGElement::ScopeBegin: |
4691 | case CFGElement::ScopeEnd: |
4692 | llvm_unreachable("getDestructorDecl should only be used with " |
4693 | "ImplicitDtors"); |
4694 | case CFGElement::AutomaticObjectDtor: { |
4695 | const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl(); |
4696 | QualType ty = var->getType(); |
4697 | |
4698 | |
4699 | |
4700 | |
4701 | |
4702 | if (ty->isReferenceType()) { |
4703 | if (const Expr *Init = var->getInit()) { |
4704 | ty = getReferenceInitTemporaryType(Init); |
4705 | } |
4706 | } |
4707 | |
4708 | while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { |
4709 | ty = arrayType->getElementType(); |
4710 | } |
4711 | const RecordType *recordType = ty->getAs<RecordType>(); |
4712 | const CXXRecordDecl *classDecl = |
4713 | cast<CXXRecordDecl>(recordType->getDecl()); |
4714 | return classDecl->getDestructor(); |
4715 | } |
4716 | case CFGElement::DeleteDtor: { |
4717 | const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr(); |
4718 | QualType DTy = DE->getDestroyedType(); |
4719 | DTy = DTy.getNonReferenceType(); |
4720 | const CXXRecordDecl *classDecl = |
4721 | astContext.getBaseElementType(DTy)->getAsCXXRecordDecl(); |
4722 | return classDecl->getDestructor(); |
4723 | } |
4724 | case CFGElement::TemporaryDtor: { |
4725 | const CXXBindTemporaryExpr *bindExpr = |
4726 | castAs<CFGTemporaryDtor>().getBindTemporaryExpr(); |
4727 | const CXXTemporary *temp = bindExpr->getTemporary(); |
4728 | return temp->getDestructor(); |
4729 | } |
4730 | case CFGElement::BaseDtor: |
4731 | case CFGElement::MemberDtor: |
4732 | |
4733 | return nullptr; |
4734 | } |
4735 | llvm_unreachable("getKind() returned bogus value"); |
4736 | } |
4737 | |
4738 | bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { |
4739 | if (const CXXDestructorDecl *DD = getDestructorDecl(astContext)) |
4740 | return DD->isNoReturn(); |
4741 | return false; |
4742 | } |
4743 | |
4744 | |
4745 | |
4746 | |
4747 | |
4748 | CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable) |
4749 | : ReachableBlock(IsReachable ? B : nullptr), |
4750 | UnreachableBlock(!IsReachable ? B : nullptr, |
4751 | B && IsReachable ? AB_Normal : AB_Unreachable) {} |
4752 | |
4753 | CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock) |
4754 | : ReachableBlock(B), |
4755 | UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock, |
4756 | B == AlternateBlock ? AB_Alternate : AB_Normal) {} |
4757 | |
4758 | void CFGBlock::addSuccessor(AdjacentBlock Succ, |
4759 | BumpVectorContext &C) { |
4760 | if (CFGBlock *B = Succ.getReachableBlock()) |
4761 | B->Preds.push_back(AdjacentBlock(this, Succ.isReachable()), C); |
4762 | |
4763 | if (CFGBlock *UnreachableB = Succ.getPossiblyUnreachableBlock()) |
4764 | UnreachableB->Preds.push_back(AdjacentBlock(this, false), C); |
4765 | |
4766 | Succs.push_back(Succ, C); |
4767 | } |
4768 | |
4769 | bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, |
4770 | const CFGBlock *From, const CFGBlock *To) { |
4771 | if (F.IgnoreNullPredecessors && !From) |
4772 | return true; |
4773 | |
4774 | if (To && From && F.IgnoreDefaultsWithCoveredEnums) { |
4775 | |
4776 | |
4777 | if (const SwitchStmt *S = |
4778 | dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { |
4779 | if (S->isAllEnumCasesCovered()) { |
4780 | const Stmt *L = To->getLabel(); |
4781 | if (!L || !isa<CaseStmt>(L)) |
4782 | return true; |
4783 | } |
4784 | } |
4785 | } |
4786 | |
4787 | return false; |
4788 | } |
4789 | |
4790 | |
4791 | |
4792 | |
4793 | |
4794 | namespace { |
4795 | |
4796 | class StmtPrinterHelper : public PrinterHelper { |
4797 | using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>; |
4798 | using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>; |
4799 | |
4800 | StmtMapTy StmtMap; |
4801 | DeclMapTy DeclMap; |
4802 | signed currentBlock = 0; |
4803 | unsigned currStmt = 0; |
4804 | const LangOptions &LangOpts; |
4805 | |
4806 | public: |
4807 | StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) |
4808 | : LangOpts(LO) { |
4809 | for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { |
4810 | unsigned j = 1; |
4811 | for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; |
4812 | BI != BEnd; ++BI, ++j ) { |
4813 | if (Optional<CFGStmt> SE = BI->getAs<CFGStmt>()) { |
4814 | const Stmt *stmt= SE->getStmt(); |
4815 | std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); |
4816 | StmtMap[stmt] = P; |
4817 | |
4818 | switch (stmt->getStmtClass()) { |
4819 | case Stmt::DeclStmtClass: |
4820 | DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; |
4821 | break; |
4822 | case Stmt::IfStmtClass: { |
4823 | const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); |
4824 | if (var) |
4825 | DeclMap[var] = P; |
4826 | break; |
4827 | } |
4828 | case Stmt::ForStmtClass: { |
4829 | const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); |
4830 | if (var) |
4831 | DeclMap[var] = P; |
4832 | break; |
4833 | } |
4834 | case Stmt::WhileStmtClass: { |
4835 | const VarDecl *var = |
4836 | cast<WhileStmt>(stmt)->getConditionVariable(); |
4837 | if (var) |
4838 | DeclMap[var] = P; |
4839 | break; |
4840 | } |
4841 | case Stmt::SwitchStmtClass: { |
4842 | const VarDecl *var = |
4843 | cast<SwitchStmt>(stmt)->getConditionVariable(); |
4844 | if (var) |
4845 | DeclMap[var] = P; |
4846 | break; |
4847 | } |
4848 | case Stmt::CXXCatchStmtClass: { |
4849 | const VarDecl *var = |
4850 | cast<CXXCatchStmt>(stmt)->getExceptionDecl(); |
4851 | if (var) |
4852 | DeclMap[var] = P; |
4853 | break; |
4854 | } |
4855 | default: |
4856 | break; |
4857 | } |
4858 | } |
4859 | } |
4860 | } |
4861 | } |
4862 | |
4863 | ~StmtPrinterHelper() override = default; |
4864 | |
4865 | const LangOptions &getLangOpts() const { return LangOpts; } |
4866 | void setBlockID(signed i) { currentBlock = i; } |
4867 | void setStmtID(unsigned i) { currStmt = i; } |
4868 | |
4869 | bool handledStmt(Stmt *S, raw_ostream &OS) override { |
4870 | StmtMapTy::iterator I = StmtMap.find(S); |
4871 | |
4872 | if (I == StmtMap.end()) |
4873 | return false; |
4874 | |
4875 | if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock |
4876 | && I->second.second == currStmt) { |
4877 | return false; |
4878 | } |
4879 | |
4880 | OS << "[B" << I->second.first << "." << I->second.second << "]"; |
4881 | return true; |
4882 | } |
4883 | |
4884 | bool handleDecl(const Decl *D, raw_ostream &OS) { |
4885 | DeclMapTy::iterator I = DeclMap.find(D); |
4886 | |
4887 | if (I == DeclMap.end()) |
4888 | return false; |
4889 | |
4890 | if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock |
4891 | && I->second.second == currStmt) { |
4892 | return false; |
4893 | } |
4894 | |
4895 | OS << "[B" << I->second.first << "." << I->second.second << "]"; |
4896 | return true; |
4897 | } |
4898 | }; |
4899 | |
4900 | class CFGBlockTerminatorPrint |
4901 | : public StmtVisitor<CFGBlockTerminatorPrint,void> { |
4902 | raw_ostream &OS; |
4903 | StmtPrinterHelper* Helper; |
4904 | PrintingPolicy Policy; |
4905 | |
4906 | public: |
4907 | CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, |
4908 | const PrintingPolicy &Policy) |
4909 | : OS(os), Helper(helper), Policy(Policy) { |
4910 | this->Policy.IncludeNewlines = false; |
4911 | } |
4912 | |
4913 | void VisitIfStmt(IfStmt *I) { |
4914 | OS << "if "; |
4915 | if (Stmt *C = I->getCond()) |
4916 | C->printPretty(OS, Helper, Policy); |
4917 | } |
4918 | |
4919 | |
4920 | void VisitStmt(Stmt *Terminator) { |
4921 | Terminator->printPretty(OS, Helper, Policy); |
4922 | } |
4923 | |
4924 | void VisitDeclStmt(DeclStmt *DS) { |
4925 | VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); |
4926 | OS << "static init " << VD->getName(); |
4927 | } |
4928 | |
4929 | void VisitForStmt(ForStmt *F) { |
4930 | OS << "for (" ; |
4931 | if (F->getInit()) |
4932 | OS << "..."; |
4933 | OS << "; "; |
4934 | if (Stmt *C = F->getCond()) |
4935 | C->printPretty(OS, Helper, Policy); |
4936 | OS << "; "; |
4937 | if (F->getInc()) |
4938 | OS << "..."; |
4939 | OS << ")"; |
4940 | } |
4941 | |
4942 | void VisitWhileStmt(WhileStmt *W) { |
4943 | OS << "while " ; |
4944 | if (Stmt *C = W->getCond()) |
4945 | C->printPretty(OS, Helper, Policy); |
4946 | } |
4947 | |
4948 | void VisitDoStmt(DoStmt *D) { |
4949 | OS << "do ... while "; |
4950 | if (Stmt *C = D->getCond()) |
4951 | C->printPretty(OS, Helper, Policy); |
4952 | } |
4953 | |
4954 | void VisitSwitchStmt(SwitchStmt *Terminator) { |
4955 | OS << "switch "; |
4956 | Terminator->getCond()->printPretty(OS, Helper, Policy); |
4957 | } |
4958 | |
4959 | void VisitCXXTryStmt(CXXTryStmt *CS) { |
4960 | OS << "try ..."; |
4961 | } |
4962 | |
4963 | void VisitSEHTryStmt(SEHTryStmt *CS) { |
4964 | OS << "__try ..."; |
4965 | } |
4966 | |
4967 | void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { |
4968 | if (Stmt *Cond = C->getCond()) |
4969 | Cond->printPretty(OS, Helper, Policy); |
4970 | OS << " ? ... : ..."; |
4971 | } |
4972 | |
4973 | void VisitChooseExpr(ChooseExpr *C) { |
4974 | OS << "__builtin_choose_expr( "; |
4975 | if (Stmt *Cond = C->getCond()) |
4976 | Cond->printPretty(OS, Helper, Policy); |
4977 | OS << " )"; |
4978 | } |
4979 | |
4980 | void VisitIndirectGotoStmt(IndirectGotoStmt *I) { |
4981 | OS << "goto *"; |
4982 | if (Stmt *T = I->getTarget()) |
4983 | T->printPretty(OS, Helper, Policy); |
4984 | } |
4985 | |
4986 | void VisitBinaryOperator(BinaryOperator* B) { |
4987 | if (!B->isLogicalOp()) { |
4988 | VisitExpr(B); |
4989 | return; |
4990 | } |
4991 | |
4992 | if (B->getLHS()) |
4993 | B->getLHS()->printPretty(OS, Helper, Policy); |
4994 | |
4995 | switch (B->getOpcode()) { |
4996 | case BO_LOr: |
4997 | OS << " || ..."; |
4998 | return; |
4999 | case BO_LAnd: |
5000 | OS << " && ..."; |
5001 | return; |
5002 | default: |
5003 | llvm_unreachable("Invalid logical operator."); |
5004 | } |
5005 | } |
5006 | |
5007 | void VisitExpr(Expr *E) { |
5008 | E->printPretty(OS, Helper, Policy); |
5009 | } |
5010 | |
5011 | public: |
5012 | void print(CFGTerminator T) { |
5013 | if (T.isTemporaryDtorsBranch()) |
5014 | OS << "(Temp Dtor) "; |
5015 | Visit(T.getStmt()); |
5016 | } |
5017 | }; |
5018 | |
5019 | } |
5020 | |
5021 | static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, |
5022 | const CXXCtorInitializer *I) { |
5023 | if (I->isBaseInitializer()) |
5024 | OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); |
5025 | else if (I->isDelegatingInitializer()) |
5026 | OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName(); |
5027 | else |
5028 | OS << I->getAnyMember()->getName(); |
5029 | OS << "("; |
5030 | if (Expr *IE = I->getInit()) |
5031 | IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts())); |
5032 | OS << ")"; |
5033 | |
5034 | if (I->isBaseInitializer()) |
5035 | OS << " (Base initializer)"; |
5036 | else if (I->isDelegatingInitializer()) |
5037 | OS << " (Delegating initializer)"; |
5038 | else |
5039 | OS << " (Member initializer)"; |
5040 | } |
5041 | |
5042 | static void print_construction_context(raw_ostream &OS, |
5043 | StmtPrinterHelper &Helper, |
5044 | const ConstructionContext *CC) { |
5045 | SmallVector<const Stmt *, 3> Stmts; |
5046 | switch (CC->getKind()) { |
5047 | case ConstructionContext::SimpleConstructorInitializerKind: { |
5048 | OS << ", "; |
5049 | const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC); |
5050 | print_initializer(OS, Helper, SICC->getCXXCtorInitializer()); |
5051 | return; |
5052 | } |
5053 | case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: { |
5054 | OS << ", "; |
5055 | const auto *CICC = |
5056 | cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC); |
5057 | print_initializer(OS, Helper, CICC->getCXXCtorInitializer()); |
5058 | Stmts.push_back(CICC->getCXXBindTemporaryExpr()); |
5059 | break; |
5060 | } |
5061 | case ConstructionContext::SimpleVariableKind: { |
5062 | const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC); |
5063 | Stmts.push_back(SDSCC->getDeclStmt()); |
5064 | break; |
5065 | } |
5066 | case ConstructionContext::CXX17ElidedCopyVariableKind: { |
5067 | const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC); |
5068 | Stmts.push_back(CDSCC->getDeclStmt()); |
5069 | Stmts.push_back(CDSCC->getCXXBindTemporaryExpr()); |
5070 | break; |
5071 | } |
5072 | case ConstructionContext::NewAllocatedObjectKind: { |
5073 | const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC); |
5074 | Stmts.push_back(NECC->getCXXNewExpr()); |
5075 | break; |
5076 | } |
5077 | case ConstructionContext::SimpleReturnedValueKind: { |
5078 | const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC); |
5079 | Stmts.push_back(RSCC->getReturnStmt()); |
5080 | break; |
5081 | } |
5082 | case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { |
5083 | const auto *RSCC = |
5084 | cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC); |
5085 | Stmts.push_back(RSCC->getReturnStmt()); |
5086 | Stmts.push_back(RSCC->getCXXBindTemporaryExpr()); |
5087 | break; |
5088 | } |
5089 | case ConstructionContext::SimpleTemporaryObjectKind: { |
5090 | const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC); |
5091 | Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); |
5092 | Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); |
5093 | break; |
5094 | } |
5095 | case ConstructionContext::ElidedTemporaryObjectKind: { |
5096 | const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC); |
5097 | Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); |
5098 | Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); |
5099 | Stmts.push_back(TOCC->getConstructorAfterElision()); |
5100 | break; |
5101 | } |
5102 | case ConstructionContext::ArgumentKind: { |
5103 | const auto *ACC = cast<ArgumentConstructionContext>(CC); |
5104 | if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) { |
5105 | OS << ", "; |
5106 | Helper.handledStmt(const_cast<Stmt *>(BTE), OS); |
5107 | } |
5108 | OS << ", "; |
5109 | Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS); |
5110 | OS << "+" << ACC->getIndex(); |
5111 | return; |
5112 | } |
5113 | } |
5114 | for (auto I: Stmts) |
5115 | if (I) { |
5116 | OS << ", "; |
5117 | Helper.handledStmt(const_cast<Stmt *>(I), OS); |
5118 | } |
5119 | } |
5120 | |
5121 | static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, |
5122 | const CFGElement &E) { |
5123 | if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) { |
5124 | const Stmt *S = CS->getStmt(); |
5125 | (0) . __assert_fail ("S != nullptr && \"Expecting non-null Stmt\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/CFG.cpp", 5125, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(S != nullptr && "Expecting non-null Stmt"); |
5126 | |
5127 | |
5128 | if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) { |
5129 | const CompoundStmt *Sub = SE->getSubStmt(); |
5130 | |
5131 | auto Children = Sub->children(); |
5132 | if (Children.begin() != Children.end()) { |
5133 | OS << "({ ... ; "; |
5134 | Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS); |
5135 | OS << " })\n"; |
5136 | return; |
5137 | } |
5138 | } |
5139 | |
5140 | if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { |
5141 | if (B->getOpcode() == BO_Comma) { |
5142 | OS << "... , "; |
5143 | Helper.handledStmt(B->getRHS(),OS); |
5144 | OS << '\n'; |
5145 | return; |
5146 | } |
5147 | } |
5148 | S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts())); |
5149 | |
5150 | if (auto VTC = E.getAs<CFGCXXRecordTypedCall>()) { |
5151 | if (isa<CXXOperatorCallExpr>(S)) |
5152 | OS << " (OperatorCall)"; |
5153 | OS << " (CXXRecordTypedCall"; |
5154 | print_construction_context(OS, Helper, VTC->getConstructionContext()); |
5155 | OS << ")"; |
5156 | } else if (isa<CXXOperatorCallExpr>(S)) { |
5157 | OS << " (OperatorCall)"; |
5158 | } else if (isa<CXXBindTemporaryExpr>(S)) { |
5159 | OS << " (BindTemporary)"; |
5160 | } else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { |
5161 | OS << " (CXXConstructExpr"; |
5162 | if (Optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) { |
5163 | print_construction_context(OS, Helper, CE->getConstructionContext()); |
5164 | } |
5165 | OS << ", " << CCE->getType().getAsString() << ")"; |
5166 | } else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { |
5167 | OS << " (" << CE->getStmtClassName() << ", " |
5168 | << CE->getCastKindName() |
5169 | << ", " << CE->getType().getAsString() |
5170 | << ")"; |
5171 | } |
5172 | |
5173 | |
5174 | if (isa<Expr>(S)) |
5175 | OS << '\n'; |
5176 | } else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) { |
5177 | print_initializer(OS, Helper, IE->getInitializer()); |
5178 | OS << '\n'; |
5179 | } else if (Optional<CFGAutomaticObjDtor> DE = |
5180 | E.getAs<CFGAutomaticObjDtor>()) { |
5181 | const VarDecl *VD = DE->getVarDecl(); |
5182 | Helper.handleDecl(VD, OS); |
5183 | |
5184 | ASTContext &ACtx = VD->getASTContext(); |
5185 | QualType T = VD->getType(); |
5186 | if (T->isReferenceType()) |
5187 | T = getReferenceInitTemporaryType(VD->getInit(), nullptr); |
5188 | if (const ArrayType *AT = ACtx.getAsArrayType(T)) |
5189 | T = ACtx.getBaseElementType(AT); |
5190 | |
5191 | OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; |
5192 | OS << " (Implicit destructor)\n"; |
5193 | } else if (Optional<CFGLifetimeEnds> DE = E.getAs<CFGLifetimeEnds>()) { |
5194 | const VarDecl *VD = DE->getVarDecl(); |
5195 | Helper.handleDecl(VD, OS); |
5196 | |
5197 | OS << " (Lifetime ends)\n"; |
5198 | } else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) { |
5199 | const Stmt *LoopStmt = LE->getLoopStmt(); |
5200 | OS << LoopStmt->getStmtClassName() << " (LoopExit)\n"; |
5201 | } else if (Optional<CFGScopeBegin> SB = E.getAs<CFGScopeBegin>()) { |
5202 | OS << "CFGScopeBegin("; |
5203 | if (const VarDecl *VD = SB->getVarDecl()) |
5204 | OS << VD->getQualifiedNameAsString(); |
5205 | OS << ")\n"; |
5206 | } else if (Optional<CFGScopeEnd> SE = E.getAs<CFGScopeEnd>()) { |
5207 | OS << "CFGScopeEnd("; |
5208 | if (const VarDecl *VD = SE->getVarDecl()) |
5209 | OS << VD->getQualifiedNameAsString(); |
5210 | OS << ")\n"; |
5211 | } else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) { |
5212 | OS << "CFGNewAllocator("; |
5213 | if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr()) |
5214 | AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts())); |
5215 | OS << ")\n"; |
5216 | } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) { |
5217 | const CXXRecordDecl *RD = DE->getCXXRecordDecl(); |
5218 | if (!RD) |
5219 | return; |
5220 | CXXDeleteExpr *DelExpr = |
5221 | const_cast<CXXDeleteExpr*>(DE->getDeleteExpr()); |
5222 | Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS); |
5223 | OS << "->~" << RD->getName().str() << "()"; |
5224 | OS << " (Implicit destructor)\n"; |
5225 | } else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) { |
5226 | const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); |
5227 | OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; |
5228 | OS << " (Base object destructor)\n"; |
5229 | } else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) { |
5230 | const FieldDecl *FD = ME->getFieldDecl(); |
5231 | const Type *T = FD->getType()->getBaseElementTypeUnsafe(); |
5232 | OS << "this->" << FD->getName(); |
5233 | OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; |
5234 | OS << " (Member object destructor)\n"; |
5235 | } else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) { |
5236 | const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); |
5237 | OS << "~"; |
5238 | BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts())); |
5239 | OS << "() (Temporary object destructor)\n"; |
5240 | } |
5241 | } |
5242 | |
5243 | static void print_block(raw_ostream &OS, const CFG* cfg, |
5244 | const CFGBlock &B, |
5245 | StmtPrinterHelper &Helper, bool print_edges, |
5246 | bool ShowColors) { |
5247 | Helper.setBlockID(B.getBlockID()); |
5248 | |
5249 | |
5250 | if (ShowColors) |
5251 | OS.changeColor(raw_ostream::YELLOW, true); |
5252 | |
5253 | OS << "\n [B" << B.getBlockID(); |
5254 | |
5255 | if (&B == &cfg->getEntry()) |
5256 | OS << " (ENTRY)]\n"; |
5257 | else if (&B == &cfg->getExit()) |
5258 | OS << " (EXIT)]\n"; |
5259 | else if (&B == cfg->getIndirectGotoBlock()) |
5260 | OS << " (INDIRECT GOTO DISPATCH)]\n"; |
5261 | else if (B.hasNoReturnElement()) |
5262 | OS << " (NORETURN)]\n"; |
5263 | else |
5264 | OS << "]\n"; |
5265 | |
5266 | if (ShowColors) |
5267 | OS.resetColor(); |
5268 | |
5269 | |
5270 | if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) { |
5271 | if (print_edges) |
5272 | OS << " "; |
5273 | |
5274 | if (LabelStmt *L = dyn_cast<LabelStmt>(Label)) |
5275 | OS << L->getName(); |
5276 | else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) { |
5277 | OS << "case "; |
5278 | if (C->getLHS()) |
5279 | C->getLHS()->printPretty(OS, &Helper, |
5280 | PrintingPolicy(Helper.getLangOpts())); |
5281 | if (C->getRHS()) { |
5282 | OS << " ... "; |
5283 | C->getRHS()->printPretty(OS, &Helper, |
5284 | PrintingPolicy(Helper.getLangOpts())); |
5285 | } |
5286 | } else if (isa<DefaultStmt>(Label)) |
5287 | OS << "default"; |
5288 | else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { |
5289 | OS << "catch ("; |
5290 | if (CS->getExceptionDecl()) |
5291 | CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper.getLangOpts()), |
5292 | 0); |
5293 | else |
5294 | OS << "..."; |
5295 | OS << ")"; |
5296 | } else if (SEHExceptStmt *ES = dyn_cast<SEHExceptStmt>(Label)) { |
5297 | OS << "__except ("; |
5298 | ES->getFilterExpr()->printPretty(OS, &Helper, |
5299 | PrintingPolicy(Helper.getLangOpts()), 0); |
5300 | OS << ")"; |
5301 | } else |
5302 | llvm_unreachable("Invalid label statement in CFGBlock."); |
5303 | |
5304 | OS << ":\n"; |
5305 | } |
5306 | |
5307 | |
5308 | unsigned j = 1; |
5309 | |
5310 | for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; |
5311 | I != E ; ++I, ++j ) { |
5312 | |
5313 | if (print_edges) |
5314 | OS << " "; |
5315 | |
5316 | OS << llvm::format("%3d", j) << ": "; |
5317 | |
5318 | Helper.setStmtID(j); |
5319 | |
5320 | print_elem(OS, Helper, *I); |
5321 | } |
5322 | |
5323 | |
5324 | if (B.getTerminator()) { |
5325 | if (ShowColors) |
5326 | OS.changeColor(raw_ostream::GREEN); |
5327 | |
5328 | OS << " T: "; |
5329 | |
5330 | Helper.setBlockID(-1); |
5331 | |
5332 | PrintingPolicy PP(Helper.getLangOpts()); |
5333 | CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP); |
5334 | TPrinter.print(B.getTerminator()); |
5335 | OS << '\n'; |
5336 | |
5337 | if (ShowColors) |
5338 | OS.resetColor(); |
5339 | } |
5340 | |
5341 | if (print_edges) { |
5342 | |
5343 | if (!B.pred_empty()) { |
5344 | const raw_ostream::Colors Color = raw_ostream::BLUE; |
5345 | if (ShowColors) |
5346 | OS.changeColor(Color); |
5347 | OS << " Preds " ; |
5348 | if (ShowColors) |
5349 | OS.resetColor(); |
5350 | OS << '(' << B.pred_size() << "):"; |
5351 | unsigned i = 0; |
5352 | |
5353 | if (ShowColors) |
5354 | OS.changeColor(Color); |
5355 | |
5356 | for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); |
5357 | I != E; ++I, ++i) { |
5358 | if (i % 10 == 8) |
5359 | OS << "\n "; |
5360 | |
5361 | CFGBlock *B = *I; |
5362 | bool Reachable = true; |
5363 | if (!B) { |
5364 | Reachable = false; |
5365 | B = I->getPossiblyUnreachableBlock(); |
5366 | } |
5367 | |
5368 | OS << " B" << B->getBlockID(); |
5369 | if (!Reachable) |
5370 | OS << "(Unreachable)"; |
5371 | } |
5372 | |
5373 | if (ShowColors) |
5374 | OS.resetColor(); |
5375 | |
5376 | OS << '\n'; |
5377 | } |
5378 | |
5379 | |
5380 | if (!B.succ_empty()) { |
5381 | const raw_ostream::Colors Color = raw_ostream::MAGENTA; |
5382 | if (ShowColors) |
5383 | OS.changeColor(Color); |
5384 | OS << " Succs "; |
5385 | if (ShowColors) |
5386 | OS.resetColor(); |
5387 | OS << '(' << B.succ_size() << "):"; |
5388 | unsigned i = 0; |
5389 | |
5390 | if (ShowColors) |
5391 | OS.changeColor(Color); |
5392 | |
5393 | for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); |
5394 | I != E; ++I, ++i) { |
5395 | if (i % 10 == 8) |
5396 | OS << "\n "; |
5397 | |
5398 | CFGBlock *B = *I; |
5399 | |
5400 | bool Reachable = true; |
5401 | if (!B) { |
5402 | Reachable = false; |
5403 | B = I->getPossiblyUnreachableBlock(); |
5404 | } |
5405 | |
5406 | if (B) { |
5407 | OS << " B" << B->getBlockID(); |
5408 | if (!Reachable) |
5409 | OS << "(Unreachable)"; |
5410 | } |
5411 | else { |
5412 | OS << " NULL"; |
5413 | } |
5414 | } |
5415 | |
5416 | if (ShowColors) |
5417 | OS.resetColor(); |
5418 | OS << '\n'; |
5419 | } |
5420 | } |
5421 | } |
5422 | |
5423 | |
5424 | void CFG::dump(const LangOptions &LO, bool ShowColors) const { |
5425 | print(llvm::errs(), LO, ShowColors); |
5426 | } |
5427 | |
5428 | |
5429 | void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { |
5430 | StmtPrinterHelper Helper(this, LO); |
5431 | |
5432 | |
5433 | print_block(OS, this, getEntry(), Helper, true, ShowColors); |
5434 | |
5435 | |
5436 | for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { |
5437 | |
5438 | if (&(**I) == &getEntry() || &(**I) == &getExit()) |
5439 | continue; |
5440 | |
5441 | print_block(OS, this, **I, Helper, true, ShowColors); |
5442 | } |
5443 | |
5444 | |
5445 | print_block(OS, this, getExit(), Helper, true, ShowColors); |
5446 | OS << '\n'; |
5447 | OS.flush(); |
5448 | } |
5449 | |
5450 | |
5451 | void CFGBlock::dump(const CFG* cfg, const LangOptions &LO, |
5452 | bool ShowColors) const { |
5453 | print(llvm::errs(), cfg, LO, ShowColors); |
5454 | } |
5455 | |
5456 | LLVM_DUMP_METHOD void CFGBlock::dump() const { |
5457 | dump(getParent(), LangOptions(), false); |
5458 | } |
5459 | |
5460 | |
5461 | |
5462 | void CFGBlock::print(raw_ostream &OS, const CFG* cfg, |
5463 | const LangOptions &LO, bool ShowColors) const { |
5464 | StmtPrinterHelper Helper(cfg, LO); |
5465 | print_block(OS, cfg, *this, Helper, true, ShowColors); |
5466 | OS << '\n'; |
5467 | } |
5468 | |
5469 | |
5470 | void CFGBlock::printTerminator(raw_ostream &OS, |
5471 | const LangOptions &LO) const { |
5472 | CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO)); |
5473 | TPrinter.print(getTerminator()); |
5474 | } |
5475 | |
5476 | Stmt *CFGBlock::getTerminatorCondition(bool StripParens) { |
5477 | Stmt *Terminator = this->Terminator; |
5478 | if (!Terminator) |
5479 | return nullptr; |
5480 | |
5481 | Expr *E = nullptr; |
5482 | |
5483 | switch (Terminator->getStmtClass()) { |
5484 | default: |
5485 | break; |
5486 | |
5487 | case Stmt::CXXForRangeStmtClass: |
5488 | E = cast<CXXForRangeStmt>(Terminator)->getCond(); |
5489 | break; |
5490 | |
5491 | case Stmt::ForStmtClass: |
5492 | E = cast<ForStmt>(Terminator)->getCond(); |
5493 | break; |
5494 | |
5495 | case Stmt::WhileStmtClass: |
5496 | E = cast<WhileStmt>(Terminator)->getCond(); |
5497 | break; |
5498 | |
5499 | case Stmt::DoStmtClass: |
5500 | E = cast<DoStmt>(Terminator)->getCond(); |
5501 | break; |
5502 | |
5503 | case Stmt::IfStmtClass: |
5504 | E = cast<IfStmt>(Terminator)->getCond(); |
5505 | break; |
5506 | |
5507 | case Stmt::ChooseExprClass: |
5508 | E = cast<ChooseExpr>(Terminator)->getCond(); |
5509 | break; |
5510 | |
5511 | case Stmt::IndirectGotoStmtClass: |
5512 | E = cast<IndirectGotoStmt>(Terminator)->getTarget(); |
5513 | break; |
5514 | |
5515 | case Stmt::SwitchStmtClass: |
5516 | E = cast<SwitchStmt>(Terminator)->getCond(); |
5517 | break; |
5518 | |
5519 | case Stmt::BinaryConditionalOperatorClass: |
5520 | E = cast<BinaryConditionalOperator>(Terminator)->getCond(); |
5521 | break; |
5522 | |
5523 | case Stmt::ConditionalOperatorClass: |
5524 | E = cast<ConditionalOperator>(Terminator)->getCond(); |
5525 | break; |
5526 | |
5527 | case Stmt::BinaryOperatorClass: |
5528 | E = cast<BinaryOperator>(Terminator)->getLHS(); |
5529 | break; |
5530 | |
5531 | case Stmt::ObjCForCollectionStmtClass: |
5532 | return Terminator; |
5533 | } |
5534 | |
5535 | if (!StripParens) |
5536 | return E; |
5537 | |
5538 | return E ? E->IgnoreParens() : nullptr; |
5539 | } |
5540 | |
5541 | |
5542 | |
5543 | |
5544 | |
5545 | #ifndef NDEBUG |
5546 | static StmtPrinterHelper* GraphHelper; |
5547 | #endif |
5548 | |
5549 | void CFG::viewCFG(const LangOptions &LO) const { |
5550 | #ifndef NDEBUG |
5551 | StmtPrinterHelper H(this, LO); |
5552 | GraphHelper = &H; |
5553 | llvm::ViewGraph(this,"CFG"); |
5554 | GraphHelper = nullptr; |
5555 | #endif |
5556 | } |
5557 | |
5558 | namespace llvm { |
5559 | |
5560 | template<> |
5561 | struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { |
5562 | DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} |
5563 | |
5564 | static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { |
5565 | #ifndef NDEBUG |
5566 | std::string OutSStr; |
5567 | llvm::raw_string_ostream Out(OutSStr); |
5568 | print_block(Out,Graph, *Node, *GraphHelper, false, false); |
5569 | std::string& OutStr = Out.str(); |
5570 | |
5571 | if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); |
5572 | |
5573 | |
5574 | for (unsigned i = 0; i != OutStr.length(); ++i) |
5575 | if (OutStr[i] == '\n') { |
5576 | OutStr[i] = '\\'; |
5577 | OutStr.insert(OutStr.begin()+i+1, 'l'); |
5578 | } |
5579 | |
5580 | return OutStr; |
5581 | #else |
5582 | return {}; |
5583 | #endif |
5584 | } |
5585 | }; |
5586 | |
5587 | } |
5588 | |