clang: lib/Analysis/CFG.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
39#include "llvm/ADT/APFloat.h"
40#include "llvm/ADT/APInt.h"
41#include "llvm/ADT/APSInt.h"
42#include "llvm/ADT/ArrayRef.h"
43#include "llvm/ADT/DenseMap.h"
44#include "llvm/ADT/STLExtras.h"
45#include "llvm/ADT/SetVector.h"
46#include "llvm/ADT/SmallPtrSet.h"
47#include "llvm/ADT/SmallVector.h"
48#include "llvm/Support/Allocator.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
57#include
58#include
59#include
60#include
61#include
62#include
63
64using namespace clang;
65
67 if (VarDecl *VD = dyn_cast(D))
68 if (Expr *Ex = VD->getInit())
69 return Ex->getSourceRange().getEnd();
71}
72
73
74
75
76
78
80
81
82
83 if (const auto *CE = dyn_cast(E)) {
84 if (CE->getCastKind() != CK_IntegralCast &&
85 CE->getCastKind() != CK_IntegralToFloating)
86 return false;
87 E = CE->getSubExpr();
88 }
89
90
91 if (const auto *UO = dyn_cast(E)) {
92 if (UO->getOpcode() != UO_Minus)
93 return false;
94 E = UO->getSubExpr();
95 }
97}
98
99
100
101
105 return E;
108 return nullptr;
109}
110
111
112
113
114
115
116static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
119
122
123 if (Constant == nullptr) {
124
125 if (Op == BO_GT)
126 Op = BO_LT;
127 else if (Op == BO_GE)
128 Op = BO_LE;
129 else if (Op == BO_LT)
130 Op = BO_GT;
131 else if (Op == BO_LE)
132 Op = BO_GE;
133
134 MaybeDecl = B->getRHS();
136 }
137
138 return std::make_tuple(MaybeDecl, Op, Constant);
139}
140
141
142
143
144
145
146
148
149
151 return false;
152
153
155 return true;
156
157
158
162
164 const DeclContext *DC1 = Decl1->getDeclContext();
165 const DeclContext *DC2 = Decl2->getDeclContext();
166
168 return DC1 == DC2;
169}
170
171namespace {
172
173class CFGBuilder;
174
175
176
177
178
179
180
181
182
183
184
185
186
187class AddStmtChoice {
188public:
189 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
190
191 AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
192
193 bool alwaysAdd(CFGBuilder &builder,
194 const Stmt *stmt) const;
195
196
197
198 AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {
199 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
200 }
201
202private:
203 Kind kind;
204};
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227class LocalScope {
228public:
229 using AutomaticVarsTy = BumpVector<VarDecl *>;
230
231
232
233 class const_iterator {
234 const LocalScope* Scope = nullptr;
235
236
237
238 unsigned VarIter = 0;
239
240 public:
241
242
243
244 const_iterator() = default;
245
246
247
248 const_iterator(const LocalScope& S, unsigned I)
249 : Scope(&S), VarIter(I) {
250
251
252 if (VarIter == 0 && Scope)
253 *this = Scope->Prev;
254 }
255
256 VarDecl *const* operator->() const {
257 assert(Scope && "Dereferencing invalid iterator is not allowed");
258 assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
259 return &Scope->Vars[VarIter - 1];
260 }
261
262 const VarDecl *getFirstVarInScope() const {
263 assert(Scope && "Dereferencing invalid iterator is not allowed");
264 assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
265 return Scope->Vars[0];
266 }
267
269 return *this->operator->();
270 }
271
272 const_iterator &operator++() {
273 if (!Scope)
274 return *this;
275
276 assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
277 --VarIter;
278 if (VarIter == 0)
279 *this = Scope->Prev;
280 return *this;
281 }
282 const_iterator operator++(int) {
283 const_iterator P = *this;
284 ++*this;
285 return P;
286 }
287
288 bool operator==(const const_iterator &rhs) const {
289 return Scope == rhs.Scope && VarIter == rhs.VarIter;
290 }
291 bool operator!=(const const_iterator &rhs) const {
292 return !(*this == rhs);
293 }
294
295 explicit operator bool() const {
296 return *this != const_iterator();
297 }
298
299 int distance(const_iterator L);
300 const_iterator shared_parent(const_iterator L);
301 bool pointsToFirstDeclaredVar() { return VarIter == 1; }
302 bool inSameLocalScope(const_iterator rhs) { return Scope == rhs.Scope; }
303 };
304
305private:
306 BumpVectorContext ctx;
307
308
309 AutomaticVarsTy Vars;
310
311
312
313 const_iterator Prev;
314
315public:
316
317 LocalScope(BumpVectorContext ctx, const_iterator P)
318 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
319
320
321 const_iterator begin() const { return const_iterator(*this, Vars.size()); }
322
323 void addVar(VarDecl *VD) {
324 Vars.push_back(VD, ctx);
325 }
326};
327
328}
329
330
331
332
333int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
334 int D = 0;
335 const_iterator F = *this;
336 while (F.Scope != L.Scope) {
337 assert(F != const_iterator() &&
338 "L iterator is not reachable from F iterator.");
339 D += F.VarIter;
340 F = F.Scope->Prev;
341 }
342 D += F.VarIter - L.VarIter;
343 return D;
344}
345
346
347
348
349
350LocalScope::const_iterator
351LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
352
353
354 if ((*this == const_iterator()) || (L == const_iterator())) {
355 return const_iterator();
356 }
357
358 const_iterator F = *this;
359 if (F.inSameLocalScope(L)) {
360
361 F.VarIter = std::min(F.VarIter, L.VarIter);
362 return F;
363 }
364
365 llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;
366 while (true) {
367 ScopesOfL.try_emplace(L.Scope, L.VarIter);
368 if (L == const_iterator())
369 break;
370 L = L.Scope->Prev;
371 }
372
373 while (true) {
374 if (auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {
375
376 F.VarIter = std::min(F.VarIter, LIt->getSecond());
377 return F;
378 }
379 assert(F != const_iterator() &&
380 "L iterator is not reachable from F iterator.");
381 F = F.Scope->Prev;
382 }
383}
384
385namespace {
386
387
388
389
390struct BlockScopePosPair {
391 CFGBlock *block = nullptr;
392 LocalScope::const_iterator scopePosition;
393
394 BlockScopePosPair() = default;
395 BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
396 : block(b), scopePosition(scopePos) {}
397};
398
399
400
401
402
403class TryResult {
404 int X = -1;
405
406public:
407 TryResult() = default;
408 TryResult(bool b) : X(b ? 1 : 0) {}
409
410 bool isTrue() const { return X == 1; }
411 bool isFalse() const { return X == 0; }
412 bool isKnown() const { return X >= 0; }
413
414 void negate() {
415 assert(isKnown());
416 X ^= 0x1;
417 }
418};
419
420}
421
423 if (!R1.isKnown() || !R2.isKnown())
424 return TryResult();
425 return TryResult(R1.isTrue() && R2.isTrue());
426}
427
428namespace {
429
430class reverse_children {
431 llvm::SmallVector<Stmt *, 12> childrenBuf;
432 ArrayRef<Stmt *> children;
433
434public:
435 reverse_children(Stmt *S, ASTContext &Ctx);
436
437 using iterator = ArrayRef<Stmt *>::reverse_iterator;
438
439 iterator begin() const { return children.rbegin(); }
440 iterator end() const { return children.rend(); }
441};
442
443}
444
445reverse_children::reverse_children(Stmt *S, ASTContext &Ctx) {
446 if (CallExpr *CE = dyn_cast(S)) {
447 children = CE->getRawSubExprs();
448 return;
449 }
450
452
453 case Stmt::InitListExprClass: {
455 children = llvm::ArrayRef(reinterpret_cast<Stmt **>(IE->getInits()),
457 return;
458 }
459
460 case Stmt::AttributedStmtClass: {
461
462
463
464
466 for (const auto *Attr : AS->getAttrs()) {
467 if (const auto *AssumeAttr = dyn_cast(Attr)) {
468 Expr *AssumeExpr = AssumeAttr->getAssumption();
470 childrenBuf.push_back(AssumeExpr);
471 }
472 }
473 }
474
475
476
477 llvm::append_range(childrenBuf, AS->children());
478 children = childrenBuf;
479 return;
480 }
481 default:
482 break;
483 }
484
485
486 llvm::append_range(childrenBuf, S->children());
487
488
489 children = childrenBuf;
490}
491
492namespace {
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507class CFGBuilder {
508 using JumpTarget = BlockScopePosPair;
509 using JumpSource = BlockScopePosPair;
510
511 ASTContext *Context;
512 std::unique_ptr cfg;
513
514
515 CFGBlock *Block = nullptr;
516
517
518 CFGBlock *Succ = nullptr;
519
520 JumpTarget ContinueJumpTarget;
521 JumpTarget BreakJumpTarget;
522 JumpTarget SEHLeaveJumpTarget;
523 CFGBlock *SwitchTerminatedBlock = nullptr;
524 CFGBlock *DefaultCaseBlock = nullptr;
525
526
527
528
529
530 CFGBlock *TryTerminatedBlock = nullptr;
531
532
533 LocalScope::const_iterator ScopePos;
534
535
536 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
537 LabelMapTy LabelMap;
538
539
540
541 using BackpatchBlocksTy = std::vector;
542 BackpatchBlocksTy BackpatchBlocks;
543
544
545 using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
546 LabelSetTy AddressTakenLabels;
547
548
549
550
551 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
552 ConstructionContextMap;
553
554 bool badCFG = false;
555 const CFG::BuildOptions &BuildOpts;
556
557
558 bool switchExclusivelyCovered = false;
559 Expr::EvalResult *switchCond = nullptr;
560
561 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;
562 const Stmt *lastLookup = nullptr;
563
564
565
566 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
567 CachedBoolEvalsTy CachedBoolEvals;
568
569public:
570 explicit CFGBuilder(ASTContext *astContext,
571 const CFG::BuildOptions &buildOpts)
572 : Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}
573
574
575 std::unique_ptr buildCFG(const Decl *D, Stmt *Statement);
576
577 bool alwaysAdd(const Stmt *stmt);
578
579private:
580
581 CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
582 CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
583 CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
584 CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
585 CFGBlock *VisitBreakStmt(BreakStmt *B);
586 CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
587 CFGBlock *VisitCaseStmt(CaseStmt *C);
588 CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
589 CFGBlock *VisitCompoundStmt(CompoundStmt *C, bool ExternallyDestructed);
590 CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,
591 AddStmtChoice asc);
592 CFGBlock *VisitContinueStmt(ContinueStmt *C);
593 CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
594 AddStmtChoice asc);
595 CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
596 CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
597 CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
598 CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
599 CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
600 CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
601 AddStmtChoice asc);
602 CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
603 AddStmtChoice asc);
604 CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
605 CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
606 CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);
607 CFGBlock *VisitDeclStmt(DeclStmt *DS);
608 CFGBlock *VisitDeclSubExpr(DeclStmt *DS);
609 CFGBlock *VisitDefaultStmt(DefaultStmt *D);
610 CFGBlock *VisitDoStmt(DoStmt *D);
611 CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,
612 AddStmtChoice asc, bool ExternallyDestructed);
613 CFGBlock *VisitForStmt(ForStmt *F);
614 CFGBlock *VisitGotoStmt(GotoStmt *G);
615 CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);
616 CFGBlock *VisitIfStmt(IfStmt *I);
617 CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
618 CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);
619 CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
620 CFGBlock *VisitLabelStmt(LabelStmt *L);
621 CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
622 CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);
623 CFGBlock *VisitLogicalOperator(BinaryOperator *B);
624 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
625 Stmt *Term,
626 CFGBlock *TrueBlock,
627 CFGBlock *FalseBlock);
628 CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
629 AddStmtChoice asc);
630 CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
631 CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
632 CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
633 CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
634 CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
635 CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
636 CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
637 CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
638 CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
639 CFGBlock *VisitReturnStmt(Stmt *S);
640 CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,
641 AddStmtChoice asc);
642 CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
643 CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
644 CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
645 CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);
646 CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
647 CFGBlock *VisitSwitchStmt(SwitchStmt *S);
648 CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
649 AddStmtChoice asc);
650 CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
651 CFGBlock *VisitWhileStmt(WhileStmt *W);
652 CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);
653
654 CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
655 bool ExternallyDestructed = false);
656 CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
657 CFGBlock *VisitChildren(Stmt *S);
658 CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
659 CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,
660 AddStmtChoice asc);
661
662 void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,
663 const Stmt *S) {
664 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
665 appendScopeBegin(B, VD, S);
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696 struct TempDtorContext {
697 TempDtorContext() = default;
698 TempDtorContext(TryResult KnownExecuted)
699 : IsConditional(true), KnownExecuted(KnownExecuted) {}
700
701
702
703
704
705
706
707 bool needsTempDtorBranch() const {
708 return IsConditional && !TerminatorExpr;
709 }
710
711
712
713 void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {
714 Succ = S;
715 TerminatorExpr = E;
716 }
717
718 const bool IsConditional = false;
719 const TryResult KnownExecuted = true;
720 CFGBlock *Succ = nullptr;
721 CXXBindTemporaryExpr *TerminatorExpr = nullptr;
722 };
723
724
725
726 CFGBlock *VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
727 TempDtorContext &Context);
728 CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
729 TempDtorContext &Context);
730 CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E,
731 bool ExternallyDestructed,
732 TempDtorContext &Context);
733 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
734 CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context);
735 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
736 AbstractConditionalOperator *E, bool ExternallyDestructed,
737 TempDtorContext &Context);
738 void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
739 CFGBlock *FalseSucc = nullptr);
740
741
742 CFGBlock *NYS() {
743 badCFG = true;
745 }
746
747
748
749 void consumeConstructionContext(const ConstructionContextLayer *Layer,
750 Expr *E);
751
752
753
754
755
756
757 void findConstructionContexts(const ConstructionContextLayer *Layer,
758 Stmt *Child);
759
760
761
762
763 template <typename CallLikeExpr,
764 typename = std::enable_if_t<
765 std::is_base_of_v<CallExpr, CallLikeExpr> ||
766 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
767 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
768 void findConstructionContextsForArguments(CallLikeExpr *E) {
769 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
770 Expr *Arg = E->getArg(i);
772 findConstructionContexts(
774 ConstructionContextItem(E, i)),
775 Arg);
776 }
777 }
778
779
780
781
782 void cleanupConstructionContext(Expr *E);
783
784 void autoCreateBlock() { if () Block = createBlock(); }
785
786 CFGBlock *createBlock(bool add_successor = true);
787 CFGBlock *createNoReturnBlock();
788
789 CFGBlock *addStmt(Stmt *S) {
790 return Visit(S, AddStmtChoice::AlwaysAdd);
791 }
792
793 CFGBlock *addInitializer(CXXCtorInitializer *I);
794 void addLoopExit(const Stmt *LoopStmt);
795 void addAutomaticObjHandling(LocalScope::const_iterator B,
796 LocalScope::const_iterator E, Stmt *S);
797 void addAutomaticObjDestruction(LocalScope::const_iterator B,
798 LocalScope::const_iterator E, Stmt *S);
799 void addScopeExitHandling(LocalScope::const_iterator B,
800 LocalScope::const_iterator E, Stmt *S);
801 void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
802 void addScopeChangesHandling(LocalScope::const_iterator SrcPos,
803 LocalScope::const_iterator DstPos,
804 Stmt *S);
805 CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,
806 CFGBlock *SrcBlk,
807 LocalScope::const_iterator DstPost,
808 CFGBlock *DstBlk);
809
810
811 LocalScope* createOrReuseLocalScope(LocalScope* Scope);
812
813 void addLocalScopeForStmt(Stmt *S);
814 LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
815 LocalScope* Scope = nullptr);
816 LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);
817
818 void addLocalScopeAndDtors(Stmt *S);
819
820 const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {
822 return nullptr;
823
824 const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);
825 if (!Layer)
826 return nullptr;
827
828 cleanupConstructionContext(E);
830 Layer);
831 }
832
833
834
835 void appendStmt(CFGBlock *B, const Stmt *S) {
836 if (alwaysAdd(S) && cachedEntry)
837 cachedEntry->second = B;
838
839
841 B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
842 }
843
844 void appendConstructor(CXXConstructExpr *CE) {
847 Block = createNoReturnBlock();
848 else
849 autoCreateBlock();
850
851 if (const ConstructionContext *CC =
852 retrieveAndCleanupConstructionContext(CE)) {
853 Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());
854 return;
855 }
856
857
858 Block->appendStmt(CE, cfg->getBumpVectorContext());
859 }
860
861 void appendCall(CFGBlock *B, CallExpr *CE) {
862 if (alwaysAdd(CE) && cachedEntry)
863 cachedEntry->second = B;
864
865 if (const ConstructionContext *CC =
866 retrieveAndCleanupConstructionContext(CE)) {
868 return;
869 }
870
871
872 B->appendStmt(CE, cfg->getBumpVectorContext());
873 }
874
875 void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
877 }
878
879 void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
881 }
882
883 void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
885 }
886
887 void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
889 }
890
891 void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {
892 if (alwaysAdd(ME) && cachedEntry)
893 cachedEntry->second = B;
894
895 if (const ConstructionContext *CC =
896 retrieveAndCleanupConstructionContext(ME)) {
898 return;
899 }
900
901 B->appendStmt(ME, cfg->getBumpVectorContext());
902 }
903
904 void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
906 }
907
908 void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
910 }
911
912 void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {
914 }
915
916 void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
918 }
919
920 void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) {
921 B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());
922 }
923
924 void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
926 }
927
928 void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
929 B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
930 cfg->getBumpVectorContext());
931 }
932
933
934
935 void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
936 B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
937 cfg->getBumpVectorContext());
938 }
939
940 void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
943 }
944
945 void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
947 B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());
948 }
949
950
951
952
953 TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {
956
957 const IntegerLiteral *IntLiteral = dyn_cast(LHSExpr);
958 const Expr *BoolExpr = RHSExpr;
959 bool IntFirst = true;
960 if (!IntLiteral) {
961 IntLiteral = dyn_cast(RHSExpr);
962 BoolExpr = LHSExpr;
963 IntFirst = false;
964 }
965
967 return TryResult();
968
969 llvm::APInt IntValue = IntLiteral->getValue();
970 if ((IntValue == 1) || (IntValue == 0))
971 return TryResult();
972
974 !IntValue.isNegative();
975
977 if (Bok == BO_GT || Bok == BO_GE) {
978
979
980 return TryResult(IntFirst == IntLarger);
981 } else {
982
983
984 return TryResult(IntFirst != IntLarger);
985 }
986 }
987
988
989
990
991
992 TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {
995
996 std::optionalllvm::APInt IntLiteral1 =
997 getIntegerLiteralSubexpressionValue(LHSExpr);
998 const Expr *BoolExpr = RHSExpr;
999
1000 if (!IntLiteral1) {
1001 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
1002 BoolExpr = LHSExpr;
1003 }
1004
1005 if (!IntLiteral1)
1006 return TryResult();
1007
1008 const BinaryOperator *BitOp = dyn_cast(BoolExpr);
1009 if (BitOp && (BitOp->getOpcode() == BO_And ||
1013
1014 std::optionalllvm::APInt IntLiteral2 =
1015 getIntegerLiteralSubexpressionValue(LHSExpr2);
1016
1017 if (!IntLiteral2)
1018 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
1019
1020 if (!IntLiteral2)
1021 return TryResult();
1022
1023 if ((BitOp->getOpcode() == BO_And &&
1024 (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
1026 (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1030 return TryResult(B->getOpcode() != BO_EQ);
1031 }
1033 if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1034 return TryResult();
1035 }
1036 return TryResult(B->getOpcode() != BO_EQ);
1037 }
1038
1039 return TryResult();
1040 }
1041
1042
1043
1044
1045
1046
1047
1048 std::optionalllvm::APInt
1049 getIntegerLiteralSubexpressionValue(const Expr *E) {
1050
1051
1052 if (const auto *UnOp = dyn_cast(E->IgnoreParens())) {
1053
1054
1055 const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();
1056
1057 if (const auto *IntLiteral = dyn_cast(SubExpr)) {
1058
1060
1061
1062 switch (UnOp->getOpcode()) {
1063 case UO_Plus:
1065 case UO_Minus:
1067 case UO_Not:
1068 return ~Value;
1069 case UO_LNot:
1071 default:
1072 assert(false && "Unexpected unary operator!");
1073 return std::nullopt;
1074 }
1075 }
1076 } else if (const auto *IntLiteral =
1077 dyn_cast(E->IgnoreParens()))
1078 return IntLiteral->getValue();
1079
1080 return std::nullopt;
1081 }
1082
1083 template
1084 TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,
1085 const APFloatOrInt &Value1,
1086 const APFloatOrInt &Value2) {
1087 switch (Relation) {
1088 default:
1089 return TryResult();
1090 case BO_EQ:
1091 return TryResult(Value1 == Value2);
1092 case BO_NE:
1093 return TryResult(Value1 != Value2);
1094 case BO_LT:
1095 return TryResult(Value1 < Value2);
1096 case BO_LE:
1097 return TryResult(Value1 <= Value2);
1098 case BO_GT:
1099 return TryResult(Value1 > Value2);
1100 case BO_GE:
1101 return TryResult(Value1 >= Value2);
1102 }
1103 }
1104
1105
1106
1107
1108
1109
1110
1111
1112 TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {
1116
1117 auto CheckLogicalOpWithNegatedVariable = [this, B](const Expr *E1,
1118 const Expr *E2) {
1119 if (const auto *Negate = dyn_cast(E1)) {
1120 if (Negate->getOpcode() == UO_LNot &&
1122 bool AlwaysTrue = B->getOpcode() == BO_LOr;
1125 return TryResult(AlwaysTrue);
1126 }
1127 }
1128 return TryResult();
1129 };
1130
1131 TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);
1132 if (Result.isKnown())
1134 Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);
1135 if (Result.isKnown())
1137
1138 const auto *LHS = dyn_cast(LHSExpr);
1139 const auto *RHS = dyn_cast(RHSExpr);
1140 if (!LHS || !RHS)
1141 return {};
1142
1143 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1144 return {};
1145
1146 const Expr *DeclExpr1;
1147 const Expr *NumExpr1;
1150
1151 if (!DeclExpr1 || !NumExpr1)
1152 return {};
1153
1154 const Expr *DeclExpr2;
1155 const Expr *NumExpr2;
1158
1159 if (!DeclExpr2 || !NumExpr2)
1160 return {};
1161
1162
1164 return {};
1165
1166
1167
1169 return {};
1170
1171
1172 Expr::EvalResult L1Result, L2Result;
1175 return {};
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187 auto AnalyzeConditions = [&](const auto &Values,
1190 bool AlwaysTrue = true, AlwaysFalse = true;
1191
1192
1193 bool LHSAlwaysTrue = true, LHSAlwaysFalse = true;
1194 bool RHSAlwaysTrue = true, RHSAlwaysFalse = true;
1195
1196 for (const auto &Value : Values) {
1197 TryResult Res1 =
1198 analyzeLogicOperatorCondition(*BO1, Value, Values[1] );
1199 TryResult Res2 =
1200 analyzeLogicOperatorCondition(*BO2, Value, Values[3] );
1201
1202 if (!Res1.isKnown() || !Res2.isKnown())
1203 return {};
1204
1205 const bool IsAnd = B->getOpcode() == BO_LAnd;
1206 const bool Combine = IsAnd ? (Res1.isTrue() && Res2.isTrue())
1207 : (Res1.isTrue() || Res2.isTrue());
1208
1209 AlwaysTrue &= Combine;
1210 AlwaysFalse &= !Combine;
1211
1212 LHSAlwaysTrue &= Res1.isTrue();
1213 LHSAlwaysFalse &= Res1.isFalse();
1214 RHSAlwaysTrue &= Res2.isTrue();
1215 RHSAlwaysFalse &= Res2.isFalse();
1216 }
1217
1218 if (AlwaysTrue || AlwaysFalse) {
1219 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1220 !RHSAlwaysFalse && BuildOpts.Observer) {
1222 }
1223 return TryResult(AlwaysTrue);
1224 }
1225 return {};
1226 };
1227
1228
1231 llvm::APSInt L1 = L1Result.Val.getInt();
1232 llvm::APSInt L2 = L2Result.Val.getInt();
1233
1234
1235 if (L1.isSigned() != L2.isSigned() ||
1236 L1.getBitWidth() != L2.getBitWidth())
1237 return {};
1238
1239
1240
1241 const llvm::APSInt Values[] = {
1242
1243 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1244
1245 L1,
1246
1247 ((L1 < L2) ? L1 : L2) +
1248 llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1), L1.isUnsigned()),
1249
1250 L2,
1251
1252 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1253 };
1254
1255 return AnalyzeConditions(Values, &BO1, &BO2);
1256 }
1257
1258
1261 llvm::APFloat L1 = L1Result.Val.getFloat();
1262 llvm::APFloat L2 = L2Result.Val.getFloat();
1263
1264
1265
1266
1267
1271
1272 if (Order > 0) {
1273
1274 if (llvm::APFloat::opOK !=
1275 L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1276 &Ignored))
1277 return {};
1278 } else if (Order < 0)
1279
1280 if (llvm::APFloat::opOK !=
1281 L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1282 &Ignored))
1283 return {};
1284
1285 llvm::APFloat MidValue = L1;
1286 MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven);
1287 MidValue.divide(llvm::APFloat(MidValue.getSemantics(), "2.0"),
1288 llvm::APFloat::rmNearestTiesToEven);
1289
1290 const llvm::APFloat Values[] = {
1291 llvm::APFloat::getSmallest(L1.getSemantics(), true), L1, MidValue, L2,
1292 llvm::APFloat::getLargest(L2.getSemantics(), false),
1293 };
1294
1295 return AnalyzeConditions(Values, &BO1, &BO2);
1296 }
1297
1298 return {};
1299 }
1300
1301
1302 TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) {
1303 const Expr *LHSConstant =
1305 const Expr *RHSConstant =
1307
1308 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1309 return {};
1310
1311 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1312
1313 Expr::EvalResult Result;
1315 return {};
1316
1317 if (Result.Val.getInt() == 0)
1318 return {};
1319
1322
1323 return TryResult(true);
1324 }
1325
1326
1327 bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
1329 return false;
1333 }
1334
1335
1336
1337 TryResult tryEvaluateBool(Expr *S) {
1340 return {};
1341
1342 if (BinaryOperator *Bop = dyn_cast(S)) {
1343 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1344
1345 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1346 if (I != CachedBoolEvals.end())
1347 return I->second;
1348
1349
1350 TryResult Result = evaluateAsBooleanConditionNoCache(S);
1351 CachedBoolEvals[S] = Result;
1353 }
1354 else {
1355 switch (Bop->getOpcode()) {
1356 default: break;
1357
1358
1359 case BO_Mul:
1360 case BO_And: {
1361
1362
1363 Expr::EvalResult LHSResult;
1364 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1365 llvm::APSInt IntVal = LHSResult.Val.getInt();
1366 if (!IntVal.getBoolValue()) {
1367 return TryResult(false);
1368 }
1369 }
1370 Expr::EvalResult RHSResult;
1371 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1372 llvm::APSInt IntVal = RHSResult.Val.getInt();
1373 if (!IntVal.getBoolValue()) {
1374 return TryResult(false);
1375 }
1376 }
1377 }
1378 break;
1379 }
1380 }
1381 }
1382
1383 return evaluateAsBooleanConditionNoCache(S);
1384 }
1385
1386
1387 TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
1388 if (BinaryOperator *Bop = dyn_cast(E)) {
1389 if (Bop->isLogicalOp()) {
1390 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1391 if (LHS.isKnown()) {
1392
1393
1394 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1395 return LHS.isTrue();
1396
1397 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1398 if (RHS.isKnown()) {
1399 if (Bop->getOpcode() == BO_LOr)
1400 return LHS.isTrue() || RHS.isTrue();
1401 else
1402 return LHS.isTrue() && RHS.isTrue();
1403 }
1404 } else {
1405 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1406 if (RHS.isKnown()) {
1407
1408
1409 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1410 return RHS.isTrue();
1411 } else {
1412 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1413 if (BopRes.isKnown())
1414 return BopRes.isTrue();
1415 }
1416 }
1417
1418 return {};
1419 } else if (Bop->isEqualityOp()) {
1420 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1421 if (BopRes.isKnown())
1422 return BopRes.isTrue();
1423 } else if (Bop->isRelationalOp()) {
1424 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1425 if (BopRes.isKnown())
1426 return BopRes.isTrue();
1427 } else if (Bop->getOpcode() == BO_Or) {
1428 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1429 if (BopRes.isKnown())
1430 return BopRes.isTrue();
1431 }
1432 }
1433
1437
1438 return {};
1439 }
1440
1441 bool hasTrivialDestructor(const VarDecl *VD) const;
1442 bool needsAutomaticDestruction(const VarDecl *VD) const;
1443};
1444
1445}
1446
1447Expr *
1449 if (!AILE)
1450 return nullptr;
1451
1453 while (const auto *E = dyn_cast(AILEInit))
1454 AILEInit = E->getSubExpr();
1455
1456 return AILEInit;
1457}
1458
1459inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1461 return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
1462}
1463
1464bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
1466
1468 return shouldAdd;
1469
1470 if (lastLookup == stmt) {
1471 if (cachedEntry) {
1472 assert(cachedEntry->first == stmt);
1473 return true;
1474 }
1475 return shouldAdd;
1476 }
1477
1478 lastLookup = stmt;
1479
1480
1482
1483 if (!fb) {
1484
1485 assert(!cachedEntry);
1486 return shouldAdd;
1487 }
1488
1489 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1490 if (itr == fb->end()) {
1491 cachedEntry = nullptr;
1492 return shouldAdd;
1493 }
1494
1495 cachedEntry = &*itr;
1496 return true;
1497}
1498
1499
1500
1502 while (const ArrayType *vt = dyn_cast(t)) {
1503 if (const VariableArrayType *vat = dyn_cast(vt))
1504 if (vat->getSizeExpr())
1505 return vat;
1506
1507 t = vt->getElementType().getTypePtr();
1508 }
1509
1510 return nullptr;
1511}
1512
1513void CFGBuilder::consumeConstructionContext(
1514 const ConstructionContextLayer *Layer, Expr *E) {
1517 if (const ConstructionContextLayer *PreviouslyStoredLayer =
1518 ConstructionContextMap.lookup(E)) {
1519 (void)PreviouslyStoredLayer;
1520
1521
1522 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1523 "Already within a different construction context!");
1524 } else {
1525 ConstructionContextMap[E] = Layer;
1526 }
1527}
1528
1529void CFGBuilder::findConstructionContexts(
1530 const ConstructionContextLayer *Layer, Stmt *Child) {
1532 return;
1533
1534 if (!Child)
1535 return;
1536
1537 auto withExtraLayer = [this, Layer](const ConstructionContextItem &Item) {
1539 Layer);
1540 };
1541
1542 switch(Child->getStmtClass()) {
1543 case Stmt::CXXConstructExprClass:
1544 case Stmt::CXXTemporaryObjectExprClass: {
1545
1548 findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
1549 }
1550
1551 consumeConstructionContext(Layer, CE);
1552 break;
1553 }
1554
1555
1556
1557 case Stmt::CallExprClass:
1558 case Stmt::CXXMemberCallExprClass:
1559 case Stmt::CXXOperatorCallExprClass:
1560 case Stmt::UserDefinedLiteralClass:
1561 case Stmt::ObjCMessageExprClass: {
1564 consumeConstructionContext(Layer, E);
1565 break;
1566 }
1567 case Stmt::ExprWithCleanupsClass: {
1569 findConstructionContexts(Layer, Cleanups->getSubExpr());
1570 break;
1571 }
1572 case Stmt::CXXFunctionalCastExprClass: {
1574 findConstructionContexts(Layer, Cast->getSubExpr());
1575 break;
1576 }
1577 case Stmt::ImplicitCastExprClass: {
1579
1580 switch (Cast->getCastKind()) {
1581 case CK_NoOp:
1582 case CK_ConstructorConversion:
1583 findConstructionContexts(Layer, Cast->getSubExpr());
1584 break;
1585 default:
1586 break;
1587 }
1588 break;
1589 }
1590 case Stmt::CXXBindTemporaryExprClass: {
1592 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1593 break;
1594 }
1595 case Stmt::MaterializeTemporaryExprClass: {
1596
1597
1598
1599
1603 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1604 }
1605 break;
1606 }
1607 case Stmt::ConditionalOperatorClass: {
1611
1612
1613
1614
1615 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1617 break;
1618 }
1619 findConstructionContexts(Layer, CO->getLHS());
1620 findConstructionContexts(Layer, CO->getRHS());
1621 break;
1622 }
1623 case Stmt::InitListExprClass: {
1625 if (ILE->isTransparent()) {
1626 findConstructionContexts(Layer, ILE->getInit(0));
1627 break;
1628 }
1629
1630 break;
1631 }
1632 case Stmt::ParenExprClass: {
1633
1634
1636 findConstructionContexts(Layer, PE->getSubExpr());
1637 break;
1638 }
1639 default:
1640 break;
1641 }
1642}
1643
1644void CFGBuilder::cleanupConstructionContext(Expr *E) {
1646 "We should not be managing construction contexts!");
1647 assert(ConstructionContextMap.count(E) &&
1648 "Cannot exit construction context without the context!");
1649 ConstructionContextMap.erase(E);
1650}
1651
1652
1653
1654
1655
1656
1657std::unique_ptr CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
1658 assert(cfg.get());
1659 if (!Statement)
1660 return nullptr;
1661
1662
1663
1664
1665 Succ = createBlock();
1666 assert(Succ == &cfg->getExit());
1667 Block = nullptr;
1668
1669
1670 LocalScope *paramScope = nullptr;
1671 if (const auto *FD = dyn_cast_or_null(D))
1672 for (ParmVarDecl *PD : FD->parameters())
1673 paramScope = addLocalScopeForVarDecl(PD, paramScope);
1674
1676 if (const CXXDestructorDecl *DD = dyn_cast_or_null(D))
1677 addImplicitDtorsForDestructor(DD);
1678
1679
1680 CFGBlock *B = addStmt(Statement);
1681
1682 if (badCFG)
1683 return nullptr;
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697 if (const auto *CD = dyn_cast_or_null(D)) {
1698 CFGBlock *VBaseSucc = nullptr;
1699 for (auto *I : llvm::reverse(CD->inits())) {
1701 I->isBaseInitializer() && I->isBaseVirtual()) {
1702
1703
1704
1705 VBaseSucc = Succ = B ? B : &cfg->getExit();
1706 Block = createBlock();
1707 }
1708 B = addInitializer(I);
1709 if (badCFG)
1710 return nullptr;
1711 }
1712 if (VBaseSucc) {
1713
1714 Succ = VBaseSucc;
1715 B = createBlock();
1718 addSuccessor(B, Block, true);
1719 }
1720 }
1721
1722 if (B)
1723 Succ = B;
1724
1725
1726
1727 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1728 E = BackpatchBlocks.end(); I != E; ++I ) {
1729
1730 CFGBlock *B = I->block;
1731 if (auto *G = dyn_cast(B->getTerminator())) {
1732 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1733
1734
1735 if (LI == LabelMap.end())
1736 continue;
1737 JumpTarget JT = LI->second;
1738
1739 CFGBlock *SuccBlk = createScopeChangesHandlingBlock(
1740 I->scopePosition, B, JT.scopePosition, JT.block);
1741 addSuccessor(B, SuccBlk);
1742 } else if (auto *G = dyn_cast(B->getTerminator())) {
1743 CFGBlock *Successor = (I+1)->block;
1744 for (auto *L : G->labels()) {
1745 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1746
1747
1748 if (LI == LabelMap.end())
1749 continue;
1750 JumpTarget JT = LI->second;
1751
1752 if (JT.block == Successor)
1753 continue;
1754 addSuccessor(B, JT.block);
1755 }
1756 I++;
1757 }
1758 }
1759
1760
1761 if (CFGBlock *B = cfg->getIndirectGotoBlock())
1762 for (LabelDecl *LD : AddressTakenLabels) {
1763
1764 LabelMapTy::iterator LI = LabelMap.find(LD);
1765
1766
1767
1768 if (LI == LabelMap.end()) continue;
1769
1770 addSuccessor(B, LI->second.block);
1771 }
1772
1773
1774 cfg->setEntry(createBlock());
1775
1777 assert(ConstructionContextMap.empty() &&
1778 "Not all construction contexts were cleaned up!");
1779
1780 return std::move(cfg);
1781}
1782
1783
1784
1785CFGBlock *CFGBuilder::createBlock(bool add_successor) {
1786 CFGBlock *B = cfg->createBlock();
1787 if (add_successor && Succ)
1788 addSuccessor(B, Succ);
1789 return B;
1790}
1791
1792
1793
1794
1795CFGBlock *CFGBuilder::createNoReturnBlock() {
1796 CFGBlock *B = createBlock(false);
1798 addSuccessor(B, &cfg->getExit(), Succ);
1799 return B;
1800}
1801
1802
1803CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
1806
1807 bool HasTemporaries = false;
1808
1809
1810
1814
1816
1817 TempDtorContext Context;
1819 false, Context);
1820 }
1821 }
1822
1823 autoCreateBlock();
1824 appendInitializer(Block, I);
1825
1827
1828
1830 dyn_cast(Init));
1831
1832 findConstructionContexts(
1834 AILEInit ? AILEInit : Init);
1835
1836 if (HasTemporaries) {
1837
1838
1840 }
1842 if (CXXDefaultInitExpr *Default = dyn_cast(Init)) {
1843
1844
1845
1846 autoCreateBlock();
1848 if (Stmt *Child = Default->getExpr())
1849 if (CFGBlock *R = Visit(Child))
1852 }
1853 }
1854 return Visit(Init);
1855 }
1856
1858}
1859
1860
1861
1863 bool *FoundMTE = nullptr) {
1864 while (true) {
1865
1866 Init = Init->IgnoreParens();
1867
1868
1870 Init = EWC->getSubExpr();
1871 continue;
1872 }
1873
1874
1876 = dyn_cast(Init)) {
1877 Init = MTE->getSubExpr();
1878 if (FoundMTE)
1879 *FoundMTE = true;
1880 continue;
1881 }
1882
1883
1884 const Expr *SkippedInit = Init->skipRValueSubobjectAdjustments();
1885 if (SkippedInit != Init) {
1886 Init = SkippedInit;
1887 continue;
1888 }
1889
1890 break;
1891 }
1892
1893 return Init->getType();
1894}
1895
1896
1897
1898void CFGBuilder::addLoopExit(const Stmt *LoopStmt){
1900 return;
1901 autoCreateBlock();
1902 appendLoopExit(Block, LoopStmt);
1903}
1904
1905
1906
1907
1908
1909
1910void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1911 LocalScope::const_iterator E,
1912 Stmt *S) {
1915 return;
1916
1917 if (B == E)
1918 return;
1919
1920
1921 if (B.inSameLocalScope(E)) {
1922 addAutomaticObjDestruction(B, E, S);
1923 return;
1924 }
1925
1926
1927 SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;
1928 LocalScopeEndMarkers.push_back(B);
1929 for (LocalScope::const_iterator I = B; I != E; ++I) {
1930 if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
1931 LocalScopeEndMarkers.push_back(I);
1932 }
1933 LocalScopeEndMarkers.push_back(E);
1934
1935
1936
1937 std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
1938 auto Pairwise =
1939 llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
1940 for (auto [E, B] : Pairwise) {
1941 if (!B.inSameLocalScope(E))
1942 addScopeExitHandling(B, E, S);
1943 addAutomaticObjDestruction(B, E, S);
1944 }
1945}
1946
1947
1948
1949
1950void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
1951 LocalScope::const_iterator E,
1952 Stmt *S) {
1954 return;
1955
1956 if (B == E)
1957 return;
1958
1959 SmallVector<VarDecl *, 10> DeclsNeedDestruction;
1960 DeclsNeedDestruction.reserve(B.distance(E));
1961
1962 for (VarDecl* D : llvm::make_range(B, E))
1963 if (needsAutomaticDestruction(D))
1964 DeclsNeedDestruction.push_back(D);
1965
1966 for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
1968
1969
1970
1971
1972 QualType Ty = VD->getType();
1976
1979 Block = createNoReturnBlock();
1980 }
1981
1982 autoCreateBlock();
1983
1984
1985
1986
1988 appendLifetimeEnds(Block, VD, S);
1989 if (BuildOpts.AddImplicitDtors && !hasTrivialDestructor(VD))
1990 appendAutomaticObjDtor(Block, VD, S);
1991 if (VD->hasAttr())
1992 appendCleanupFunction(Block, VD);
1993 }
1994}
1995
1996
1997
1998
1999
2000
2001void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
2002 LocalScope::const_iterator E, Stmt *S) {
2003 assert(!B.inSameLocalScope(E));
2005 return;
2006
2008 autoCreateBlock();
2009 appendScopeEnd(Block, B.getFirstVarInScope(), S);
2010 }
2011
2013 return;
2014
2015
2016 SmallVector<VarDecl *, 10> DeclsTrivial;
2017 DeclsTrivial.reserve(B.distance(E));
2018
2019
2020
2021
2022 for (VarDecl* D : llvm::make_range(B, E))
2023 if (!needsAutomaticDestruction(D))
2024 DeclsTrivial.push_back(D);
2025
2026 if (DeclsTrivial.empty())
2027 return;
2028
2029 autoCreateBlock();
2030 for (VarDecl *VD : llvm::reverse(DeclsTrivial))
2031 appendLifetimeEnds(Block, VD, S);
2032}
2033
2034
2035
2036
2037
2038
2039void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
2040 LocalScope::const_iterator DstPos,
2041 Stmt *S) {
2042 assert(Block && "Source block should be always crated");
2045 return;
2046 }
2047
2048 if (SrcPos == DstPos)
2049 return;
2050
2051
2052
2053 LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
2054
2055
2056 if (BuildOpts.AddScopes && !DstPos.inSameLocalScope(BasePos)) {
2057 for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
2058 if (I.pointsToFirstDeclaredVar())
2059 appendScopeBegin(Block, *I, S);
2060 }
2061
2062
2063
2064 addAutomaticObjHandling(SrcPos, BasePos, S);
2065}
2066
2067
2068
2069
2070
2071
2072CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
2073 LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,
2074 LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {
2075 if (SrcPos == DstPos)
2076 return DstBlk;
2077
2079 (!BuildOpts.AddScopes || SrcPos.inSameLocalScope(DstPos)))
2080 return DstBlk;
2081
2082
2083
2084 SaveAndRestore save_Block(Block), save_Succ(Succ);
2085
2086
2087 Block = createBlock(false);
2090 addSuccessor(Block, DstBlk);
2091
2092
2093 addScopeChangesHandling(SrcPos, DstPos, Block->getTerminatorStmt());
2094
2095 assert(Block && "There should be at least one scope changing Block");
2097}
2098
2099
2100
2101void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
2103 "Can be called only when dtors should be added");
2104 const CXXRecordDecl *RD = DD->getParent();
2105
2106
2107 for (const auto &VI : RD->vbases()) {
2108
2109
2110
2111 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2113 autoCreateBlock();
2114 appendBaseDtor(Block, &VI);
2115 }
2116 }
2117
2118
2119 for (const auto &BI : RD->bases()) {
2120 if (!BI.isVirtual()) {
2121 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2123 autoCreateBlock();
2124 appendBaseDtor(Block, &BI);
2125 }
2126 }
2127 }
2128
2129
2131 return;
2132 for (auto *FI : RD->fields()) {
2133
2134 QualType QT = FI->getType();
2135
2137 if (AT->isZeroSize())
2138 break;
2139 QT = AT->getElementType();
2140 }
2141
2144 autoCreateBlock();
2145 appendMemberDtor(Block, FI);
2146 }
2147 }
2148}
2149
2150
2151
2152LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
2153 if (Scope)
2154 return Scope;
2155 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
2156 return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);
2157}
2158
2159
2160
2161void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
2164 return;
2165
2166 LocalScope *Scope = nullptr;
2167
2168
2169 if (CompoundStmt *CS = dyn_cast(S)) {
2170 for (auto *BI : CS->body()) {
2171 Stmt *SI = BI->stripLabelLikeStatements();
2172 if (DeclStmt *DS = dyn_cast(SI))
2173 Scope = addLocalScopeForDeclStmt(DS, Scope);
2174 }
2175 return;
2176 }
2177
2178
2179
2181 addLocalScopeForDeclStmt(DS);
2182}
2183
2184
2185
2186LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
2187 LocalScope* Scope) {
2190 return Scope;
2191
2192 for (auto *DI : DS->decls())
2193 if (VarDecl *VD = dyn_cast(DI))
2194 Scope = addLocalScopeForVarDecl(VD, Scope);
2195 return Scope;
2196}
2197
2198bool CFGBuilder::needsAutomaticDestruction(const VarDecl *VD) const {
2199 return !hasTrivialDestructor(VD) || VD->hasAttr();
2200}
2201
2202bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const {
2203
2204 QualType QT = VD->getType();
2206
2207
2208
2209
2210
2211
2212
2213
2215 if () {
2216
2217
2218
2219 return true;
2220 }
2221
2222
2223 bool FoundMTE = false;
2225 if (!FoundMTE)
2226 return true;
2227 }
2228
2229
2231 if (AT->isZeroSize())
2232 return true;
2233 QT = AT->getElementType();
2234 }
2235
2236
2239 return true;
2240}
2241
2242
2243
2244
2245LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
2246 LocalScope* Scope) {
2249 return Scope;
2250
2251
2253 return Scope;
2254
2255
2256
2258 return Scope;
2259
2261 !needsAutomaticDestruction(VD)) {
2263 return Scope;
2264 }
2265
2266
2267 Scope = createOrReuseLocalScope(Scope);
2268 Scope->addVar(VD);
2269 ScopePos = Scope->begin();
2270 return Scope;
2271}
2272
2273
2274
2275void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
2276 LocalScope::const_iterator scopeBeginPos = ScopePos;
2277 addLocalScopeForStmt(S);
2278 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2279}
2280
2281
2282
2283
2284CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2285 bool ExternallyDestructed) {
2286 if (!S) {
2287 badCFG = true;
2288 return nullptr;
2289 }
2290
2291 if (Expr *E = dyn_cast(S))
2292 S = E->IgnoreParens();
2293
2295 if (auto *D = dyn_cast(S))
2296 return VisitOMPExecutableDirective(D, asc);
2297
2299 default:
2300 return VisitStmt(S, asc);
2301
2302 case Stmt::ImplicitValueInitExprClass:
2305 return VisitStmt(S, asc);
2306
2307 case Stmt::InitListExprClass:
2309
2310 case Stmt::AttributedStmtClass:
2312
2313 case Stmt::AddrLabelExprClass:
2315
2316 case Stmt::BinaryConditionalOperatorClass:
2318
2319 case Stmt::BinaryOperatorClass:
2321
2322 case Stmt::BlockExprClass:
2324
2325 case Stmt::BreakStmtClass:
2327
2328 case Stmt::CallExprClass:
2329 case Stmt::CXXOperatorCallExprClass:
2330 case Stmt::CXXMemberCallExprClass:
2331 case Stmt::UserDefinedLiteralClass:
2333
2334 case Stmt::CaseStmtClass:
2336
2337 case Stmt::ChooseExprClass:
2339
2340 case Stmt::CompoundStmtClass:
2341 return VisitCompoundStmt(cast(S), ExternallyDestructed);
2342
2343 case Stmt::ConditionalOperatorClass:
2345
2346 case Stmt::ContinueStmtClass:
2348
2349 case Stmt::CXXCatchStmtClass:
2351
2352 case Stmt::ExprWithCleanupsClass:
2354 asc, ExternallyDestructed);
2355
2356 case Stmt::CXXDefaultArgExprClass:
2357 case Stmt::CXXDefaultInitExprClass:
2358
2359
2360
2361
2362
2363
2364
2365
2366 return VisitStmt(S, asc);
2367
2368 case Stmt::CXXBindTemporaryExprClass:
2370
2371 case Stmt::CXXConstructExprClass:
2373
2374 case Stmt::CXXNewExprClass:
2376
2377 case Stmt::CXXDeleteExprClass:
2379
2380 case Stmt::CXXFunctionalCastExprClass:
2382
2383 case Stmt::CXXTemporaryObjectExprClass:
2385
2386 case Stmt::CXXThrowExprClass:
2388
2389 case Stmt::CXXTryStmtClass:
2391
2392 case Stmt::CXXTypeidExprClass:
2394
2395 case Stmt::CXXForRangeStmtClass:
2397
2398 case Stmt::DeclStmtClass:
2400
2401 case Stmt::DefaultStmtClass:
2403
2404 case Stmt::DoStmtClass:
2406
2407 case Stmt::ForStmtClass:
2409
2410 case Stmt::GotoStmtClass:
2412
2413 case Stmt::GCCAsmStmtClass:
2415
2416 case Stmt::IfStmtClass:
2418
2419 case Stmt::ImplicitCastExprClass:
2421
2422 case Stmt::ConstantExprClass:
2424
2425 case Stmt::IndirectGotoStmtClass:
2427
2428 case Stmt::LabelStmtClass:
2430
2431 case Stmt::LambdaExprClass:
2433
2434 case Stmt::MaterializeTemporaryExprClass:
2436 asc);
2437
2438 case Stmt::MemberExprClass:
2440
2441 case Stmt::NullStmtClass:
2443
2444 case Stmt::ObjCAtCatchStmtClass:
2446
2447 case Stmt::ObjCAutoreleasePoolStmtClass:
2449
2450 case Stmt::ObjCAtSynchronizedStmtClass:
2452
2453 case Stmt::ObjCAtThrowStmtClass:
2455
2456 case Stmt::ObjCAtTryStmtClass:
2458
2459 case Stmt::ObjCForCollectionStmtClass:
2461
2462 case Stmt::ObjCMessageExprClass:
2464
2465 case Stmt::OpaqueValueExprClass:
2467
2468 case Stmt::PseudoObjectExprClass:
2470
2471 case Stmt::ReturnStmtClass:
2472 case Stmt::CoreturnStmtClass:
2473 return VisitReturnStmt(S);
2474
2475 case Stmt::CoyieldExprClass:
2476 case Stmt::CoawaitExprClass:
2478
2479 case Stmt::SEHExceptStmtClass:
2481
2482 case Stmt::SEHFinallyStmtClass:
2484
2485 case Stmt::SEHLeaveStmtClass:
2487
2488 case Stmt::SEHTryStmtClass:
2490
2491 case Stmt::UnaryExprOrTypeTraitExprClass:
2493 asc);
2494
2495 case Stmt::StmtExprClass:
2497
2498 case Stmt::SwitchStmtClass:
2500
2501 case Stmt::UnaryOperatorClass:
2503
2504 case Stmt::WhileStmtClass:
2506
2507 case Stmt::ArrayInitLoopExprClass:
2509 }
2510}
2511
2512CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
2513 if (asc.alwaysAdd(*this, S)) {
2514 autoCreateBlock();
2515 appendStmt(Block, S);
2516 }
2517
2518 return VisitChildren(S);
2519}
2520
2521
2522CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
2523 CFGBlock *B = Block;
2524
2525
2526
2527 reverse_children RChildren(S, *Context);
2528 for (Stmt *Child : RChildren) {
2529 if (Child)
2530 if (CFGBlock *R = Visit(Child))
2531 B = R;
2532 }
2533 return B;
2534}
2535
2536CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
2537 if (asc.alwaysAdd(*this, ILE)) {
2538 autoCreateBlock();
2539 appendStmt(Block, ILE);
2540 }
2541 CFGBlock *B = Block;
2542
2543 reverse_children RChildren(ILE, *Context);
2544 for (Stmt *Child : RChildren) {
2545 if (!Child)
2546 continue;
2547 if (CFGBlock *R = Visit(Child))
2548 B = R;
2550 if (auto *DIE = dyn_cast(Child))
2551 if (Stmt *Child = DIE->getExpr())
2552 if (CFGBlock *R = Visit(Child))
2553 B = R;
2554 }
2555 }
2556 return B;
2557}
2558
2559CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
2560 AddStmtChoice asc) {
2561 AddressTakenLabels.insert(A->getLabel());
2562
2563 if (asc.alwaysAdd(*this, A)) {
2564 autoCreateBlock();
2565 appendStmt(Block, A);
2566 }
2567
2569}
2570
2574 "expected fallthrough not to have children");
2575 return isFallthrough;
2576}
2577
2580
2582 "expected [[assume]] not to have children");
2583 return hasAssumeAttr;
2584}
2585
2586CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
2587 AddStmtChoice asc) {
2588
2589
2590
2591
2592
2593
2594
2595
2597 if (isInterestingAttribute && asc.alwaysAdd(*this, A)) {
2598 autoCreateBlock();
2599 appendStmt(Block, A);
2600 }
2601
2602 return VisitChildren(A);
2603}
2604
2605CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {
2606 if (asc.alwaysAdd(*this, U)) {
2607 autoCreateBlock();
2608 appendStmt(Block, U);
2609 }
2610
2613
2614 return Visit(U->getSubExpr(), AddStmtChoice());
2615}
2616
2617CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
2618 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2619 appendStmt(ConfluenceBlock, B);
2620
2621 if (badCFG)
2622 return nullptr;
2623
2624 return VisitLogicalOperator(B, nullptr, ConfluenceBlock,
2625 ConfluenceBlock).first;
2626}
2627
2628std::pair<CFGBlock*, CFGBlock*>
2629CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
2630 Stmt *Term,
2631 CFGBlock *TrueBlock,
2632 CFGBlock *FalseBlock) {
2633
2634
2635
2637 CFGBlock *RHSBlock, *ExitBlock;
2638
2639 do {
2640 if (BinaryOperator *B_RHS = dyn_cast(RHS))
2641 if (B_RHS->isLogicalOp()) {
2642 std::tie(RHSBlock, ExitBlock) =
2643 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2644 break;
2645 }
2646
2647
2648
2649
2650
2651 ExitBlock = RHSBlock = createBlock(false);
2652
2653
2654
2655
2656 TryResult KnownVal = tryEvaluateBool(RHS);
2657 if (!KnownVal.isKnown())
2658 KnownVal = tryEvaluateBool(B);
2659
2660 if (!Term) {
2661 assert(TrueBlock == FalseBlock);
2662 addSuccessor(RHSBlock, TrueBlock);
2663 }
2664 else {
2666 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2667 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2668 }
2669
2670 Block = RHSBlock;
2671 RHSBlock = addStmt(RHS);
2672 }
2673 while (false);
2674
2675 if (badCFG)
2676 return std::make_pair(nullptr, nullptr);
2677
2678
2680
2681 if (BinaryOperator *B_LHS = dyn_cast(LHS))
2682 if (B_LHS->isLogicalOp()) {
2684 FalseBlock = RHSBlock;
2685 else
2686 TrueBlock = RHSBlock;
2687
2688
2689
2690
2691 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2692 }
2693
2694
2695
2696 CFGBlock *LHSBlock = createBlock(false);
2698
2699 Block = LHSBlock;
2700 CFGBlock *EntryLHSBlock = addStmt(LHS);
2701
2702 if (badCFG)
2703 return std::make_pair(nullptr, nullptr);
2704
2705
2706 TryResult KnownVal = tryEvaluateBool(LHS);
2707
2708
2710 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2711 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2712 } else {
2713 assert(B->getOpcode() == BO_LAnd);
2714 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2715 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2716 }
2717
2718 return std::make_pair(EntryLHSBlock, ExitBlock);
2719}
2720
2721CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
2722 AddStmtChoice asc) {
2723
2725 return VisitLogicalOperator(B);
2726
2727 if (B->getOpcode() == BO_Comma) {
2728 autoCreateBlock();
2729 appendStmt(Block, B);
2730 addStmt(B->getRHS());
2731 return addStmt(B->getLHS());
2732 }
2733
2735 if (asc.alwaysAdd(*this, B)) {
2736 autoCreateBlock();
2737 appendStmt(Block, B);
2738 }
2740 return Visit(B->getRHS());
2741 }
2742
2743 if (asc.alwaysAdd(*this, B)) {
2744 autoCreateBlock();
2745 appendStmt(Block, B);
2746 }
2747
2749 tryEvaluateBool(B);
2750
2751 CFGBlock *RBlock = Visit(B->getRHS());
2752 CFGBlock *LBlock = Visit(B->getLHS());
2753
2754
2755
2756 return (LBlock ? LBlock : RBlock);
2757}
2758
2759CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
2760 if (asc.alwaysAdd(*this, E)) {
2761 autoCreateBlock();
2762 appendStmt(Block, E);
2763 }
2765}
2766
2767CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
2768
2769
2770 if (badCFG)
2771 return nullptr;
2772
2773
2774 Block = createBlock(false);
2775 Block->setTerminator(B);
2776
2777
2778
2779 if (BreakJumpTarget.block) {
2780 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2781 addSuccessor(Block, BreakJumpTarget.block);
2782 } else
2783 badCFG = true;
2784
2786}
2787
2792
2794 if (FT) {
2795 if (const FunctionProtoType *Proto = dyn_cast(FT))
2797 Proto->isNothrow())
2798 return false;
2799 }
2800 return true;
2801}
2802
2806 if (BuiltinID != Builtin::BI__assume &&
2807 BuiltinID != Builtin::BI__builtin_assume)
2808 return false;
2809
2811}
2812
2813CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
2814
2815 QualType calleeType = C->getCallee()->getType();
2818
2819
2820
2821 if (!boundType.isNull()) calleeType = boundType;
2822 }
2823
2824
2826
2827 bool AddEHEdge = false;
2828
2829
2830 if (Context->getLangOpts().Exceptions) {
2832 AddEHEdge = true;
2833 }
2834
2835
2836
2837 bool OmitArguments = false;
2838
2839 if (FunctionDecl *FD = C->getDirectCallee()) {
2840
2841
2842
2843
2844 if (!FD->isVariadic())
2845 findConstructionContextsForArguments(C);
2846
2847 if (FD->isNoReturn() || FD->isAnalyzerNoReturn() ||
2848 C->isBuiltinAssumeFalse(*Context))
2849 NoReturn = true;
2850 if (FD->hasAttr())
2851 AddEHEdge = false;
2853 FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2854 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2855 OmitArguments = true;
2856 }
2857
2858 if ((C->getCallee(), *Context))
2859 AddEHEdge = false;
2860
2861 if (OmitArguments) {
2862 assert(!NoReturn && "noreturn calls with unevaluated args not implemented");
2863 assert(!AddEHEdge && "EH calls with unevaluated args not implemented");
2864 autoCreateBlock();
2866 return Visit(C->getCallee());
2867 }
2868
2869 if (!NoReturn && !AddEHEdge) {
2870 autoCreateBlock();
2872
2873 return VisitChildren(C);
2874 }
2875
2878 if (badCFG)
2879 return nullptr;
2880 }
2881
2882 if (NoReturn)
2883 Block = createNoReturnBlock();
2884 else
2885 Block = createBlock();
2886
2888
2889 if (AddEHEdge) {
2890
2891 if (TryTerminatedBlock)
2892 addSuccessor(Block, TryTerminatedBlock);
2893 else
2894 addSuccessor(Block, &cfg->getExit());
2895 }
2896
2897 return VisitChildren(C);
2898}
2899
2900CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
2901 AddStmtChoice asc) {
2902 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2903 appendStmt(ConfluenceBlock, C);
2904 if (badCFG)
2905 return nullptr;
2906
2907 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
2908 Succ = ConfluenceBlock;
2909 Block = nullptr;
2910 CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);
2911 if (badCFG)
2912 return nullptr;
2913
2914 Succ = ConfluenceBlock;
2915 Block = nullptr;
2916 CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);
2917 if (badCFG)
2918 return nullptr;
2919
2920 Block = createBlock(false);
2921
2922 const TryResult& KnownVal = tryEvaluateBool(C->getCond());
2923 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2924 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2926 return addStmt(C->getCond());
2927}
2928
2929CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C,
2930 bool ExternallyDestructed) {
2931 LocalScope::const_iterator scopeBeginPos = ScopePos;
2932 addLocalScopeForStmt(C);
2933
2935
2936
2937 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2938 }
2939
2940 CFGBlock *LastBlock = Block;
2941
2942 for (Stmt *S : llvm::reverse(C->body())) {
2943
2944
2945 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2946 ExternallyDestructed);
2947
2948 if (newBlock)
2949 LastBlock = newBlock;
2950
2951 if (badCFG)
2952 return nullptr;
2953
2954 ExternallyDestructed = false;
2955 }
2956
2957 return LastBlock;
2958}
2959
2960CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
2961 AddStmtChoice asc) {
2962 const BinaryConditionalOperator *BCO = dyn_cast(C);
2963 const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);
2964
2965
2966
2967 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2968 appendStmt(ConfluenceBlock, C);
2969 if (badCFG)
2970 return nullptr;
2971
2972 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
2973
2974
2975
2976
2977
2978 Succ = ConfluenceBlock;
2979 Block = nullptr;
2980 CFGBlock *LHSBlock = nullptr;
2981 const Expr *trueExpr = C->getTrueExpr();
2982 if (trueExpr != opaqueValue) {
2983 LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);
2984 if (badCFG)
2985 return nullptr;
2986 Block = nullptr;
2987 }
2988 else
2989 LHSBlock = ConfluenceBlock;
2990
2991
2992 Succ = ConfluenceBlock;
2993 CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);
2994 if (badCFG)
2995 return nullptr;
2996
2997
2998 if (BinaryOperator *Cond =
2999 dyn_cast(C->getCond()->IgnoreParens()))
3000 if (Cond->isLogicalOp())
3001 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
3002
3003
3004 Block = createBlock(false);
3005
3006
3007 const TryResult& KnownVal = tryEvaluateBool(C->getCond());
3008 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
3009 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
3011 Expr *condExpr = C->getCond();
3012
3013 if (opaqueValue) {
3014
3015
3016 if (condExpr != opaqueValue)
3017 addStmt(condExpr);
3018
3019
3020
3021 return addStmt(BCO->getCommon());
3022 }
3023
3024 return addStmt(condExpr);
3025}
3026
3027CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
3028
3029
3032
3033
3035 return VisitDeclSubExpr(DS);
3036
3037 CFGBlock *B = nullptr;
3038
3039
3042 I != E; ++I) {
3043
3044
3045
3046 DeclGroupRef DG(*I);
3047 Decl *D = *I;
3048 DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
3049 cfg->addSyntheticDeclStmt(DSNew, DS);
3050
3051
3052 B = VisitDeclSubExpr(DSNew);
3053 }
3054
3055 return B;
3056}
3057
3058
3059
3060CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
3061 assert(DS->isSingleDecl() && "Can handle single declarations only.");
3062
3063 if (const auto *TND = dyn_cast(DS->getSingleDecl())) {
3064
3065 const Type *T = TND->getUnderlyingType().getTypePtr();
3068
3069 autoCreateBlock();
3070 appendStmt(Block, DS);
3071
3072 CFGBlock *LastBlock = Block;
3073 for (const VariableArrayType *VA = FindVA(T); VA != nullptr;
3074 VA = FindVA(VA->getElementType().getTypePtr())) {
3075 if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
3076 LastBlock = NewBlock;
3077 }
3078 return LastBlock;
3079 }
3080
3081 VarDecl *VD = dyn_cast(DS->getSingleDecl());
3082
3083 if (!VD) {
3084
3085
3087 }
3088
3089 bool HasTemporaries = false;
3090
3091
3092 CFGBlock *blockAfterStaticInit = nullptr;
3093
3095
3096
3099 Block = nullptr;
3100 if (badCFG)
3101 return nullptr;
3102 }
3103 blockAfterStaticInit = Succ;
3104 }
3105
3106
3107
3111
3113
3114 TempDtorContext Context;
3116 true, Context);
3117 }
3118 }
3119
3120
3121
3122 if (const auto *DD = dyn_cast(VD)) {
3123 for (auto *BD : llvm::reverse(DD->bindings())) {
3124 if (auto *VD = BD->getHoldingVar()) {
3125 DeclGroupRef DG(VD);
3126 DeclStmt *DSNew =
3128 cfg->addSyntheticDeclStmt(DSNew, DS);
3129 Block = VisitDeclSubExpr(DSNew);
3130 }
3131 }
3132 }
3133
3134 autoCreateBlock();
3135 appendStmt(Block, DS);
3136
3137
3138
3139 const auto *AILE = dyn_cast_or_null(Init);
3140
3141 findConstructionContexts(
3143 AILE ? AILE->getSubExpr() : Init);
3144
3145
3146
3147
3148 CFGBlock *LastBlock = Block;
3149
3151 if (HasTemporaries) {
3152
3153
3155 if (CFGBlock *newBlock = Visit(EC->getSubExpr()))
3156 LastBlock = newBlock;
3157 }
3158 else {
3159 if (CFGBlock *newBlock = Visit(Init))
3160 LastBlock = newBlock;
3161 }
3162 }
3163
3164
3165
3166
3168 VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {
3169 if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3170 LastBlock = newBlock;
3171 }
3172
3173 maybeAddScopeBeginForVarDecl(Block, VD, DS);
3174
3175
3176 if (ScopePos && VD == *ScopePos)
3177 ++ScopePos;
3178
3179 CFGBlock *B = LastBlock;
3180 if (blockAfterStaticInit) {
3181 Succ = B;
3182 Block = createBlock(false);
3183 Block->setTerminator(DS);
3184 addSuccessor(Block, blockAfterStaticInit);
3185 addSuccessor(Block, B);
3187 }
3188
3189 return B;
3190}
3191
3192CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202 SaveAndRestore save_scope_pos(ScopePos);
3203
3204
3206 addLocalScopeForStmt(Init);
3207
3208
3209
3211 addLocalScopeForVarDecl(VD);
3212
3213 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3214
3215
3216
3219 if (badCFG)
3220 return nullptr;
3221 }
3222
3223
3224 CFGBlock *ElseBlock = Succ;
3225
3226 if (Stmt *Else = I->getElse()) {
3227 SaveAndRestore sv(Succ);
3228
3229
3230
3231 Block = nullptr;
3232
3233
3234
3236 addLocalScopeAndDtors(Else);
3237
3238 ElseBlock = addStmt(Else);
3239
3240 if (!ElseBlock)
3241 ElseBlock = sv.get();
3242 else if (Block) {
3243 if (badCFG)
3244 return nullptr;
3245 }
3246 }
3247
3248
3249 CFGBlock *ThenBlock;
3250 {
3251 Stmt *Then = I->getThen();
3252 assert(Then);
3253 SaveAndRestore sv(Succ);
3254 Block = nullptr;
3255
3256
3257
3259 addLocalScopeAndDtors(Then);
3260
3261 ThenBlock = addStmt(Then);
3262
3263 if (!ThenBlock) {
3264
3265
3266
3267 ThenBlock = createBlock(false);
3268 addSuccessor(ThenBlock, sv.get());
3269 } else if (Block) {
3270 if (badCFG)
3271 return nullptr;
3272 }
3273 }
3274
3275
3276
3277
3278
3279
3280
3281
3282 BinaryOperator *Cond =
3286 CFGBlock *LastBlock;
3287 if (Cond && Cond->isLogicalOp())
3288 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
3289 else {
3290
3291 Block = createBlock(false);
3292
3293
3294 Block->setTerminator(I);
3295
3296
3297 TryResult KnownVal;
3299 KnownVal = tryEvaluateBool(I->getCond());
3300
3301
3302
3303 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
3304 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
3305
3308
3309
3310
3311
3312 LastBlock = addStmt(I->getCond());
3313
3314
3315
3317 autoCreateBlock();
3318 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
3319 }
3320 }
3321
3322
3324 autoCreateBlock();
3325 LastBlock = addStmt(Init);
3326 }
3327
3328 return LastBlock;
3329}
3330
3331CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
3332
3333
3334
3335
3336
3337
3339
3340
3341 Block = createBlock(false);
3342
3343 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3344
3345 if (auto *R = dyn_cast(S))
3346 findConstructionContexts(
3348 R->getRetValue());
3349
3350
3351
3352 if (->hasNoReturnElement())
3353 addSuccessor(Block, &cfg->getExit());
3354
3355
3356 appendStmt(Block, S);
3357
3358
3359 if (ReturnStmt *RS = dyn_cast(S)) {
3360 if (Expr *O = RS->getRetValue())
3361 return Visit(O, AddStmtChoice::AlwaysAdd, true);
3363 }
3364
3366 auto *B = Block;
3368 B = R;
3369
3372
3373 if (CFGBlock *R = Visit(RV))
3374 B = R;
3375
3376 return B;
3377}
3378
3379CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
3380 AddStmtChoice asc) {
3381
3382
3383
3384 if (asc.alwaysAdd(*this, E)) {
3385 autoCreateBlock();
3386 appendStmt(Block, E);
3387 }
3388 CFGBlock *B = Block;
3390 B = R;
3392 B = R;
3394 B = R;
3396 B = R;
3397 return B;
3398}
3399
3400CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
3401
3402
3403
3404
3405
3406 SaveAndRestore save_scope_pos(ScopePos);
3407
3409 CFGBlock *SEHExceptBlock = Block;
3410 if (!SEHExceptBlock)
3411 SEHExceptBlock = createBlock();
3412
3413 appendStmt(SEHExceptBlock, ES);
3414
3415
3416 SEHExceptBlock->setLabel(ES);
3417
3418
3419 if (badCFG)
3420 return nullptr;
3421
3422
3423 Block = nullptr;
3424
3425 return SEHExceptBlock;
3426}
3427
3428CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
3429 return VisitCompoundStmt(FS->getBlock(), false);
3430}
3431
3432CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
3433
3434
3435 if (badCFG)
3436 return nullptr;
3437
3438
3439 Block = createBlock(false);
3440 Block->setTerminator(LS);
3441
3442
3443
3444 if (SEHLeaveJumpTarget.block) {
3445 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3446 addSuccessor(Block, SEHLeaveJumpTarget.block);
3447 } else
3448 badCFG = true;
3449
3451}
3452
3453CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
3454
3455
3456 CFGBlock *SEHTrySuccessor = nullptr;
3457
3459 if (badCFG)
3460 return nullptr;
3461 SEHTrySuccessor = Block;
3462 } else SEHTrySuccessor = Succ;
3463
3464
3466 return NYS();
3467
3468 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3469
3470
3471 CFGBlock *NewTryTerminatedBlock = createBlock(false);
3472
3473
3474 NewTryTerminatedBlock->setTerminator(Terminator);
3475
3476 if (SEHExceptStmt *Except = Terminator->getExceptHandler()) {
3477
3478 Succ = SEHTrySuccessor;
3479 Block = nullptr;
3480 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3481 if (!ExceptBlock)
3482 return nullptr;
3483
3484
3485 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3486 }
3487 if (PrevSEHTryTerminatedBlock)
3488 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3489 else
3490 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3491
3492
3493 Succ = SEHTrySuccessor;
3494
3495
3496 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3497 cfg->addTryDispatchBlock(TryTerminatedBlock);
3498
3499
3500
3501
3502 SaveAndRestore save_break(SEHLeaveJumpTarget);
3503 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3504
3505 assert(Terminator->getTryBlock() && "__try must contain a non-NULL body");
3506 Block = nullptr;
3507 return addStmt(Terminator->getTryBlock());
3508}
3509
3510CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
3511
3513 CFGBlock *LabelBlock = Block;
3514
3515 if (!LabelBlock)
3516 LabelBlock = createBlock();
3517
3518 assert(!LabelMap.contains(L->getDecl()) && "label already in map");
3519 LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);
3520
3521
3522
3523
3524
3526 if (badCFG)
3527 return nullptr;
3528
3529
3530 Block = nullptr;
3531
3532
3533 Succ = LabelBlock;
3534
3535 return LabelBlock;
3536}
3537
3538CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
3539 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3541 if (Expr *CopyExpr = CI.getCopyExpr()) {
3542 CFGBlock *Tmp = Visit(CopyExpr);
3543 if (Tmp)
3544 LastBlock = Tmp;
3545 }
3546 }
3547 return LastBlock;
3548}
3549
3550CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {
3551 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3552
3553 unsigned Idx = 0;
3556 it != et; ++it, ++Idx) {
3557 if (Expr *Init = *it) {
3558
3559
3561 dyn_cast(Init));
3562
3564 cfg->getBumpVectorContext(), {E, Idx}),
3565 AILEInit ? AILEInit : Init);
3566
3567 CFGBlock *Tmp = Visit(Init);
3568 if (Tmp)
3569 LastBlock = Tmp;
3570 }
3571 }
3572 return LastBlock;
3573}
3574
3575CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
3576
3577
3578
3579 Block = createBlock(false);
3580 Block->setTerminator(G);
3581
3582
3583 LabelMapTy::iterator I = LabelMap.find(G->getLabel());
3584
3585 if (I == LabelMap.end())
3586
3587 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3588 else {
3589 JumpTarget JT = I->second;
3590 addSuccessor(Block, JT.block);
3591 addScopeChangesHandling(ScopePos, JT.scopePosition, G);
3592 }
3593
3595}
3596
3597CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
3598
3599
3600
3602 return VisitStmt(G, asc);
3603
3606 if (badCFG)
3607 return nullptr;
3608 }
3609 Block = createBlock();
3610 Block->setTerminator(G);
3611
3612 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3613
3614
3615 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3616 return VisitChildren(G);
3617}
3618
3619CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
3620 CFGBlock *LoopSuccessor = nullptr;
3621
3622
3623
3624 SaveAndRestore save_scope_pos(ScopePos);
3625
3626
3627
3628
3630 addLocalScopeForStmt(Init);
3631 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3632
3634 addLocalScopeForVarDecl(VD);
3635 LocalScope::const_iterator ContinueScopePos = ScopePos;
3636
3637 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3638
3639 addLoopExit(F);
3640
3641
3642
3644 if (badCFG)
3645 return nullptr;
3646 LoopSuccessor = Block;
3647 } else
3648 LoopSuccessor = Succ;
3649
3650
3651
3652 SaveAndRestore save_break(BreakJumpTarget);
3653 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3654
3655 CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
3656
3657
3658 {
3660
3661
3662 SaveAndRestore save_Block(Block), save_Succ(Succ);
3663 SaveAndRestore save_continue(ContinueJumpTarget);
3664
3665
3666
3667
3668 Block = Succ = TransitionBlock = createBlock(false);
3669 TransitionBlock->setLoopTarget(F);
3670
3671
3672
3673
3674 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3675
3676 if (Stmt *I = F->getInc()) {
3677
3678
3679 Succ = addStmt(I);
3680 }
3681
3682
3684 assert(Block == Succ);
3685 if (badCFG)
3686 return nullptr;
3687 Block = nullptr;
3688 }
3689
3690
3691
3692 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3693 ContinueJumpTarget.block->setLoopTarget(F);
3694
3695
3696
3697
3699 addLocalScopeAndDtors(F->getBody());
3700
3701
3702
3703 BodyBlock = addStmt(F->getBody());
3704
3705 if (!BodyBlock) {
3706
3707
3708 BodyBlock = ContinueJumpTarget.block;
3709 }
3710 else if (badCFG)
3711 return nullptr;
3712 }
3713
3714
3715
3716
3717 CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
3718
3719 do {
3721 SaveAndRestore save_scope_pos(ScopePos);
3722
3723
3724
3725 if (BinaryOperator *Cond =
3726 dyn_cast_or_null(C ? C->IgnoreParens() : nullptr))
3727 if (Cond->isLogicalOp()) {
3728 std::tie(EntryConditionBlock, ExitConditionBlock) =
3729 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3730 break;
3731 }
3732
3733
3734 EntryConditionBlock = ExitConditionBlock = createBlock(false);
3735 ExitConditionBlock->setTerminator(F);
3736
3737
3738 TryResult KnownVal(true);
3739
3740 if (C) {
3741
3742
3743
3744 Block = ExitConditionBlock;
3745 EntryConditionBlock = addStmt(C);
3746
3747
3748
3751 autoCreateBlock();
3754 findConstructionContexts(
3757 appendStmt(Block, DS);
3758 EntryConditionBlock = addStmt(Init);
3759 assert(Block == EntryConditionBlock);
3760 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3761 }
3762 }
3763
3764 if (Block && badCFG)
3765 return nullptr;
3766
3767 KnownVal = tryEvaluateBool(C);
3768 }
3769
3770
3771 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3772
3773
3774 addSuccessor(ExitConditionBlock,
3775 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3776 } while (false);
3777
3778
3779 addSuccessor(TransitionBlock, EntryConditionBlock);
3780
3781
3782 Succ = EntryConditionBlock;
3783
3784
3785
3786 if (Stmt *I = F->getInit()) {
3787 SaveAndRestore save_scope_pos(ScopePos);
3788 ScopePos = LoopBeginScopePos;
3789 Block = createBlock();
3790 return addStmt(I);
3791 }
3792
3793
3794
3795 Block = nullptr;
3796 Succ = EntryConditionBlock;
3797 return EntryConditionBlock;
3798}
3799
3800CFGBlock *
3801CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
3802 AddStmtChoice asc) {
3803 findConstructionContexts(
3806
3807 return VisitStmt(MTE, asc);
3808}
3809
3810CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
3811 if (asc.alwaysAdd(*this, M)) {
3812 autoCreateBlock();
3813 appendStmt(Block, M);
3814 }
3815 return Visit(M->getBase());
3816}
3817
3818CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850 CFGBlock *LoopSuccessor = nullptr;
3851
3853 if (badCFG)
3854 return nullptr;
3855 LoopSuccessor = Block;
3856 Block = nullptr;
3857 } else
3858 LoopSuccessor = Succ;
3859
3860
3861 CFGBlock *ExitConditionBlock = createBlock(false);
3862
3863
3865
3866
3867
3868
3869 appendStmt(ExitConditionBlock, S);
3870 Block = ExitConditionBlock;
3871
3872
3873
3874
3875 CFGBlock *EntryConditionBlock = Visit(S->getElement(),
3876 AddStmtChoice::NotAlwaysAdd);
3878 if (badCFG)
3879 return nullptr;
3880 Block = nullptr;
3881 }
3882
3883
3884
3885 Succ = EntryConditionBlock;
3886
3887
3888 {
3889
3890 SaveAndRestore save_Block(Block), save_Succ(Succ);
3891 SaveAndRestore save_continue(ContinueJumpTarget),
3892 save_break(BreakJumpTarget);
3893
3894
3895
3896
3897 CFGBlock *LoopBackBlock = nullptr;
3898 Succ = LoopBackBlock = createBlock();
3900
3901 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3902 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3903
3904 CFGBlock *BodyBlock = addStmt(S->getBody());
3905
3906 if (!BodyBlock)
3907 BodyBlock = ContinueJumpTarget.block;
3908 else if (Block) {
3909 if (badCFG)
3910 return nullptr;
3911 }
3912
3913
3914 addSuccessor(ExitConditionBlock, BodyBlock);
3915 }
3916
3917
3918
3919 addSuccessor(ExitConditionBlock, LoopSuccessor);
3920
3921
3922 Block = createBlock();
3924}
3925
3926CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
3927
3929
3930}
3931
3932CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
3933
3934
3935
3936 CFGBlock *SyncBlock = addStmt(S->getSynchBody());
3937
3938
3939
3940 if (SyncBlock) {
3941 if (badCFG)
3942 return nullptr;
3943
3944 Block = nullptr;
3945 Succ = SyncBlock;
3946 }
3947
3948
3949 autoCreateBlock();
3950 appendStmt(Block, S);
3951
3952
3954}
3955
3956CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
3957 autoCreateBlock();
3958
3959
3960 appendStmt(Block, E);
3961
3962 CFGBlock *lastBlock = Block;
3963
3964
3965
3968
3969
3970
3971 if (OpaqueValueExpr *OVE = dyn_cast(Semantic))
3972 Semantic = OVE->getSourceExpr();
3973
3974 if (CFGBlock *B = Visit(Semantic))
3975 lastBlock = B;
3976 }
3977
3978 return lastBlock;
3979}
3980
3981CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
3982 CFGBlock *LoopSuccessor = nullptr;
3983
3984
3985
3986 SaveAndRestore save_scope_pos(ScopePos);
3987
3988
3989
3990 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3992 addLocalScopeForVarDecl(VD);
3993 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3994 }
3995 addLoopExit(W);
3996
3997
3998
4000 if (badCFG)
4001 return nullptr;
4002 LoopSuccessor = Block;
4003 Block = nullptr;
4004 } else {
4005 LoopSuccessor = Succ;
4006 }
4007
4008 CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
4009
4010
4011 {
4013
4014
4015 SaveAndRestore save_Block(Block), save_Succ(Succ);
4016 SaveAndRestore save_continue(ContinueJumpTarget),
4017 save_break(BreakJumpTarget);
4018
4019
4020
4021 Succ = TransitionBlock = createBlock(false);
4022 TransitionBlock->setLoopTarget(W);
4023 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
4024
4025
4026 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4027
4028
4029 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4030
4031
4032
4034 addLocalScopeAndDtors(W->getBody());
4035
4036
4037 BodyBlock = addStmt(W->getBody());
4038
4039 if (!BodyBlock)
4040 BodyBlock = ContinueJumpTarget.block;
4041 else if (Block && badCFG)
4042 return nullptr;
4043 }
4044
4045
4046
4047
4048 CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
4049
4050 do {
4052
4053
4054
4055 if (BinaryOperator *Cond = dyn_cast(C->IgnoreParens()))
4056 if (Cond->isLogicalOp()) {
4057 std::tie(EntryConditionBlock, ExitConditionBlock) =
4058 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
4059 break;
4060 }
4061
4062
4063 ExitConditionBlock = createBlock(false);
4065
4066
4067
4068
4069 Block = ExitConditionBlock;
4070 Block = EntryConditionBlock = addStmt(C);
4071
4072
4073
4076 autoCreateBlock();
4079 findConstructionContexts(
4081 const_cast<DeclStmt *>(DS)),
4083 appendStmt(Block, DS);
4084 EntryConditionBlock = addStmt(Init);
4085 assert(Block == EntryConditionBlock);
4086 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
4087 }
4088 }
4089
4090 if (Block && badCFG)
4091 return nullptr;
4092
4093
4094 const TryResult& KnownVal = tryEvaluateBool(C);
4095
4096
4097 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
4098
4099
4100 addSuccessor(ExitConditionBlock,
4101 KnownVal.isTrue() ? nullptr : LoopSuccessor);
4102 } while(false);
4103
4104
4105 addSuccessor(TransitionBlock, EntryConditionBlock);
4106
4107
4108
4109 Block = nullptr;
4110
4111
4112 Succ = EntryConditionBlock;
4113 return EntryConditionBlock;
4114}
4115
4116CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
4117 AddStmtChoice asc) {
4118 if (asc.alwaysAdd(*this, A)) {
4119 autoCreateBlock();
4120 appendStmt(Block, A);
4121 }
4122
4123 CFGBlock *B = Block;
4124
4125 if (CFGBlock *R = Visit(A->getSubExpr()))
4126 B = R;
4127
4128 auto *OVE = dyn_cast(A->getCommonExpr());
4129 assert(OVE && "ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
4130 "OpaqueValueExpr!");
4131 if (CFGBlock *R = Visit(OVE->getSourceExpr()))
4132 B = R;
4133
4134 return B;
4135}
4136
4137CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {
4138
4139
4140
4141
4142
4143 SaveAndRestore save_scope_pos(ScopePos);
4144
4147
4148 CFGBlock *CatchBlock = Block;
4149 if (!CatchBlock)
4150 CatchBlock = createBlock();
4151
4152 appendStmt(CatchBlock, CS);
4153
4154
4156
4157
4158 if (badCFG)
4159 return nullptr;
4160
4161
4162 Block = nullptr;
4163
4164 return CatchBlock;
4165}
4166
4167CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
4168
4169 if (badCFG)
4170 return nullptr;
4171
4172
4173 Block = createBlock(false);
4174
4175 if (TryTerminatedBlock)
4176
4177 addSuccessor(Block, TryTerminatedBlock);
4178 else
4179
4180 addSuccessor(Block, &cfg->getExit());
4181
4182
4183
4184 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4185}
4186
4187CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {
4188
4189
4190 CFGBlock *TrySuccessor = nullptr;
4191
4193 if (badCFG)
4194 return nullptr;
4195 TrySuccessor = Block;
4196 } else
4197 TrySuccessor = Succ;
4198
4199
4201 return NYS();
4202
4203 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4204
4205
4206 CFGBlock *NewTryTerminatedBlock = createBlock(false);
4207
4208 NewTryTerminatedBlock->setTerminator(Terminator);
4209
4210 bool HasCatchAll = false;
4211 for (ObjCAtCatchStmt *CS : Terminator->catch_stmts()) {
4212
4213 Succ = TrySuccessor;
4215 HasCatchAll = true;
4216 }
4217 Block = nullptr;
4218 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4219 if (!CatchBlock)
4220 return nullptr;
4221
4222
4223 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4224 }
4225
4226
4227 if (!HasCatchAll) {
4228 if (PrevTryTerminatedBlock)
4229 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4230 else
4231 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4232 }
4233
4234
4235 Succ = TrySuccessor;
4236
4237
4238 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4239 cfg->addTryDispatchBlock(TryTerminatedBlock);
4240
4241 assert(Terminator->getTryBody() && "try must contain a non-NULL body");
4242 Block = nullptr;
4243 return addStmt(Terminator->getTryBody());
4244}
4245
4246CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
4247 AddStmtChoice asc) {
4248 findConstructionContextsForArguments(ME);
4249
4250 autoCreateBlock();
4251 appendObjCMessage(Block, ME);
4252
4253 return VisitChildren(ME);
4254}
4255
4256CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
4257
4258 if (badCFG)
4259 return nullptr;
4260
4261
4262 Block = createBlock(false);
4263
4264 if (TryTerminatedBlock)
4265
4266 addSuccessor(Block, TryTerminatedBlock);
4267 else
4268
4269 addSuccessor(Block, &cfg->getExit());
4270
4271
4272
4273 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4274}
4275
4276CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {
4277 if (asc.alwaysAdd(*this, S)) {
4278 autoCreateBlock();
4279 appendStmt(Block, S);
4280 }
4281
4282
4283
4284
4285
4286
4287
4289 return VisitChildren(S);
4290
4291
4293}
4294
4295CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
4296 CFGBlock *LoopSuccessor = nullptr;
4297
4298 addLoopExit(D);
4299
4300
4301
4303 if (badCFG)
4304 return nullptr;
4305 LoopSuccessor = Block;
4306 } else
4307 LoopSuccessor = Succ;
4308
4309
4310
4311
4312 CFGBlock *ExitConditionBlock = createBlock(false);
4313 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4314
4315
4317
4318
4319
4320 if (Stmt *C = D->getCond()) {
4321 Block = ExitConditionBlock;
4322 EntryConditionBlock = addStmt(C);
4324 if (badCFG)
4325 return nullptr;
4326 }
4327 }
4328
4329
4330 Succ = EntryConditionBlock;
4331
4332
4333 const TryResult &KnownVal = tryEvaluateBool(D->getCond());
4334
4335
4336 CFGBlock *BodyBlock = nullptr;
4337 {
4339
4340
4341 SaveAndRestore save_Block(Block), save_Succ(Succ);
4342 SaveAndRestore save_continue(ContinueJumpTarget),
4343 save_break(BreakJumpTarget);
4344
4345
4346 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4347
4348
4349 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4350
4351
4352 Block = nullptr;
4353
4354
4355
4357 addLocalScopeAndDtors(D->getBody());
4358
4359
4360 BodyBlock = addStmt(D->getBody());
4361
4362 if (!BodyBlock)
4363 BodyBlock = EntryConditionBlock;
4364 else if (Block) {
4365 if (badCFG)
4366 return nullptr;
4367 }
4368
4369
4370
4371
4372
4373
4374 Block = nullptr;
4375 Succ = BodyBlock;
4376 CFGBlock *LoopBackBlock = createBlock();
4378
4379 if (!KnownVal.isFalse())
4380
4381 addSuccessor(ExitConditionBlock, LoopBackBlock);
4382 else
4383 addSuccessor(ExitConditionBlock, nullptr);
4384 }
4385
4386
4387
4388 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4389
4390
4391
4392 Block = nullptr;
4393
4394
4395 Succ = BodyBlock;
4396 return BodyBlock;
4397}
4398
4399CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {
4400
4401
4402 if (badCFG)
4403 return nullptr;
4404
4405
4406 Block = createBlock(false);
4408
4409
4410
4411 if (ContinueJumpTarget.block) {
4412 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
4413 addSuccessor(Block, ContinueJumpTarget.block);
4414 } else
4415 badCFG = true;
4416
4418}
4419
4420CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
4421 AddStmtChoice asc) {
4422 if (asc.alwaysAdd(*this, E)) {
4423 autoCreateBlock();
4424 appendStmt(Block, E);
4425 }
4426
4427
4428
4429
4430 if (E->getKind() != UETT_SizeOf)
4432
4433 CFGBlock *lastBlock = Block;
4434
4437 VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))
4438 lastBlock = addStmt(VA->getSizeExpr());
4439 }
4440 return lastBlock;
4441}
4442
4443
4444
4445CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
4446 if (asc.alwaysAdd(*this, SE)) {
4447 autoCreateBlock();
4448 appendStmt(Block, SE);
4449 }
4450 return VisitCompoundStmt(SE->getSubStmt(), true);
4451}
4452
4453CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
4454
4455
4456 CFGBlock *SwitchSuccessor = nullptr;
4457
4458
4459
4460 SaveAndRestore save_scope_pos(ScopePos);
4461
4462
4464 addLocalScopeForStmt(Init);
4465
4466
4467
4469 addLocalScopeForVarDecl(VD);
4470
4471 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4472
4474 if (badCFG)
4475 return nullptr;
4476 SwitchSuccessor = Block;
4477 } else SwitchSuccessor = Succ;
4478
4479
4480 SaveAndRestore save_switch(SwitchTerminatedBlock),
4481 save_default(DefaultCaseBlock);
4482 SaveAndRestore save_break(BreakJumpTarget);
4483
4484
4485
4486
4487 DefaultCaseBlock = SwitchSuccessor;
4488
4489
4490 SwitchTerminatedBlock = createBlock(false);
4491
4492
4493
4494 Succ = SwitchSuccessor;
4495 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4496
4497
4498
4499
4500 assert(Terminator->getBody() && "switch must contain a non-NULL body");
4501 Block = nullptr;
4502
4503
4504
4505 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered, false);
4506
4507
4508 assert(Terminator->getCond() && "switch condition must be non-NULL");
4509 Expr::EvalResult result;
4510 bool b = tryEvaluate(Terminator->getCond(), result);
4511 SaveAndRestore save_switchCond(switchCond, b ? &result : nullptr);
4512
4513
4514
4516 addLocalScopeAndDtors(Terminator->getBody());
4517
4518 addStmt(Terminator->getBody());
4520 if (badCFG)
4521 return nullptr;
4522 }
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532 bool SwitchAlwaysHasSuccessor = false;
4533 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4534 SwitchAlwaysHasSuccessor |=
4537 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4538 !SwitchAlwaysHasSuccessor);
4539
4540
4541 SwitchTerminatedBlock->setTerminator(Terminator);
4542 Block = SwitchTerminatedBlock;
4543 CFGBlock *LastBlock = addStmt(Terminator->getCond());
4544
4545
4546
4549 autoCreateBlock();
4551 LastBlock = addStmt(Init);
4552 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
4553 }
4554 }
4555
4556
4557 if (Stmt *Init = Terminator->getInit()) {
4558 autoCreateBlock();
4559 LastBlock = addStmt(Init);
4560 }
4561
4562 return LastBlock;
4563}
4564
4569 if (!switchCond)
4570 return true;
4571
4572 bool addCase = false;
4573
4574 if (!switchExclusivelyCovered) {
4575 if (switchCond->Val.isInt()) {
4576
4578 const llvm::APSInt &condInt = switchCond->Val.getInt();
4579
4580 if (condInt == lhsInt) {
4581 addCase = true;
4582 switchExclusivelyCovered = true;
4583 }
4584 else if (condInt > lhsInt) {
4585 if (const Expr *RHS = CS->getRHS()) {
4586
4588 if (V2 >= condInt) {
4589 addCase = true;
4590 switchExclusivelyCovered = true;
4591 }
4592 }
4593 }
4594 }
4595 else
4596 addCase = true;
4597 }
4598 return addCase;
4599}
4600
4601CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
4602
4603
4604 CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;
4605
4607
4608
4609
4611 CFGBlock *currentBlock = createBlock(false);
4613
4614 if (TopBlock)
4615 addSuccessor(LastBlock, currentBlock);
4616 else
4617 TopBlock = currentBlock;
4618
4619 addSuccessor(SwitchTerminatedBlock,
4620 shouldAddCase(switchExclusivelyCovered, switchCond,
4621 CS, *Context)
4622 ? currentBlock : nullptr);
4623
4624 LastBlock = currentBlock;
4627 }
4628
4629 addStmt(Sub);
4630 }
4631
4632 CFGBlock *CaseBlock = Block;
4633 if (!CaseBlock)
4634 CaseBlock = createBlock();
4635
4636
4637
4639
4640 if (badCFG)
4641 return nullptr;
4642
4643
4644
4645 assert(SwitchTerminatedBlock);
4646 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4647 shouldAddCase(switchExclusivelyCovered, switchCond,
4648 CS, *Context));
4649
4650
4651 Block = nullptr;
4652
4653 if (TopBlock) {
4654 addSuccessor(LastBlock, CaseBlock);
4655 Succ = TopBlock;
4656 } else {
4657
4658 Succ = CaseBlock;
4659 }
4660
4661 return Succ;
4662}
4663
4664CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
4667
4668 DefaultCaseBlock = Block;
4669
4670 if (!DefaultCaseBlock)
4671 DefaultCaseBlock = createBlock();
4672
4673
4674
4675 DefaultCaseBlock->setLabel(Terminator);
4676
4677 if (badCFG)
4678 return nullptr;
4679
4680
4681
4682
4683
4684
4685
4686
4687 Block = nullptr;
4688
4689
4690 Succ = DefaultCaseBlock;
4691
4692 return DefaultCaseBlock;
4693}
4694
4695CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
4696
4697
4698 CFGBlock *TrySuccessor = nullptr;
4699
4701 if (badCFG)
4702 return nullptr;
4703 TrySuccessor = Block;
4704 } else
4705 TrySuccessor = Succ;
4706
4707 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4708
4709
4710 CFGBlock *NewTryTerminatedBlock = createBlock(false);
4711
4712 NewTryTerminatedBlock->setTerminator(Terminator);
4713
4714 bool HasCatchAll = false;
4715 for (unsigned I = 0, E = Terminator->getNumHandlers(); I != E; ++I) {
4716
4717 Succ = TrySuccessor;
4718 CXXCatchStmt *CS = Terminator->getHandler(I);
4720 HasCatchAll = true;
4721 }
4722 Block = nullptr;
4723 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4724 if (!CatchBlock)
4725 return nullptr;
4726
4727
4728 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4729 }
4730 if (!HasCatchAll) {
4731 if (PrevTryTerminatedBlock)
4732 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4733 else
4734 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4735 }
4736
4737
4738 Succ = TrySuccessor;
4739
4740
4741 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4742 cfg->addTryDispatchBlock(TryTerminatedBlock);
4743
4744 assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
4745 Block = nullptr;
4746 return addStmt(Terminator->getTryBlock());
4747}
4748
4749CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
4750
4751
4752
4753
4754
4755 SaveAndRestore save_scope_pos(ScopePos);
4756
4757
4758
4760 LocalScope::const_iterator BeginScopePos = ScopePos;
4761 addLocalScopeForVarDecl(VD);
4762 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4763 }
4764
4767
4768 CFGBlock *CatchBlock = Block;
4769 if (!CatchBlock)
4770 CatchBlock = createBlock();
4771
4772
4773
4774
4775
4776 appendStmt(CatchBlock, CS);
4777
4778
4779
4781
4782
4783 if (badCFG)
4784 return nullptr;
4785
4786
4787 Block = nullptr;
4788
4789 return CatchBlock;
4790}
4791
4792CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807 SaveAndRestore save_scope_pos(ScopePos);
4808
4809
4811 addLocalScopeForStmt(Range);
4813 addLocalScopeForStmt(Begin);
4815 addLocalScopeForStmt(End);
4816 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4817
4818 LocalScope::const_iterator ContinueScopePos = ScopePos;
4819
4820
4821
4822 CFGBlock *LoopSuccessor = nullptr;
4824 if (badCFG)
4825 return nullptr;
4826 LoopSuccessor = Block;
4827 } else
4828 LoopSuccessor = Succ;
4829
4830
4831
4832 SaveAndRestore save_break(BreakJumpTarget);
4833 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4834
4835
4836 CFGBlock *ConditionBlock = createBlock(false);
4838
4839
4840 if (Expr *C = S->getCond()) {
4841 Block = ConditionBlock;
4842 CFGBlock *BeginConditionBlock = addStmt(C);
4843 if (badCFG)
4844 return nullptr;
4845 assert(BeginConditionBlock == ConditionBlock &&
4846 "condition block in for-range was unexpectedly complex");
4847 (void)BeginConditionBlock;
4848 }
4849
4850
4851
4852 Succ = ConditionBlock;
4853
4854
4855 TryResult KnownVal(true);
4856
4858 KnownVal = tryEvaluateBool(S->getCond());
4859
4860
4861 {
4863
4864
4865 SaveAndRestore save_Block(Block), save_Succ(Succ);
4866 SaveAndRestore save_continue(ContinueJumpTarget);
4867
4868
4869
4870 Block = nullptr;
4871 Succ = addStmt(S->getInc());
4872 if (badCFG)
4873 return nullptr;
4874 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4875
4876
4877
4878 ContinueJumpTarget.block->setLoopTarget(S);
4879
4880
4882 if (badCFG)
4883 return nullptr;
4884 Block = nullptr;
4885
4886
4888
4889
4890
4892 addLocalScopeAndDtors(S->getBody());
4893
4894
4896
4897 if (badCFG)
4898 return nullptr;
4899 CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
4900 if (badCFG)
4901 return nullptr;
4902
4903
4904 addSuccessor(ConditionBlock,
4905 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
4906 }
4907
4908
4909
4910 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4911
4912
4913 Block = createBlock();
4916 CFGBlock *Head = addStmt(S->getRangeStmt());
4918 Head = addStmt(S->getInit());
4919 return Head;
4920}
4921
4922CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
4923 AddStmtChoice asc, bool ExternallyDestructed) {
4925
4926
4927 TempDtorContext Context;
4928 VisitForTemporaryDtors(E->getSubExpr(), ExternallyDestructed, Context);
4929
4930
4931
4932 asc = asc.withAlwaysAdd(true);
4933 }
4935}
4936
4937CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
4938 AddStmtChoice asc) {
4939 if (asc.alwaysAdd(*this, E)) {
4940 autoCreateBlock();
4941 appendStmt(Block, E);
4942
4943 findConstructionContexts(
4946
4947
4948 asc = asc.withAlwaysAdd(false);
4949 }
4951}
4952
4953CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
4954 AddStmtChoice asc) {
4955
4956
4957
4958 findConstructionContextsForArguments(C);
4959 appendConstructor(C);
4960
4961 return VisitChildren(C);
4962}
4963
4964CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
4965 AddStmtChoice asc) {
4966 autoCreateBlock();
4967 appendStmt(Block, NE);
4968
4969 findConstructionContexts(
4971 const_cast<CXXConstructExpr *>(NE->getConstructExpr()));
4972
4973 if (NE->getInitializer())
4974 Block = Visit(NE->getInitializer());
4975
4977 appendNewAllocator(Block, NE);
4978
4979 if (NE->isArray() && *NE->getArraySize())
4980 Block = Visit(*NE->getArraySize());
4981
4983 E = NE->placement_arg_end(); I != E; ++I)
4984 Block = Visit(*I);
4985
4987}
4988
4989CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
4990 AddStmtChoice asc) {
4991 autoCreateBlock();
4992 appendStmt(Block, DE);
4994 if (!DTy.isNull()) {
4997 if (RD) {
4999 appendDeleteDtor(Block, RD, DE);
5000 }
5001 }
5002
5003 return VisitChildren(DE);
5004}
5005
5006CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
5007 AddStmtChoice asc) {
5008 if (asc.alwaysAdd(*this, E)) {
5009 autoCreateBlock();
5010 appendStmt(Block, E);
5011
5012 asc = asc.withAlwaysAdd(false);
5013 }
5015}
5016
5017CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
5018 AddStmtChoice asc) {
5019
5020
5021
5022 findConstructionContextsForArguments(E);
5023 appendConstructor(E);
5024
5025 return VisitChildren(E);
5026}
5027
5028CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
5029 AddStmtChoice asc) {
5030 if (asc.alwaysAdd(*this, E)) {
5031 autoCreateBlock();
5032 appendStmt(Block, E);
5033 }
5034
5035 if (E->getCastKind() == CK_IntegralToBoolean)
5037
5038 return Visit(E->getSubExpr(), AddStmtChoice());
5039}
5040
5041CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
5042 return Visit(E->getSubExpr(), AddStmtChoice());
5043}
5044
5045CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5046
5047 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
5048
5049 if (!IBlock) {
5050 IBlock = createBlock(false);
5051 cfg->setIndirectGotoBlock(IBlock);
5052 }
5053
5054
5055
5056 if (badCFG)
5057 return nullptr;
5058
5059 Block = createBlock(false);
5060 Block->setTerminator(I);
5061 addSuccessor(Block, IBlock);
5063}
5064
5065CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
5066 TempDtorContext &Context) {
5068
5069tryAgain:
5070 if (!E) {
5071 badCFG = true;
5072 return nullptr;
5073 }
5075 default:
5076 return VisitChildrenForTemporaryDtors(E, false, Context);
5077
5078 case Stmt::InitListExprClass:
5079 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
5080
5081 case Stmt::BinaryOperatorClass:
5083 ExternallyDestructed,
5084 Context);
5085
5086 case Stmt::CXXBindTemporaryExprClass:
5087 return VisitCXXBindTemporaryExprForTemporaryDtors(
5089
5090 case Stmt::BinaryConditionalOperatorClass:
5091 case Stmt::ConditionalOperatorClass:
5092 return VisitConditionalOperatorForTemporaryDtors(
5094
5095 case Stmt::ImplicitCastExprClass:
5096
5098 goto tryAgain;
5099
5100 case Stmt::CXXFunctionalCastExprClass:
5101
5103 goto tryAgain;
5104
5105 case Stmt::ConstantExprClass:
5107 goto tryAgain;
5108
5109 case Stmt::ParenExprClass:
5111 goto tryAgain;
5112
5113 case Stmt::MaterializeTemporaryExprClass: {
5116 SmallVector<const Expr *, 2> CommaLHSs;
5117 SmallVector<SubobjectAdjustment, 2> Adjustments;
5118
5119 E = const_cast<Expr *>(
5121 ->getSubExpr()
5122 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
5123
5124 for (const Expr *CommaLHS : CommaLHSs) {
5125 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
5126 false, Context);
5127 }
5128 goto tryAgain;
5129 }
5130
5131 case Stmt::BlockExprClass:
5132
5133
5135
5136 case Stmt::LambdaExprClass: {
5137
5138
5140 CFGBlock *B = Block;
5141 for (Expr *Init : LE->capture_inits()) {
5143 if (CFGBlock *R = VisitForTemporaryDtors(
5144 Init, true, Context))
5145 B = R;
5146 }
5147 }
5148 return B;
5149 }
5150
5151 case Stmt::StmtExprClass:
5152
5153
5155
5156 case Stmt::CXXDefaultArgExprClass:
5158 goto tryAgain;
5159
5160 case Stmt::CXXDefaultInitExprClass:
5162 goto tryAgain;
5163 }
5164}
5165
5166CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,
5167 bool ExternallyDestructed,
5168 TempDtorContext &Context) {
5170
5172 }
5173
5174
5175
5176
5177
5178 CFGBlock *B = Block;
5179 for (Stmt *Child : E->children())
5180 if (Child)
5181 if (CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
5182 B = R;
5183
5184 return B;
5185}
5186
5187CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
5188 BinaryOperator *E, bool ExternallyDestructed, TempDtorContext &Context) {
5190
5191
5192 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
5193 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), ExternallyDestructed, Context);
5194 return RHSBlock ? RHSBlock : LHSBlock;
5195 }
5196
5198 VisitForTemporaryDtors(E->getLHS(), false, Context);
5199 TryResult RHSExecuted = tryEvaluateBool(E->getLHS());
5200 if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)
5201 RHSExecuted.negate();
5202
5203
5204
5205
5206 TempDtorContext RHSContext(
5207 bothKnownTrue(Context.KnownExecuted, RHSExecuted));
5208 VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
5209 InsertTempDtorDecisionBlock(RHSContext);
5210
5212 }
5213
5215
5216
5217 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);
5218 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
5219 return LHSBlock ? LHSBlock : RHSBlock;
5220 }
5221
5222
5223 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
5224}
5225
5226CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5227 CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context) {
5228
5229
5230 CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), true, Context);
5231 if (!ExternallyDestructed) {
5232
5233
5234
5236
5238
5239
5240
5241
5242 if (B) Succ = B;
5243 Block = createNoReturnBlock();
5244 } else if (Context.needsTempDtorBranch()) {
5245
5246
5247 if (B) Succ = B;
5248 Block = createBlock();
5249 } else {
5250 autoCreateBlock();
5251 }
5252 if (Context.needsTempDtorBranch()) {
5253 Context.setDecisionPoint(Succ, E);
5254 }
5255 appendTemporaryDtor(Block, E);
5256
5258 }
5259 return B;
5260}
5261
5262void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
5263 CFGBlock *FalseSucc) {
5264 if (!Context.TerminatorExpr) {
5265
5266 return;
5267 }
5268 assert(Context.TerminatorExpr);
5269 CFGBlock *Decision = createBlock(false);
5270 Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,
5272 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
5273 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5274 !Context.KnownExecuted.isTrue());
5275 Block = Decision;
5276}
5277
5278CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
5279 AbstractConditionalOperator *E, bool ExternallyDestructed,
5280 TempDtorContext &Context) {
5281 VisitForTemporaryDtors(E->getCond(), false, Context);
5282 CFGBlock *ConditionBlock = Block;
5283 CFGBlock *ConditionSucc = Succ;
5284 TryResult ConditionVal = tryEvaluateBool(E->getCond());
5285 TryResult NegatedVal = ConditionVal;
5286 if (NegatedVal.isKnown()) NegatedVal.negate();
5287
5288 TempDtorContext TrueContext(
5289 bothKnownTrue(Context.KnownExecuted, ConditionVal));
5290 VisitForTemporaryDtors(E->getTrueExpr(), ExternallyDestructed, TrueContext);
5291 CFGBlock *TrueBlock = Block;
5292
5293 Block = ConditionBlock;
5294 Succ = ConditionSucc;
5295 TempDtorContext FalseContext(
5296 bothKnownTrue(Context.KnownExecuted, NegatedVal));
5297 VisitForTemporaryDtors(E->getFalseExpr(), ExternallyDestructed, FalseContext);
5298
5299 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5300 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
5301 } else if (TrueContext.TerminatorExpr) {
5302 Block = TrueBlock;
5303 InsertTempDtorDecisionBlock(TrueContext);
5304 } else {
5305 InsertTempDtorDecisionBlock(FalseContext);
5306 }
5308}
5309
5310CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
5311 AddStmtChoice asc) {
5312 if (asc.alwaysAdd(*this, D)) {
5313 autoCreateBlock();
5314 appendStmt(Block, D);
5315 }
5316
5317
5318 CFGBlock *B = Block;
5319
5320
5321
5322 SmallVector<Stmt *, 8> Used(
5323 OMPExecutableDirective::used_clauses_children(D->clauses()));
5324 for (Stmt *S : llvm::reverse(Used)) {
5325 assert(S && "Expected non-null used-in-clause child.");
5326 if (CFGBlock *R = Visit(S))
5327 B = R;
5328 }
5329
5330 if (!D->isStandaloneDirective()) {
5331 Stmt *S = D->getRawStmt();
5333 addLocalScopeAndDtors(S);
5334 if (CFGBlock *R = addStmt(S))
5335 B = R;
5336 }
5337
5338 return B;
5339}
5340
5341
5342
5343
5345 bool first_block = begin() == end();
5346
5347
5349 Blocks.push_back(Mem, BlkBVC);
5350
5351
5352 if (first_block)
5353 Entry = Exit = &back();
5354
5355
5356 return &back();
5357}
5358
5359
5362 CFGBuilder Builder(C, BO);
5363 return Builder.buildCFG(D, Statement);
5364}
5365
5367
5368
5369 if (size() <= 3)
5370 return true;
5371
5372
5373
5374
5377 while (B != Exit) {
5378 auto IteratorAndFlag = Visited.insert(B);
5379 if (!IteratorAndFlag.second) {
5380
5381 return false;
5382 }
5383
5384
5385 const CFGBlock *FirstReachableB = nullptr;
5387 if (!AB.isReachable())
5388 continue;
5389
5390 if (FirstReachableB == nullptr) {
5391 FirstReachableB = &*AB;
5392 } else {
5393
5394 return false;
5395 }
5396 }
5397
5398 if (!FirstReachableB) {
5399
5400 return true;
5401 }
5402
5403
5404 B = FirstReachableB;
5405 }
5406
5407
5408 return true;
5409}
5410
5424 llvm_unreachable("getDestructorDecl should only be used with "
5425 "ImplicitDtors");
5428 QualType ty = var->getType();
5429
5430
5431
5432
5433
5435 if (const Expr *Init = var->getInit()) {
5437 }
5438 }
5439
5441 ty = arrayType->getElementType();
5442 }
5443
5444
5445
5446
5447
5449 assert(classDecl);
5451 }
5459 }
5465 }
5469
5471 ty = arrayType->getElementType();
5472 }
5473
5475 assert(classDecl);
5477 }
5479
5480 return nullptr;
5481 }
5482 llvm_unreachable("getKind() returned bogus value");
5483}
5484
5485
5486
5487
5488
5490 : ReachableBlock(IsReachable ? B : nullptr),
5491 UnreachableBlock(!IsReachable ? B : nullptr,
5492 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5493
5495 : ReachableBlock(B),
5496 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
5497 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5498
5503
5505 UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);
5506
5507 Succs.push_back(Succ, C);
5508}
5509
5513 return true;
5514
5516
5517
5520 if (S->isAllEnumCasesCovered()) {
5523 return true;
5524 }
5525 }
5526 }
5527
5528 return false;
5529}
5530
5531
5532
5533
5534
5535namespace {
5536
5538 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5539 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5540
5541 StmtMapTy StmtMap;
5542 DeclMapTy DeclMap;
5543 signed currentBlock = 0;
5544 unsigned currStmt = 0;
5546
5547public:
5548 StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
5549 : LangOpts(LO) {
5550 if (!cfg)
5551 return;
5553 unsigned j = 1;
5554 for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
5555 BI != BEnd; ++BI, ++j ) {
5556 if (std::optional SE = BI->getAs()) {
5557 const Stmt *stmt= SE->getStmt();
5558 std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
5559 StmtMap[stmt] = P;
5560
5561 switch (stmt->getStmtClass()) {
5562 case Stmt::DeclStmtClass:
5563 DeclMap[cast(stmt)->getSingleDecl()] = P;
5564 break;
5565 case Stmt::IfStmtClass: {
5566 const VarDecl *var = cast(stmt)->getConditionVariable();
5567 if (var)
5568 DeclMap[var] = P;
5569 break;
5570 }
5571 case Stmt::ForStmtClass: {
5572 const VarDecl *var = cast(stmt)->getConditionVariable();
5573 if (var)
5574 DeclMap[var] = P;
5575 break;
5576 }
5577 case Stmt::WhileStmtClass: {
5578 const VarDecl *var =
5579 cast(stmt)->getConditionVariable();
5580 if (var)
5581 DeclMap[var] = P;
5582 break;
5583 }
5584 case Stmt::SwitchStmtClass: {
5585 const VarDecl *var =
5586 cast(stmt)->getConditionVariable();
5587 if (var)
5588 DeclMap[var] = P;
5589 break;
5590 }
5591 case Stmt::CXXCatchStmtClass: {
5592 const VarDecl *var =
5593 cast(stmt)->getExceptionDecl();
5594 if (var)
5595 DeclMap[var] = P;
5596 break;
5597 }
5598 default:
5599 break;
5600 }
5601 }
5602 }
5603 }
5604 }
5605
5606 ~StmtPrinterHelper() override = default;
5607
5608 const LangOptions &getLangOpts() const { return LangOpts; }
5609 void setBlockID(signed i) { currentBlock = i; }
5610 void setStmtID(unsigned i) { currStmt = i; }
5611
5612 bool handledStmt(Stmt *S, raw_ostream &OS) override {
5613 StmtMapTy::iterator I = StmtMap.find(S);
5614
5615 if (I == StmtMap.end())
5616 return false;
5617
5618 if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
5619 && I->second.second == currStmt) {
5620 return false;
5621 }
5622
5623 OS << "[B" << I->second.first << "." << I->second.second << "]";
5624 return true;
5625 }
5626
5627 bool handleDecl(const Decl *D, raw_ostream &OS) {
5628 DeclMapTy::iterator I = DeclMap.find(D);
5629
5630 if (I == DeclMap.end()) {
5631
5632
5633 if (auto *PVD = dyn_cast_or_null(D)) {
5634 OS << "[Parm: " << PVD->getNameAsString() << "]";
5635 return true;
5636 }
5637 return false;
5638 }
5639
5640 if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
5641 && I->second.second == currStmt) {
5642 return false;
5643 }
5644
5645 OS << "[B" << I->second.first << "." << I->second.second << "]";
5646 return true;
5647 }
5648};
5649
5650class CFGBlockTerminatorPrint
5651 : public StmtVisitor<CFGBlockTerminatorPrint,void> {
5652 raw_ostream &OS;
5653 StmtPrinterHelper* Helper;
5654 PrintingPolicy Policy;
5655
5656public:
5657 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5658 const PrintingPolicy &Policy)
5659 : OS(os), Helper(helper), Policy(Policy) {
5661 }
5662
5663 void VisitIfStmt(IfStmt *I) {
5664 OS << "if ";
5666 C->printPretty(OS, Helper, Policy);
5667 }
5668
5669
5670 void VisitStmt(Stmt *Terminator) {
5671 Terminator->printPretty(OS, Helper, Policy);
5672 }
5673
5674 void VisitDeclStmt(DeclStmt *DS) {
5676 OS << "static init " << VD->getName();
5677 }
5678
5679 void VisitForStmt(ForStmt *F) {
5680 OS << "for (" ;
5682 OS << "...";
5683 OS << "; ";
5685 C->printPretty(OS, Helper, Policy);
5686 OS << "; ";
5688 OS << "...";
5689 OS << ")";
5690 }
5691
5692 void VisitWhileStmt(WhileStmt *W) {
5693 OS << "while " ;
5695 C->printPretty(OS, Helper, Policy);
5696 }
5697
5698 void VisitDoStmt(DoStmt *D) {
5699 OS << "do ... while ";
5701 C->printPretty(OS, Helper, Policy);
5702 }
5703
5704 void VisitSwitchStmt(SwitchStmt *Terminator) {
5705 OS << "switch ";
5707 }
5708
5709 void VisitCXXTryStmt(CXXTryStmt *) { OS << "try ..."; }
5710
5711 void VisitObjCAtTryStmt(ObjCAtTryStmt *) { OS << "@try ..."; }
5712
5713 void VisitSEHTryStmt(SEHTryStmt *CS) { OS << "__try ..."; }
5714
5715 void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
5716 if (Stmt *Cond = C->getCond())
5718 OS << " ? ... : ...";
5719 }
5720
5721 void VisitChooseExpr(ChooseExpr *C) {
5722 OS << "__builtin_choose_expr( ";
5723 if (Stmt *Cond = C->getCond())
5725 OS << " )";
5726 }
5727
5728 void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5729 OS << "goto *";
5731 T->printPretty(OS, Helper, Policy);
5732 }
5733
5734 void VisitBinaryOperator(BinaryOperator* B) {
5736 VisitExpr(B);
5737 return;
5738 }
5739
5742
5744 case BO_LOr:
5745 OS << " || ...";
5746 return;
5747 case BO_LAnd:
5748 OS << " && ...";
5749 return;
5750 default:
5751 llvm_unreachable("Invalid logical operator.");
5752 }
5753 }
5754
5755 void VisitExpr(Expr *E) {
5757 }
5758
5759public:
5760 void print(CFGTerminator T) {
5761 switch (T.getKind()) {
5763 Visit(T.getStmt());
5764 break;
5766 OS << "(Temp Dtor) ";
5767 Visit(T.getStmt());
5768 break;
5770 OS << "(See if most derived ctor has already initialized vbases)";
5771 break;
5772 }
5773 }
5774};
5775
5776}
5777
5784 else
5786 OS << "(";
5789 OS << ")";
5790
5792 OS << " (Base initializer)";
5794 OS << " (Delegating initializer)";
5795 else
5796 OS << " (Member initializer)";
5797}
5798
5800 StmtPrinterHelper &Helper,
5803 switch (CC->getKind()) {
5805 OS << ", ";
5808 return;
5809 }
5811 OS << ", ";
5812 const auto *CICC =
5815 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5816 break;
5817 }
5820 Stmts.push_back(SDSCC->getDeclStmt());
5821 break;
5822 }
5825 Stmts.push_back(CDSCC->getDeclStmt());
5826 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5827 break;
5828 }
5831 Stmts.push_back(NECC->getCXXNewExpr());
5832 break;
5833 }
5836 Stmts.push_back(RSCC->getReturnStmt());
5837 break;
5838 }
5840 const auto *RSCC =
5842 Stmts.push_back(RSCC->getReturnStmt());
5843 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5844 break;
5845 }
5848 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5849 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5850 break;
5851 }
5854 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5855 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5856 Stmts.push_back(TOCC->getConstructorAfterElision());
5857 break;
5858 }
5861 Helper.handledStmt(const_cast<LambdaExpr *>(LCC->getLambdaExpr()), OS);
5862 OS << "+" << LCC->getIndex();
5863 return;
5864 }
5867 if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5868 OS << ", ";
5869 Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
5870 }
5871 OS << ", ";
5872 Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
5873 OS << "+" << ACC->getIndex();
5874 return;
5875 }
5876 }
5877 for (auto I: Stmts)
5878 if (I) {
5879 OS << ", ";
5880 Helper.handledStmt(const_cast<Stmt *>(I), OS);
5881 }
5882}
5883
5884static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5885 const CFGElement &E, bool TerminateWithNewLine = true);
5886
5888 bool TerminateWithNewLine) const {
5890 StmtPrinterHelper Helper(nullptr, LangOpts);
5891 print_elem(OS, Helper, *this, TerminateWithNewLine);
5892}
5893
5894static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5895 const CFGElement &E, bool TerminateWithNewLine) {
5902 assert(S != nullptr && "Expecting non-null Stmt");
5903
5904
5905 if (const StmtExpr *SE = dyn_cast(S)) {
5907
5908 auto Children = Sub->children();
5910 OS << "({ ... ; ";
5912 OS << " })";
5913 if (TerminateWithNewLine)
5914 OS << '\n';
5915 return;
5916 }
5917 }
5918
5919 if (const BinaryOperator* B = dyn_cast(S)) {
5920 if (B->getOpcode() == BO_Comma) {
5921 OS << "... , ";
5922 Helper.handledStmt(B->getRHS(),OS);
5923 if (TerminateWithNewLine)
5924 OS << '\n';
5925 return;
5926 }
5927 }
5928 S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
5929
5932 OS << " (OperatorCall)";
5933 OS << " (CXXRecordTypedCall";
5935 OS << ")";
5937 OS << " (OperatorCall)";
5939 OS << " (BindTemporary)";
5940 } else if (const CXXConstructExpr *CCE = dyn_cast(S)) {
5941 OS << " (CXXConstructExpr";
5944 }
5945 OS << ", " << CCE->getType() << ")";
5946 } else if (const CastExpr *CE = dyn_cast(S)) {
5947 OS << " (" << CE->getStmtClassName() << ", " << CE->getCastKindName()
5948 << ", " << CE->getType() << ")";
5949 }
5950
5951
5952 if (isa(S) && TerminateWithNewLine)
5953 OS << '\n';
5954
5955 return;
5956 }
5957
5960 break;
5961
5965 Helper.handleDecl(VD, OS);
5966
5968 if (T->isReferenceType())
5970
5971 OS << ".~";
5972 T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
5973 OS << "() (Implicit destructor)";
5974 break;
5975 }
5976
5978 OS << "CleanupFunction ("
5980 break;
5981
5984 OS << " (Lifetime ends)";
5985 break;
5986
5989 << " (LoopExit)";
5990 break;
5991
5993 OS << "CFGScopeBegin(";
5996 OS << ")";
5997 break;
5998
6000 OS << "CFGScopeEnd(";
6003 OS << ")";
6004 break;
6005
6007 OS << "CFGNewAllocator(";
6009 AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
6010 OS << ")";
6011 break;
6012
6016 if (!RD)
6017 return;
6021 OS << "->~" << RD->getName().str() << "()";
6022 OS << " (Implicit destructor)";
6023 break;
6024 }
6025
6029 OS << " (Base object destructor)";
6030 break;
6031 }
6032
6036 OS << "this->" << FD->getName();
6037 OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
6038 OS << " (Member object destructor)";
6039 break;
6040 }
6041
6045 OS << "~";
6047 OS << "() (Temporary object destructor)";
6048 break;
6049 }
6050 }
6051 if (TerminateWithNewLine)
6052 OS << '\n';
6053}
6054
6057 StmtPrinterHelper &Helper, bool print_edges,
6058 bool ShowColors) {
6060
6061
6062 if (ShowColors)
6063 OS.changeColor(raw_ostream::YELLOW, true);
6064
6066
6068 OS << " (ENTRY)]\n";
6069 else if (&B == &cfg->getExit())
6070 OS << " (EXIT)]\n";
6072 OS << " (INDIRECT GOTO DISPATCH)]\n";
6074 OS << " (NORETURN)]\n";
6075 else
6076 OS << "]\n";
6077
6078 if (ShowColors)
6079 OS.resetColor();
6080
6081
6083 if (print_edges)
6084 OS << " ";
6085
6089 OS << "case ";
6090 if (const Expr *LHS = C->getLHS())
6092 if (const Expr *RHS = C->getRHS()) {
6093 OS << " ... ";
6095 }
6097 OS << "default";
6099 OS << "catch (";
6101 ED->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);
6102 else
6103 OS << "...";
6104 OS << ")";
6106 OS << "@catch (";
6107 if (const VarDecl *PD = CS->getCatchParamDecl())
6108 PD->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);
6109 else
6110 OS << "...";
6111 OS << ")";
6113 OS << "__except (";
6116 OS << ")";
6117 } else
6118 llvm_unreachable("Invalid label statement in CFGBlock.");
6119
6120 OS << ":\n";
6121 }
6122
6123
6124 unsigned j = 1;
6125
6127 I != E ; ++I, ++j ) {
6128
6129 if (print_edges)
6130 OS << " ";
6131
6132 OS << llvm::format("%3d", j) << ": ";
6133
6134 Helper.setStmtID(j);
6135
6137 }
6138
6139
6141 if (ShowColors)
6142 OS.changeColor(raw_ostream::GREEN);
6143
6144 OS << " T: ";
6145
6146 Helper.setBlockID(-1);
6147
6149 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
6151 OS << '\n';
6152
6153 if (ShowColors)
6154 OS.resetColor();
6155 }
6156
6157 if (print_edges) {
6158
6160 const raw_ostream::Colors Color = raw_ostream::BLUE;
6161 if (ShowColors)
6162 OS.changeColor(Color);
6163 OS << " Preds " ;
6164 if (ShowColors)
6165 OS.resetColor();
6166 OS << '(' << B.pred_size() << "):";
6167 unsigned i = 0;
6168
6169 if (ShowColors)
6170 OS.changeColor(Color);
6171
6173 I != E; ++I, ++i) {
6174 if (i % 10 == 8)
6175 OS << "\n ";
6176
6178 bool Reachable = true;
6179 if (!B) {
6180 Reachable = false;
6181 B = I->getPossiblyUnreachableBlock();
6182 }
6183
6185 if (!Reachable)
6186 OS << "(Unreachable)";
6187 }
6188
6189 if (ShowColors)
6190 OS.resetColor();
6191
6192 OS << '\n';
6193 }
6194
6195
6197 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
6198 if (ShowColors)
6199 OS.changeColor(Color);
6200 OS << " Succs ";
6201 if (ShowColors)
6202 OS.resetColor();
6203 OS << '(' << B.succ_size() << "):";
6204 unsigned i = 0;
6205
6206 if (ShowColors)
6207 OS.changeColor(Color);
6208
6210 I != E; ++I, ++i) {
6211 if (i % 10 == 8)
6212 OS << "\n ";
6213
6215
6216 bool Reachable = true;
6217 if (!B) {
6218 Reachable = false;
6219 B = I->getPossiblyUnreachableBlock();
6220 }
6221
6222 if (B) {
6224 if (!Reachable)
6225 OS << "(Unreachable)";
6226 }
6227 else {
6228 OS << " NULL";
6229 }
6230 }
6231
6232 if (ShowColors)
6233 OS.resetColor();
6234 OS << '\n';
6235 }
6236 }
6237}
6238
6239
6241 print(llvm::errs(), LO, ShowColors);
6242}
6243
6244
6246 StmtPrinterHelper Helper(this, LO);
6247
6248
6250
6251
6252 for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
6253
6255 continue;
6256
6257 print_block(OS, this, **I, Helper, true, ShowColors);
6258 }
6259
6260
6262 OS << '\n';
6263 OS.flush();
6264}
6265
6269
6270
6272 bool ShowColors) const {
6273 print(llvm::errs(), cfg, LO, ShowColors);
6274}
6275
6279
6280
6281
6283 const LangOptions &LO, bool ShowColors) const {
6284 StmtPrinterHelper Helper(cfg, LO);
6285 print_block(OS, cfg, *this, Helper, true, ShowColors);
6286 OS << '\n';
6287}
6288
6289
6292 CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));
6294}
6295
6296
6298 bool AddQuotes) const {
6299 std::string Buf;
6300 llvm::raw_string_ostream TempOut(Buf);
6301
6303
6305}
6306
6307
6308
6309
6310
6311
6312
6315 return true;
6316
6317
6318
6319
6320
6321
6322
6323 if (llvm::any_of(*Blk, [](const CFGElement &Elm) {
6324 if (std::optional StmtElm = Elm.getAs<CFGStmt>())
6326 return true;
6327 return false;
6328 }))
6329 return true;
6330
6331 return false;
6332}
6333
6336
6337 const CFGBlock *StartBlk = this;
6339 return true;
6340
6343
6344 DFSWorkList.push_back(StartBlk);
6345 while (!DFSWorkList.empty()) {
6346 const CFGBlock *Blk = DFSWorkList.pop_back_val();
6347 Visited.insert(Blk);
6348
6349
6350
6351
6352
6353 if (Blk == &Cfg.getExit())
6354 return false;
6355
6356 for (const auto &Succ : Blk->succs()) {
6357 if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
6359
6360
6361 DFSWorkList.push_back(SuccBlk);
6362 }
6363 }
6364 }
6365 }
6366
6367
6368 return true;
6369}
6370
6372
6373
6375 return nullptr;
6376
6377
6378
6380 return nullptr;
6381
6382
6383 if (size() == 0)
6384 return nullptr;
6385
6387 if (!StmtElem)
6388 return nullptr;
6389
6390 const Stmt *Cond = StmtElem->getStmt();
6392 return nullptr;
6393
6394
6395
6397}
6398
6402 return nullptr;
6403
6404 Expr *E = nullptr;
6405
6406 switch (Terminator->getStmtClass()) {
6407 default:
6408 break;
6409
6410 case Stmt::CXXForRangeStmtClass:
6412 break;
6413
6414 case Stmt::ForStmtClass:
6416 break;
6417
6418 case Stmt::WhileStmtClass:
6420 break;
6421
6422 case Stmt::DoStmtClass:
6424 break;
6425
6426 case Stmt::IfStmtClass:
6428 break;
6429
6430 case Stmt::ChooseExprClass:
6432 break;
6433
6434 case Stmt::IndirectGotoStmtClass:
6436 break;
6437
6438 case Stmt::SwitchStmtClass:
6440 break;
6441
6442 case Stmt::BinaryConditionalOperatorClass:
6444 break;
6445
6446 case Stmt::ConditionalOperatorClass:
6448 break;
6449
6450 case Stmt::BinaryOperatorClass:
6452 break;
6453
6454 case Stmt::ObjCForCollectionStmtClass:
6456 }
6457
6458 if (!StripParens)
6459 return E;
6460
6462}
6463
6464
6465
6466
6467
6469
6471 StmtPrinterHelper H(this, LO);
6473 llvm::ViewGraph(this,"CFG");
6475}
6476
6477namespace llvm {
6478
6479template<>
6482
6484 std::string OutStr;
6485 llvm::raw_string_ostream Out(OutStr);
6487
6488 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
6489
6490
6491 for (unsigned i = 0; i != OutStr.length(); ++i)
6492 if (OutStr[i] == '\n') {
6493 OutStr[i] = '\\';
6494 OutStr.insert(OutStr.begin()+i+1, 'l');
6495 }
6496
6497 return OutStr;
6498 }
6499};
6500
6501}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static StmtPrinterHelper * GraphHelper
Definition CFG.cpp:6468
static bool isCXXAssumeAttr(const AttributedStmt *A)
Definition CFG.cpp:2578
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E, bool TerminateWithNewLine=true)
Definition CFG.cpp:5894
static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXCtorInitializer *I)
Definition CFG.cpp:5778
static SourceLocation GetEndLoc(Decl *D)
Definition CFG.cpp:66
static bool isBuiltinAssumeWithSideEffects(const ASTContext &Ctx, const CallExpr *CE)
Definition CFG.cpp:2803
static bool CanThrow(Expr *E, ASTContext &Ctx)
Definition CFG.cpp:2788
static bool isFallthroughStatement(const AttributedStmt *A)
Definition CFG.cpp:2571
static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)
Definition CFG.cpp:6055
static bool isImmediateSinkBlock(const CFGBlock *Blk)
Definition CFG.cpp:6313
static const Expr * tryTransformToLiteralConstant(const Expr *E)
Helper for tryNormalizeBinaryOperator.
Definition CFG.cpp:102
static QualType getReferenceInitTemporaryType(const Expr *Init, bool *FoundMTE=nullptr)
Retrieve the type of the temporary object whose lifetime was extended by a local reference with the g...
Definition CFG.cpp:1862
static const VariableArrayType * FindVA(const Type *t)
Definition CFG.cpp:1501
static std::tuple< const Expr *, BinaryOperatorKind, const Expr * > tryNormalizeBinaryOperator(const BinaryOperator *B)
Tries to interpret a binary operator into Expr Op NumExpr form, if NumExpr is an integer literal or a...
Definition CFG.cpp:117
static bool IsLiteralConstantExpr(const Expr *E)
Returns true on constant values based around a single IntegerLiteral, CharacterLiteral,...
Definition CFG.cpp:77
static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC)
Definition CFG.cpp:5799
static bool shouldAddCase(bool &switchExclusivelyCovered, const Expr::EvalResult *switchCond, const CaseStmt *CS, ASTContext &Ctx)
Definition CFG.cpp:4565
static bool areExprTypesCompatible(const Expr *E1, const Expr *E2)
For an expression x == Foo && x == Bar, this determines whether the Foo and Bar are either of the sam...
Definition CFG.cpp:147
static TryResult bothKnownTrue(TryResult R1, TryResult R2)
Definition CFG.cpp:422
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the ExceptionSpecificationType enumeration and various utility functions.
Defines the clang::Expr interface and subclasses for C++ expressions.
SmallVector< AnnotatedLine *, 1 > Children
If this token starts a block, this contains all the unwrapped lines in it.
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
llvm::APInt getValue() const
ValueKind getKind() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const LangOptions & getLangOpts() const
int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const
Compare the rank of two floating point types as above, but compare equal if both types have the same ...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType BoundMemberTy
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
LabelDecl * getLabel() const
Represents a loop initializing the elements of an array.
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isLogicalOp(Opcode Opc)
static bool isRelationalOp(Opcode Opc)
static bool isCommaOp(Opcode Opc)
static bool isAssignmentOp(Opcode Opc)
static bool isEqualityOp(Opcode Opc)
ArrayRef< Capture > captures() const
const BlockDecl * getBlockDecl() const
void push_back(const_reference Elt, BumpVectorContext &C)
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
Represents C++ object destructor implicitly generated for base object in destructor.
This class represents a potential adjacent block in the CFG.
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Definition CFG.cpp:5489
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
unsigned IgnoreNullPredecessors
unsigned IgnoreDefaultsWithCoveredEnums
Represents a single basic block in a source-level CFG.
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
Definition CFG.cpp:6290
void setLoopTarget(const Stmt *loopTarget)
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
Definition CFG.cpp:6334
size_t getIndexInCFG() const
Definition CFG.cpp:6266
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Definition CFG.cpp:5510
reverse_iterator rbegin()
void setTerminator(CFGTerminator Term)
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)
void print(raw_ostream &OS, const CFG *cfg, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFGBlock that outputs to an ostream.
Definition CFG.cpp:6282
ElementList::const_iterator const_iterator
bool hasNoReturnElement() const
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const
printTerminatorJson - Pretty-prints the terminator in JSON format.
Definition CFG.cpp:6297
void dump() const
Definition CFG.cpp:6276
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
Stmt * Label
An (optional) label that prefixes the executable statements in the block.
CFGTerminator getTerminator() const
succ_iterator succ_begin()
Stmt * getTerminatorStmt()
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
AdjacentBlocks::const_iterator const_pred_iterator
unsigned pred_size() const
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
pred_iterator pred_begin()
void appendCleanupFunction(const VarDecl *VD, BumpVectorContext &C)
void setLabel(Stmt *Statement)
unsigned getBlockID() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
void setHasNoReturnElement()
const Expr * getLastCondition() const
Definition CFG.cpp:6371
Stmt * getTerminatorCondition(bool StripParens=true)
Definition CFG.cpp:6399
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
Definition CFG.cpp:5499
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
AdjacentBlocks::const_iterator const_succ_iterator
CFGTerminator Terminator
The terminator for a basic block that indicates the type of control-flow that occurs between a block ...
unsigned succ_size() const
Represents a function call that returns a C++ object by value.
static bool isCXXRecordTypedCall(const Expr *E)
Returns true when call expression CE needs to be represented by CFGCXXRecordTypedCall,...
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
virtual void compareBitwiseOr(const BinaryOperator *B)
Represents C++ constructor call.
Represents C++ object destructor generated from a call to delete.
const CXXDeleteExpr * getDeleteExpr() const
const CXXRecordDecl * getCXXRecordDecl() const
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
void dumpToStream(llvm::raw_ostream &OS, bool TerminateWithNewLine=true) const
Definition CFG.cpp:5887
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Definition CFG.cpp:5412
Represents C++ base or member initializer from constructor's initialization list.
CXXCtorInitializer * getInitializer() const
Represents the point where the lifetime of an automatic object ends.
const VarDecl * getVarDecl() const
Represents the point where a loop ends.
Represents C++ object destructor implicitly generated for member object in destructor.
Represents C++ allocator call.
const CXXNewExpr * getAllocatorExpr() const
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt.
const VarDecl * getVarDecl() const
Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...
const VarDecl * getVarDecl() const
const Stmt * getStmt() const
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
@ TemporaryDtorsBranch
A branch in control flow of destructors of temporaries.
@ VirtualBaseBranch
A shortcut around virtual base initializers.
@ StmtBranch
A branch that corresponds to a statement in the code, such as an if-statement.
bool PruneTriviallyFalseEdges
bool AddStaticInitBranches
bool OmitImplicitValueInitializers
ForcedBlkExprs ** forcedBlkExprs
bool AddCXXDefaultInitExprInAggregates
bool AddCXXDefaultInitExprInCtors
bool AssumeReachableDefaultInSwitchStatements
bool alwaysAdd(const Stmt *stmt) const
bool AddRichCXXConstructors
bool AddVirtualBaseBranches
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
bool MarkElidedCXXConstructors
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
CFGBlockListTy::const_iterator const_iterator
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFG that outputs to an ostream.
Definition CFG.cpp:6245
bool isLinear() const
Returns true if the CFG has no branches.
Definition CFG.cpp:5366
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
Definition CFG.cpp:5360
llvm::BumpPtrAllocator & getAllocator()
CFGBlock * createBlock()
Create a new block in the CFG.
Definition CFG.cpp:5344
CFGBlock * getIndirectGotoBlock()
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
Definition CFG.cpp:6240
void viewCFG(const LangOptions &LO) const
Definition CFG.cpp:6470
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
const Expr * getSubExpr() const
CXXCatchStmt - This represents a C++ catch block.
Stmt * getHandlerBlock() const
VarDecl * getExceptionDecl() const
Represents a call to a C++ constructor.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Represents a C++ base or member initializer.
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
Expr * getInit() const
Get the initializer.
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
FieldDecl * getAnyMember() const
Represents a delete expression for memory deallocation and destructor calls, e.g.
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents a C++ destructor within a class.
DeclStmt * getBeginStmt()
DeclStmt * getLoopVarStmt()
DeclStmt * getRangeStmt()
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
ExprIterator arg_iterator
Represents a C++ struct/union/class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
base_class_range vbases()
bool hasDefinition() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
bool isAnyDestructorNoReturn() const
Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn.
Represents a C++ temporary.
const CXXDestructorDecl * getDestructor() const
CXXCatchStmt * getHandler(unsigned i)
unsigned getNumHandlers() const
CompoundStmt * getTryBlock()
bool isPotentiallyEvaluated() const
Determine whether this typeid has a type operand which is potentially evaluated, per C++11 [expr....
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
CaseStmt - Represent a case statement.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
CompoundStmt - This represents a group of statements like { stmt stmt }.
reverse_body_iterator body_rbegin()
@ ElidableConstructorKind
static const ConstructionContextLayer * create(BumpVectorContext &C, const ConstructionContextItem &Item, const ConstructionContextLayer *Parent=nullptr)
const ConstructionContextItem & getItem() const
ConstructionContext's subclasses describe different ways of constructing an object in C++.
static const ConstructionContext * createFromLayers(BumpVectorContext &C, const ConstructionContextLayer *TopLayer)
Consume the construction context layer, together with its parent layers, and wrap it up into a comple...
@ CXX17ElidedCopyVariableKind
@ ElidedTemporaryObjectKind
@ SimpleTemporaryObjectKind
@ CXX17ElidedCopyConstructorInitializerKind
@ SimpleConstructorInitializerKind
@ SimpleReturnedValueKind
@ CXX17ElidedCopyReturnedValueKind
Expr * getOperand() const
Retrieve the operand of the 'co_return' statement.
Expr * getPromiseCall() const
Retrieve the promise call that results from this 'co_return' statement.
Expr * getReadyExpr() const
Expr * getResumeExpr() const
Expr * getSuspendExpr() const
Expr * getCommonExpr() const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
std::reverse_iterator< decl_iterator > reverse_decl_iterator
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
decl_iterator decl_begin()
const Decl * getSingleDecl() const
reverse_decl_iterator decl_rend()
reverse_decl_iterator decl_rbegin()
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
SourceLocation getLocation() const
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
static QualType findBoundMemberType(const Expr *expr)
Given an expression of bound-member type, find the type of the member.
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool isKnownToHaveBooleanValue(bool Semantic=true) const
isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...
Represents a member of a struct/union/class.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
DeclStmt * getConditionVariableDeclStmt()
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
const Expr * getSubExpr() const
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
LabelDecl * getLabel() const
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
unsigned getNumInits() const
Expr ** getInits()
Retrieve the set of initializers.
LabelStmt - Represents a label, which has a substatement.
LabelDecl * getDecl() const
const char * getName() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Expr ** capture_init_iterator
Iterator that walks over the capture initialization arguments.
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument for this lambda expression.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getQualifiedNameAsString() const
Represents Objective-C's @catch statement.
const Stmt * getCatchBody() const
const Expr * getSynchExpr() const
const CompoundStmt * getSynchBody() const
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
const Stmt * getTryBody() const
Retrieve the @try body.
catch_range catch_stmts()
const Stmt * getSubStmt() const
unsigned getNumSemanticExprs() const
Expr * getSemanticExpr(unsigned index)
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
field_range fields() const
CompoundStmt * getBlock() const
Expr * getFilterExpr() const
CompoundStmt * getBlock() const
CompoundStmt * getTryBlock() const
SEHFinallyStmt * getFinallyHandler() const
SEHExceptStmt * getExceptHandler() const
Returns 0 if not defined.
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
CompoundStmt * getSubStmt()
Stmt - This represents one statement.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
StmtClass getStmtClass() const
const char * getStmtClassName() const
SwitchStmt - This represents a 'switch' stmt.
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SwitchCase * getSwitchCaseList()
DeclStmt * getConditionVariableDeclStmt()
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
bool isBlockPointerType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isFunctionPointerType() const
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs'.
QualType getArgumentType() const
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
Expr * getSubExpr() const
Represents a variable declaration or definition.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Represents a C array with a specified size that is not an integer-constant-expression.
DeclStmt * getConditionVariableDeclStmt()
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool Sub(InterpState &S, CodePtr OpPC)
bool NE(InterpState &S, CodePtr OpPC)
bool LE(InterpState &S, CodePtr OpPC)
bool Cast(InterpState &S, CodePtr OpPC)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool hasSpecificAttr(const Container &container)
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SD_FullExpression
Full-expression storage duration (for temporaries).
@ Result
The result type of a method or function.
const FunctionProtoType * T
std::string JsonFormat(StringRef RawSR, bool AddQuotes)
@ Type
The name was classified as a type.
bool operator!=(CanQual< T > x, CanQual< U > y)
U cast(CodeGen::Address addr)
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
Definition CFG.cpp:1448
Diagnostic wrappers for TextAPI types for error reporting.
float __ovld __cnfn distance(float, float)
Returns the distance between p0 and p1.
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
Describes how types, statements, expressions, and declarations should be printed.
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
DOTGraphTraits(bool isSimple=false)
Definition CFG.cpp:6481
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)
Definition CFG.cpp:6483