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/TimeProfiler.h"
56#include "llvm/Support/raw_ostream.h"
70 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
71 if (
Expr *Ex = VD->getInit())
72 return Ex->getSourceRange().getEnd();
86 if (
const auto *CE = dyn_cast<CastExpr>(E)) {
87 if (CE->getCastKind() != CK_IntegralCast &&
88 CE->getCastKind() != CK_IntegralToFloating)
94 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
95 if (UO->getOpcode() != UO_Minus)
119static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
126 if (Constant ==
nullptr) {
130 else if (Op == BO_GE)
132 else if (Op == BO_LT)
134 else if (Op == BO_LE)
141 return std::make_tuple(MaybeDecl, Op, Constant);
192 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
194 AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
196 bool alwaysAdd(CFGBuilder &builder,
197 const Stmt *
stmt)
const;
201 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
202 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
232 using AutomaticVarsTy = BumpVector<VarDecl *>;
236 class const_iterator {
237 const LocalScope* Scope =
nullptr;
241 unsigned VarIter = 0;
247 const_iterator() =
default;
251 const_iterator(
const LocalScope& S,
unsigned I)
252 : Scope(&S), VarIter(I) {
255 if (VarIter == 0 && Scope)
259 VarDecl *
const* operator->()
const {
260 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
261 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
262 return &Scope->Vars[VarIter - 1];
265 const VarDecl *getFirstVarInScope()
const {
266 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
267 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
268 return Scope->Vars[0];
272 return *this->operator->();
275 const_iterator &operator++() {
279 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
285 const_iterator operator++(
int) {
286 const_iterator P = *
this;
291 bool operator==(
const const_iterator &rhs)
const {
292 return Scope == rhs.Scope && VarIter == rhs.VarIter;
294 bool operator!=(
const const_iterator &rhs)
const {
295 return !(*
this == rhs);
298 explicit operator bool()
const {
299 return *
this != const_iterator();
303 const_iterator shared_parent(const_iterator L);
304 bool pointsToFirstDeclaredVar() {
return VarIter == 1; }
305 bool inSameLocalScope(const_iterator rhs) {
return Scope == rhs.Scope; }
309 BumpVectorContext ctx;
312 AutomaticVarsTy Vars;
320 LocalScope(BumpVectorContext ctx, const_iterator P)
321 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
324 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
326 void addVar(VarDecl *VD) {
327 Vars.push_back(VD, ctx);
336int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
338 const_iterator F = *
this;
339 while (F.Scope != L.Scope) {
340 assert(F != const_iterator() &&
341 "L iterator is not reachable from F iterator.");
345 D += F.VarIter - L.VarIter;
353LocalScope::const_iterator
354LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
357 if ((*
this == const_iterator()) || (L == const_iterator())) {
358 return const_iterator();
361 const_iterator F = *
this;
362 if (F.inSameLocalScope(L)) {
364 F.VarIter = std::min(F.VarIter, L.VarIter);
368 llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;
370 ScopesOfL.try_emplace(L.Scope, L.VarIter);
371 if (L == const_iterator())
377 if (
auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {
379 F.VarIter = std::min(F.VarIter, LIt->getSecond());
382 assert(F != const_iterator() &&
383 "L iterator is not reachable from F iterator.");
393struct BlockScopePosPair {
394 CFGBlock *block =
nullptr;
395 LocalScope::const_iterator scopePosition;
397 BlockScopePosPair() =
default;
398 BlockScopePosPair(CFGBlock *
b, LocalScope::const_iterator scopePos)
399 : block(
b), scopePosition(scopePos) {}
410 TryResult() =
default;
411 TryResult(
bool b) :
X(
b ? 1 : 0) {}
413 bool isTrue()
const {
return X == 1; }
414 bool isFalse()
const {
return X == 0; }
415 bool isKnown()
const {
return X >= 0; }
426 if (!R1.isKnown() || !R2.isKnown())
428 return TryResult(R1.isTrue() && R2.isTrue());
433class reverse_children {
434 llvm::SmallVector<Stmt *, 12> childrenBuf;
438 reverse_children(Stmt *S, ASTContext &Ctx);
440 using iterator = ArrayRef<Stmt *>::reverse_iterator;
442 iterator begin()
const {
return children.rbegin(); }
443 iterator end()
const {
return children.rend(); }
448reverse_children::reverse_children(Stmt *S, ASTContext &Ctx) {
449 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
456 case Stmt::InitListExprClass: {
463 case Stmt::AttributedStmtClass: {
469 for (
const auto *Attr : AS->getAttrs()) {
470 if (
const auto *AssumeAttr = dyn_cast<CXXAssumeAttr>(Attr)) {
471 Expr *AssumeExpr = AssumeAttr->getAssumption();
473 childrenBuf.push_back(AssumeExpr);
480 llvm::append_range(childrenBuf, AS->children());
489 llvm::append_range(childrenBuf, S->
children());
511 using JumpTarget = BlockScopePosPair;
512 using JumpSource = BlockScopePosPair;
515 std::unique_ptr<CFG> cfg;
518 CFGBlock *
Block =
nullptr;
521 CFGBlock *Succ =
nullptr;
523 JumpTarget ContinueJumpTarget;
524 JumpTarget BreakJumpTarget;
525 JumpTarget SEHLeaveJumpTarget;
526 CFGBlock *SwitchTerminatedBlock =
nullptr;
527 CFGBlock *DefaultCaseBlock =
nullptr;
533 CFGBlock *TryTerminatedBlock =
nullptr;
536 LocalScope::const_iterator ScopePos;
539 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
544 using BackpatchBlocksTy = std::vector<JumpSource>;
545 BackpatchBlocksTy BackpatchBlocks;
548 using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
549 LabelSetTy AddressTakenLabels;
554 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
555 ConstructionContextMap;
558 const CFG::BuildOptions &BuildOpts;
561 bool switchExclusivelyCovered =
false;
562 Expr::EvalResult *switchCond =
nullptr;
564 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
565 const Stmt *lastLookup =
nullptr;
569 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
570 CachedBoolEvalsTy CachedBoolEvals;
573 explicit CFGBuilder(ASTContext *astContext,
574 const CFG::BuildOptions &buildOpts)
575 : Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}
578 std::unique_ptr<CFG> buildCFG(
const Decl *D, Stmt *Statement);
580 bool alwaysAdd(
const Stmt *
stmt);
584 CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
585 CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
586 CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
587 CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
588 CFGBlock *VisitBreakStmt(BreakStmt *B);
589 CFGBlock *VisitCallExpr(CallExpr *
C, AddStmtChoice asc);
590 CFGBlock *VisitCaseStmt(CaseStmt *
C);
591 CFGBlock *VisitChooseExpr(ChooseExpr *
C, AddStmtChoice asc);
592 CFGBlock *VisitCompoundStmt(
CompoundStmt *
C,
bool ExternallyDestructed);
593 CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *
C,
595 CFGBlock *VisitContinueStmt(ContinueStmt *
C);
596 CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
598 CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
599 CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *
C, AddStmtChoice asc);
600 CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
601 CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
602 CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
603 CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
605 CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *
C,
607 CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
608 CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
609 CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);
610 CFGBlock *VisitDeclStmt(DeclStmt *DS);
611 CFGBlock *VisitDeclSubExpr(DeclStmt *DS);
612 CFGBlock *VisitDefaultStmt(DefaultStmt *D);
613 CFGBlock *VisitDoStmt(DoStmt *D);
614 CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,
615 AddStmtChoice asc,
bool ExternallyDestructed);
616 CFGBlock *VisitForStmt(ForStmt *F);
617 CFGBlock *VisitGotoStmt(GotoStmt *G);
618 CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);
619 CFGBlock *VisitIfStmt(IfStmt *I);
620 CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
621 CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);
622 CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
623 CFGBlock *VisitLabelStmt(LabelStmt *L);
624 CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
625 CFGBlock *VisitLambdaExpr(
LambdaExpr *E, AddStmtChoice asc);
626 CFGBlock *VisitLogicalOperator(BinaryOperator *B);
627 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
630 CFGBlock *FalseBlock);
631 CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
633 CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
634 CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
635 CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
636 CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
637 CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
638 CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
639 CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
640 CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
641 CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
642 CFGBlock *VisitReturnStmt(Stmt *S);
643 CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,
645 CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
646 CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
647 CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
648 CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);
649 CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
650 CFGBlock *VisitSwitchStmt(SwitchStmt *S);
651 CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
653 CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
654 CFGBlock *VisitWhileStmt(WhileStmt *W);
655 CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);
657 CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
658 bool ExternallyDestructed =
false);
659 CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
660 CFGBlock *VisitChildren(Stmt *S);
661 CFGBlock *VisitCallExprChildren(CallExpr *
C);
662 CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
663 CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,
666 void maybeAddScopeBeginForVarDecl(CFGBlock *B,
const VarDecl *VD,
668 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
669 appendScopeBegin(B, VD, S);
700 struct TempDtorContext {
701 TempDtorContext() =
default;
702 TempDtorContext(TryResult KnownExecuted)
703 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
710 bool needsTempDtorBranch()
const {
711 return IsConditional && !TerminatorExpr;
716 void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {
721 void track(
const MaterializeTemporaryExpr *MTE) {
722 CollectedMTEs.push_back(MTE);
725 const bool IsConditional =
false;
726 SmallVector<const MaterializeTemporaryExpr *, 5> CollectedMTEs;
727 const TryResult KnownExecuted =
true;
728 CFGBlock *Succ =
nullptr;
729 CXXBindTemporaryExpr *TerminatorExpr =
nullptr;
734 CFGBlock *VisitForTemporaries(Stmt *E,
bool ExternallyDestructed,
735 TempDtorContext &Context);
736 CFGBlock *VisitChildrenForTemporaries(Stmt *E,
bool ExternallyDestructed,
737 TempDtorContext &Context);
738 CFGBlock *VisitBinaryOperatorForTemporaries(BinaryOperator *E,
739 bool ExternallyDestructed,
740 TempDtorContext &Context);
741 CFGBlock *VisitCXXOperatorCallExprForTemporaryDtors(CXXOperatorCallExpr *E,
742 TempDtorContext &Context);
743 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
744 CXXBindTemporaryExpr *E,
bool ExternallyDestructed, TempDtorContext &Context);
746 VisitConditionalOperatorForTemporaries(AbstractConditionalOperator *E,
747 bool ExternallyDestructed,
748 TempDtorContext &Context);
749 void InsertTempDecisionBlock(
const TempDtorContext &Context,
750 CFGBlock *FalseSucc =
nullptr);
760 void consumeConstructionContext(
const ConstructionContextLayer *Layer,
768 void findConstructionContexts(
const ConstructionContextLayer *Layer,
774 template <
typename CallLikeExpr,
775 typename = std::enable_if_t<
776 std::is_base_of_v<CallExpr, CallLikeExpr> ||
777 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
778 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
779 void findConstructionContextsForArguments(CallLikeExpr *E) {
780 for (
unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
781 Expr *Arg = E->getArg(i);
783 findConstructionContexts(
785 ConstructionContextItem(E, i)),
793 void cleanupConstructionContext(Expr *E);
795 void autoCreateBlock() {
if (!
Block)
Block = createBlock(); }
797 CFGBlock *createBlock(
bool add_successor =
true);
798 CFGBlock *createNoReturnBlock();
800 CFGBlock *addStmt(Stmt *S) {
801 return Visit(S, AddStmtChoice::AlwaysAdd);
804 CFGBlock *addInitializer(CXXCtorInitializer *I);
805 void addLoopExit(
const Stmt *LoopStmt);
806 void addAutomaticObjHandling(LocalScope::const_iterator B,
807 LocalScope::const_iterator E, Stmt *S);
808 void addAutomaticObjDestruction(LocalScope::const_iterator B,
809 LocalScope::const_iterator E, Stmt *S);
810 void addScopeExitHandling(LocalScope::const_iterator B,
811 LocalScope::const_iterator E, Stmt *S);
812 void addImplicitDtorsForDestructor(
const CXXDestructorDecl *DD);
813 void addScopeChangesHandling(LocalScope::const_iterator SrcPos,
814 LocalScope::const_iterator DstPos,
816 void addFullExprCleanupMarker(TempDtorContext &Context);
817 CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,
819 LocalScope::const_iterator DstPost,
823 LocalScope* createOrReuseLocalScope(LocalScope* Scope);
825 void addLocalScopeForStmt(Stmt *S);
826 LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
827 LocalScope* Scope =
nullptr);
828 LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope =
nullptr);
830 void addLocalScopeAndDtors(Stmt *S);
832 const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {
836 const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);
840 cleanupConstructionContext(E);
847 void appendStmt(CFGBlock *B,
const Stmt *S) {
848 if (alwaysAdd(S) && cachedEntry)
849 cachedEntry->second = B;
853 B->
appendStmt(
const_cast<Stmt*
>(S), cfg->getBumpVectorContext());
856 void appendConstructor(CXXConstructExpr *CE) {
858 if (
C &&
C->isNoReturn())
859 Block = createNoReturnBlock();
863 if (
const ConstructionContext *CC =
864 retrieveAndCleanupConstructionContext(CE)) {
865 Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());
870 Block->appendStmt(CE, cfg->getBumpVectorContext());
873 void appendCall(CFGBlock *B, CallExpr *CE) {
874 if (alwaysAdd(CE) && cachedEntry)
875 cachedEntry->second = B;
877 if (
const ConstructionContext *CC =
878 retrieveAndCleanupConstructionContext(CE)) {
884 B->
appendStmt(CE, cfg->getBumpVectorContext());
887 void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
891 void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
895 void appendBaseDtor(CFGBlock *B,
const CXXBaseSpecifier *BS) {
899 void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
903 void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {
904 if (alwaysAdd(ME) && cachedEntry)
905 cachedEntry->second = B;
907 if (
const ConstructionContext *CC =
908 retrieveAndCleanupConstructionContext(ME)) {
913 B->
appendStmt(ME, cfg->getBumpVectorContext());
916 void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
920 void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
924 void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {
928 void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
932 void appendLoopExit(CFGBlock *B,
const Stmt *LoopStmt) {
936 void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
940 void addSuccessor(CFGBlock *B, CFGBlock *S,
bool IsReachable =
true) {
941 B->
addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
942 cfg->getBumpVectorContext());
947 void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
948 B->
addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
949 cfg->getBumpVectorContext());
952 void appendScopeBegin(CFGBlock *B,
const VarDecl *VD,
const Stmt *S) {
957 void appendScopeEnd(CFGBlock *B,
const VarDecl *VD,
const Stmt *S) {
965 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
969 const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
970 const Expr *BoolExpr = RHSExpr;
971 bool IntFirst =
true;
973 IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
981 llvm::APInt IntValue = IntLiteral->
getValue();
982 if ((IntValue == 1) || (IntValue == 0))
986 !IntValue.isNegative();
989 if (Bok == BO_GT || Bok == BO_GE) {
992 return TryResult(IntFirst == IntLarger);
996 return TryResult(IntFirst != IntLarger);
1004 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
1008 std::optional<llvm::APInt> IntLiteral1 =
1009 getIntegerLiteralSubexpressionValue(LHSExpr);
1010 const Expr *BoolExpr = RHSExpr;
1013 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
1020 const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);
1021 if (BitOp && (BitOp->
getOpcode() == BO_And ||
1026 std::optional<llvm::APInt> IntLiteral2 =
1027 getIntegerLiteralSubexpressionValue(LHSExpr2);
1030 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
1036 (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
1038 (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1042 return TryResult(B->
getOpcode() != BO_EQ);
1045 if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1048 return TryResult(B->
getOpcode() != BO_EQ);
1060 std::optional<llvm::APInt>
1061 getIntegerLiteralSubexpressionValue(
const Expr *E) {
1064 if (
const auto *UnOp = dyn_cast<UnaryOperator>(E->
IgnoreParens())) {
1067 const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();
1069 if (
const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1074 switch (UnOp->getOpcode()) {
1084 assert(
false &&
"Unexpected unary operator!");
1085 return std::nullopt;
1088 }
else if (
const auto *IntLiteral =
1092 return std::nullopt;
1095 template <
typename APFloatOrInt>
1097 const APFloatOrInt &Value1,
1098 const APFloatOrInt &Value2) {
1103 return TryResult(Value1 == Value2);
1105 return TryResult(Value1 != Value2);
1107 return TryResult(Value1 < Value2);
1109 return TryResult(Value1 <= Value2);
1111 return TryResult(Value1 > Value2);
1113 return TryResult(Value1 >= Value2);
1124 TryResult checkIncorrectLogicOperator(
const BinaryOperator *B) {
1129 auto CheckLogicalOpWithNegatedVariable = [
this, B](
const Expr *E1,
1131 if (
const auto *Negate = dyn_cast<UnaryOperator>(E1)) {
1132 if (Negate->getOpcode() == UO_LNot &&
1134 bool AlwaysTrue = B->
getOpcode() == BO_LOr;
1137 return TryResult(AlwaysTrue);
1143 TryResult
Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);
1146 Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);
1150 const auto *LHS = dyn_cast<BinaryOperator>(LHSExpr);
1151 const auto *RHS = dyn_cast<BinaryOperator>(RHSExpr);
1155 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1158 const Expr *DeclExpr1;
1159 const Expr *NumExpr1;
1163 if (!DeclExpr1 || !NumExpr1)
1166 const Expr *DeclExpr2;
1167 const Expr *NumExpr2;
1171 if (!DeclExpr2 || !NumExpr2)
1184 Expr::EvalResult L1Result, L2Result;
1199 auto AnalyzeConditions = [&](
const auto &Values,
1202 bool AlwaysTrue =
true, AlwaysFalse =
true;
1205 bool LHSAlwaysTrue =
true, LHSAlwaysFalse =
true;
1206 bool RHSAlwaysTrue =
true, RHSAlwaysFalse =
true;
1208 for (
const auto &
Value : Values) {
1210 analyzeLogicOperatorCondition(*BO1,
Value, Values[1] );
1212 analyzeLogicOperatorCondition(*BO2,
Value, Values[3] );
1214 if (!Res1.isKnown() || !Res2.isKnown())
1217 const bool IsAnd = B->
getOpcode() == BO_LAnd;
1218 const bool Combine = IsAnd ? (Res1.isTrue() && Res2.isTrue())
1219 : (Res1.isTrue() || Res2.isTrue());
1221 AlwaysTrue &= Combine;
1222 AlwaysFalse &= !Combine;
1224 LHSAlwaysTrue &= Res1.isTrue();
1225 LHSAlwaysFalse &= Res1.isFalse();
1226 RHSAlwaysTrue &= Res2.isTrue();
1227 RHSAlwaysFalse &= Res2.isFalse();
1230 if (AlwaysTrue || AlwaysFalse) {
1231 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1232 !RHSAlwaysFalse && BuildOpts.
Observer) {
1235 return TryResult(AlwaysTrue);
1243 llvm::APSInt L1 = L1Result.
Val.
getInt();
1244 llvm::APSInt L2 = L2Result.
Val.
getInt();
1247 if (L1.isSigned() != L2.isSigned() ||
1248 L1.getBitWidth() != L2.getBitWidth())
1253 const llvm::APSInt Values[] = {
1255 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1259 ((L1 < L2) ? L1 : L2) +
1260 llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1), L1.isUnsigned()),
1264 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1267 return AnalyzeConditions(Values, &BO1, &BO2);
1286 if (llvm::APFloat::opOK !=
1287 L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1290 }
else if (Order < 0)
1292 if (llvm::APFloat::opOK !=
1293 L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1297 llvm::APFloat MidValue = L1;
1298 MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven);
1299 MidValue.divide(llvm::APFloat(MidValue.getSemantics(),
"2.0"),
1300 llvm::APFloat::rmNearestTiesToEven);
1302 const llvm::APFloat Values[] = {
1303 llvm::APFloat::getSmallest(L1.getSemantics(),
true), L1, MidValue, L2,
1304 llvm::APFloat::getLargest(L2.getSemantics(),
false),
1307 return AnalyzeConditions(Values, &BO1, &BO2);
1314 TryResult checkIncorrectBitwiseOrOperator(
const BinaryOperator *B) {
1315 const Expr *LHSConstant =
1317 const Expr *RHSConstant =
1320 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1323 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1329 if (
Result.Val.getInt() == 0)
1335 return TryResult(
true);
1339 bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
1349 TryResult tryEvaluateBool(Expr *S) {
1354 if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
1355 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1357 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1358 if (I != CachedBoolEvals.end())
1362 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
1363 CachedBoolEvals[S] =
Result;
1367 switch (Bop->getOpcode()) {
1375 Expr::EvalResult LHSResult;
1376 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1377 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1378 if (!IntVal.getBoolValue()) {
1379 return TryResult(
false);
1382 Expr::EvalResult RHSResult;
1383 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1384 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1385 if (!IntVal.getBoolValue()) {
1386 return TryResult(
false);
1395 return evaluateAsBooleanConditionNoCache(S);
1399 TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
1400 if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
1401 if (Bop->isLogicalOp()) {
1402 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1403 if (LHS.isKnown()) {
1406 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1407 return LHS.isTrue();
1409 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1410 if (RHS.isKnown()) {
1411 if (Bop->getOpcode() == BO_LOr)
1412 return LHS.isTrue() || RHS.isTrue();
1414 return LHS.isTrue() && RHS.isTrue();
1417 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1418 if (RHS.isKnown()) {
1421 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1422 return RHS.isTrue();
1424 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1425 if (BopRes.isKnown())
1426 return BopRes.isTrue();
1431 }
else if (Bop->isEqualityOp()) {
1432 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1433 if (BopRes.isKnown())
1434 return BopRes.isTrue();
1435 }
else if (Bop->isRelationalOp()) {
1436 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1437 if (BopRes.isKnown())
1438 return BopRes.isTrue();
1439 }
else if (Bop->getOpcode() == BO_Or) {
1440 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1441 if (BopRes.isKnown())
1442 return BopRes.isTrue();
1453 bool hasTrivialDestructor(
const VarDecl *VD)
const;
1454 bool needsAutomaticDestruction(
const VarDecl *VD)
const;
1465 while (
const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1466 AILEInit = E->getSubExpr();
1471inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1473 return builder.alwaysAdd(
stmt) ||
kind == AlwaysAdd;
1476bool CFGBuilder::alwaysAdd(
const Stmt *
stmt) {
1482 if (lastLookup ==
stmt) {
1484 assert(cachedEntry->first ==
stmt);
1497 assert(!cachedEntry);
1501 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(
stmt);
1502 if (itr == fb->end()) {
1503 cachedEntry =
nullptr;
1507 cachedEntry = &*itr;
1514 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1516 if (vat->getSizeExpr())
1519 t = vt->getElementType().getTypePtr();
1525void CFGBuilder::consumeConstructionContext(
1526 const ConstructionContextLayer *Layer, Expr *E) {
1529 if (
const ConstructionContextLayer *PreviouslyStoredLayer =
1530 ConstructionContextMap.lookup(E)) {
1531 (void)PreviouslyStoredLayer;
1534 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1535 "Already within a different construction context!");
1537 ConstructionContextMap[E] = Layer;
1541void CFGBuilder::findConstructionContexts(
1542 const ConstructionContextLayer *Layer, Stmt *Child) {
1549 auto withExtraLayer = [
this, Layer](
const ConstructionContextItem &Item) {
1554 switch(Child->getStmtClass()) {
1555 case Stmt::CXXConstructExprClass:
1556 case Stmt::CXXTemporaryObjectExprClass: {
1560 findConstructionContexts(withExtraLayer(CE), CE->
getArg(0));
1563 consumeConstructionContext(Layer, CE);
1569 case Stmt::CallExprClass:
1570 case Stmt::CXXMemberCallExprClass:
1571 case Stmt::CXXOperatorCallExprClass:
1572 case Stmt::UserDefinedLiteralClass:
1573 case Stmt::ObjCMessageExprClass: {
1576 consumeConstructionContext(Layer, E);
1579 case Stmt::ExprWithCleanupsClass: {
1581 findConstructionContexts(Layer, Cleanups->getSubExpr());
1584 case Stmt::CXXFunctionalCastExprClass: {
1586 findConstructionContexts(Layer,
Cast->getSubExpr());
1589 case Stmt::ImplicitCastExprClass: {
1592 switch (
Cast->getCastKind()) {
1594 case CK_ConstructorConversion:
1595 findConstructionContexts(Layer,
Cast->getSubExpr());
1602 case Stmt::CXXBindTemporaryExprClass: {
1604 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1607 case Stmt::MaterializeTemporaryExprClass: {
1615 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1619 case Stmt::ConditionalOperatorClass: {
1627 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1631 findConstructionContexts(Layer, CO->getLHS());
1632 findConstructionContexts(Layer, CO->getRHS());
1635 case Stmt::InitListExprClass: {
1637 if (ILE->isTransparent()) {
1638 findConstructionContexts(Layer, ILE->getInit(0));
1644 case Stmt::ParenExprClass: {
1648 findConstructionContexts(Layer, PE->getSubExpr());
1656void CFGBuilder::cleanupConstructionContext(Expr *E) {
1658 "We should not be managing construction contexts!");
1659 assert(ConstructionContextMap.count(E) &&
1660 "Cannot exit construction context without the context!");
1661 ConstructionContextMap.erase(E);
1669std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D, Stmt *Statement) {
1677 Succ = createBlock();
1678 assert(Succ == &cfg->getExit());
1683 LocalScope *paramScope =
nullptr;
1684 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
1685 for (ParmVarDecl *PD : FD->parameters()) {
1686 paramScope = addLocalScopeForVarDecl(PD, paramScope);
1688 if (
auto *
C = dyn_cast<CompoundStmt>(Statement))
1692 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(),
1696 if (
const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
1697 addImplicitDtorsForDestructor(DD);
1700 CFGBlock *B = addStmt(Statement);
1717 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1718 CFGBlock *VBaseSucc =
nullptr;
1719 for (
auto *I : llvm::reverse(CD->inits())) {
1721 I->isBaseInitializer() && I->isBaseVirtual()) {
1725 VBaseSucc = Succ = B ? B : &cfg->getExit();
1726 Block = createBlock();
1728 B = addInitializer(I);
1738 addSuccessor(B,
Block,
true);
1747 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1748 E = BackpatchBlocks.end(); I != E; ++I ) {
1750 CFGBlock *B = I->block;
1752 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1755 if (LI == LabelMap.end())
1757 JumpTarget JT = LI->second;
1759 CFGBlock *SuccBlk = createScopeChangesHandlingBlock(
1760 I->scopePosition, B, JT.scopePosition, JT.block);
1761 addSuccessor(B, SuccBlk);
1762 }
else if (
auto *G = dyn_cast<GCCAsmStmt>(B->
getTerminator())) {
1763 CFGBlock *Successor = (I+1)->block;
1764 for (
auto *L : G->labels()) {
1765 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1768 if (LI == LabelMap.end())
1770 JumpTarget JT = LI->second;
1772 if (JT.block == Successor)
1774 addSuccessor(B, JT.block);
1781 if (CFGBlock *B = cfg->getIndirectGotoBlock())
1782 for (LabelDecl *LD : AddressTakenLabels) {
1784 LabelMapTy::iterator LI = LabelMap.find(LD);
1788 if (LI == LabelMap.end())
continue;
1790 addSuccessor(B, LI->second.block);
1794 cfg->setEntry(createBlock());
1797 assert(ConstructionContextMap.empty() &&
1798 "Not all construction contexts were cleaned up!");
1800 return std::move(cfg);
1805CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1806 CFGBlock *B = cfg->createBlock();
1807 if (add_successor && Succ)
1808 addSuccessor(B, Succ);
1815CFGBlock *CFGBuilder::createNoReturnBlock() {
1816 CFGBlock *B = createBlock(
false);
1818 addSuccessor(B, &cfg->getExit(), Succ);
1823CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
1827 bool HasTemporaries =
false;
1835 if (HasTemporaries &&
1838 TempDtorContext Context;
1842 addFullExprCleanupMarker(Context);
1847 appendInitializer(
Block, I);
1853 dyn_cast<ArrayInitLoopExpr>(
Init));
1855 findConstructionContexts(
1857 AILEInit ? AILEInit :
Init);
1859 if (HasTemporaries) {
1865 if (CXXDefaultInitExpr *
Default = dyn_cast<CXXDefaultInitExpr>(
Init)) {
1871 if (Stmt *Child =
Default->getExpr())
1872 if (CFGBlock *R = Visit(Child))
1886 bool *FoundMTE =
nullptr) {
1893 Init = EWC->getSubExpr();
1899 = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
1900 Init = MTE->getSubExpr();
1907 const Expr *SkippedInit =
Init->skipRValueSubobjectAdjustments();
1908 if (SkippedInit !=
Init) {
1916 return Init->getType();
1921void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1925 appendLoopExit(
Block, LoopStmt);
1933void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1934 LocalScope::const_iterator E,
1944 if (B.inSameLocalScope(E)) {
1945 addAutomaticObjDestruction(B, E, S);
1950 SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;
1951 LocalScopeEndMarkers.push_back(B);
1952 for (LocalScope::const_iterator I = B; I != E; ++I) {
1953 if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
1954 LocalScopeEndMarkers.push_back(I);
1956 LocalScopeEndMarkers.push_back(E);
1960 std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
1962 llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
1963 for (
auto [E, B] : Pairwise) {
1964 if (!B.inSameLocalScope(E))
1965 addScopeExitHandling(B, E, S);
1966 addAutomaticObjDestruction(B, E, S);
1973void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
1974 LocalScope::const_iterator E,
1982 SmallVector<VarDecl *, 10> DeclsNeedDestruction;
1983 DeclsNeedDestruction.reserve(B.distance(E));
1985 for (VarDecl* D : llvm::make_range(B, E))
1986 if (needsAutomaticDestruction(D))
1987 DeclsNeedDestruction.push_back(D);
1989 for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
2002 Block = createNoReturnBlock();
2011 appendLifetimeEnds(
Block, VD, S);
2013 appendAutomaticObjDtor(
Block, VD, S);
2014 if (VD->
hasAttr<CleanupAttr>())
2015 appendCleanupFunction(
Block, VD);
2024void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
2025 LocalScope::const_iterator E, Stmt *S) {
2026 assert(!B.inSameLocalScope(E));
2032 appendScopeEnd(
Block, B.getFirstVarInScope(), S);
2039 SmallVector<VarDecl *, 10> DeclsTrivial;
2040 DeclsTrivial.reserve(B.distance(E));
2045 for (VarDecl* D : llvm::make_range(B, E))
2046 if (!needsAutomaticDestruction(D))
2047 DeclsTrivial.push_back(D);
2049 if (DeclsTrivial.empty())
2053 for (VarDecl *VD : llvm::reverse(DeclsTrivial))
2054 appendLifetimeEnds(
Block, VD, S);
2062void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
2063 LocalScope::const_iterator DstPos,
2065 assert(
Block &&
"Source block should be always crated");
2071 if (SrcPos == DstPos)
2076 LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
2079 if (BuildOpts.
AddScopes && !DstPos.inSameLocalScope(BasePos)) {
2080 for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
2081 if (I.pointsToFirstDeclaredVar())
2082 appendScopeBegin(
Block, *I, S);
2087 addAutomaticObjHandling(SrcPos, BasePos, S);
2090void CFGBuilder::addFullExprCleanupMarker(TempDtorContext &Context) {
2092 BumpVectorContext &BVC = cfg->getBumpVectorContext();
2094 size_t NumCollected = Context.CollectedMTEs.size();
2095 if (NumCollected > 0) {
2097 ExpiringMTEs =
new (cfg->getAllocator())
2099 for (
const MaterializeTemporaryExpr *MTE : Context.CollectedMTEs)
2101 Block->appendFullExprCleanup(ExpiringMTEs, BVC);
2110CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
2111 LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,
2112 LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {
2113 if (SrcPos == DstPos)
2117 (!BuildOpts.
AddScopes || SrcPos.inSameLocalScope(DstPos)))
2122 SaveAndRestore save_Block(
Block), save_Succ(Succ);
2125 Block = createBlock(
false);
2128 addSuccessor(
Block, DstBlk);
2131 addScopeChangesHandling(SrcPos, DstPos,
Block->getTerminatorStmt());
2133 assert(
Block &&
"There should be at least one scope changing Block");
2139void CFGBuilder::addImplicitDtorsForDestructor(
const CXXDestructorDecl *DD) {
2141 "Can be called only when dtors should be added");
2142 const CXXRecordDecl *RD = DD->
getParent();
2145 for (
const auto &VI : RD->
vbases()) {
2149 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2152 appendBaseDtor(
Block, &VI);
2157 for (
const auto &BI : RD->
bases()) {
2158 if (!BI.isVirtual()) {
2159 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2162 appendBaseDtor(
Block, &BI);
2170 for (
auto *FI : RD->
fields()) {
2172 QualType QT = FI->getType();
2175 if (AT->isZeroSize())
2177 QT = AT->getElementType();
2183 appendMemberDtor(
Block, FI);
2190LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
2193 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
2194 return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);
2199void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
2204 LocalScope *Scope =
nullptr;
2208 for (
auto *BI : CS->body()) {
2209 Stmt *SI = BI->stripLabelLikeStatements();
2210 if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2211 Scope = addLocalScopeForDeclStmt(DS, Scope);
2219 addLocalScopeForDeclStmt(DS);
2224LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
2225 LocalScope* Scope) {
2230 for (
auto *DI : DS->
decls())
2231 if (VarDecl *VD = dyn_cast<VarDecl>(DI))
2232 Scope = addLocalScopeForVarDecl(VD, Scope);
2236bool CFGBuilder::needsAutomaticDestruction(
const VarDecl *VD)
const {
2237 return !hasTrivialDestructor(VD) || VD->
hasAttr<CleanupAttr>();
2240bool CFGBuilder::hasTrivialDestructor(
const VarDecl *VD)
const {
2261 bool FoundMTE =
false;
2269 if (AT->isZeroSize())
2271 QT = AT->getElementType();
2283LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
2284 LocalScope* Scope) {
2299 !needsAutomaticDestruction(VD)) {
2305 Scope = createOrReuseLocalScope(Scope);
2307 ScopePos = Scope->begin();
2313void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
2314 LocalScope::const_iterator scopeBeginPos = ScopePos;
2315 addLocalScopeForStmt(S);
2316 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2322CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2323 bool ExternallyDestructed) {
2329 if (Expr *E = dyn_cast<Expr>(S))
2330 S = E->IgnoreParens();
2333 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2334 return VisitOMPExecutableDirective(D, asc);
2338 return VisitStmt(S, asc);
2340 case Stmt::ImplicitValueInitExprClass:
2343 return VisitStmt(S, asc);
2345 case Stmt::InitListExprClass:
2348 case Stmt::AttributedStmtClass:
2351 case Stmt::AddrLabelExprClass:
2354 case Stmt::BinaryConditionalOperatorClass:
2357 case Stmt::BinaryOperatorClass:
2360 case Stmt::BlockExprClass:
2363 case Stmt::BreakStmtClass:
2366 case Stmt::CallExprClass:
2367 case Stmt::CXXOperatorCallExprClass:
2368 case Stmt::CXXMemberCallExprClass:
2369 case Stmt::UserDefinedLiteralClass:
2372 case Stmt::CaseStmtClass:
2375 case Stmt::ChooseExprClass:
2378 case Stmt::CompoundStmtClass:
2381 case Stmt::ConditionalOperatorClass:
2384 case Stmt::ContinueStmtClass:
2387 case Stmt::CXXCatchStmtClass:
2390 case Stmt::ExprWithCleanupsClass:
2392 asc, ExternallyDestructed);
2394 case Stmt::CXXDefaultArgExprClass:
2395 case Stmt::CXXDefaultInitExprClass:
2404 return VisitStmt(S, asc);
2406 case Stmt::CXXBindTemporaryExprClass:
2409 case Stmt::CXXConstructExprClass:
2412 case Stmt::CXXNewExprClass:
2415 case Stmt::CXXDeleteExprClass:
2418 case Stmt::CXXFunctionalCastExprClass:
2421 case Stmt::CXXTemporaryObjectExprClass:
2424 case Stmt::CXXThrowExprClass:
2427 case Stmt::CXXTryStmtClass:
2430 case Stmt::CXXTypeidExprClass:
2433 case Stmt::CXXForRangeStmtClass:
2436 case Stmt::DeclStmtClass:
2439 case Stmt::DefaultStmtClass:
2442 case Stmt::DoStmtClass:
2445 case Stmt::ForStmtClass:
2448 case Stmt::GotoStmtClass:
2451 case Stmt::GCCAsmStmtClass:
2454 case Stmt::IfStmtClass:
2457 case Stmt::ImplicitCastExprClass:
2460 case Stmt::ConstantExprClass:
2463 case Stmt::IndirectGotoStmtClass:
2466 case Stmt::LabelStmtClass:
2469 case Stmt::LambdaExprClass:
2472 case Stmt::MaterializeTemporaryExprClass:
2476 case Stmt::MemberExprClass:
2479 case Stmt::NullStmtClass:
2482 case Stmt::ObjCAtCatchStmtClass:
2485 case Stmt::ObjCAutoreleasePoolStmtClass:
2488 case Stmt::ObjCAtSynchronizedStmtClass:
2491 case Stmt::ObjCAtThrowStmtClass:
2494 case Stmt::ObjCAtTryStmtClass:
2497 case Stmt::ObjCForCollectionStmtClass:
2500 case Stmt::ObjCMessageExprClass:
2503 case Stmt::OpaqueValueExprClass:
2506 case Stmt::PseudoObjectExprClass:
2509 case Stmt::ReturnStmtClass:
2510 case Stmt::CoreturnStmtClass:
2511 return VisitReturnStmt(S);
2513 case Stmt::CoyieldExprClass:
2514 case Stmt::CoawaitExprClass:
2517 case Stmt::SEHExceptStmtClass:
2520 case Stmt::SEHFinallyStmtClass:
2523 case Stmt::SEHLeaveStmtClass:
2526 case Stmt::SEHTryStmtClass:
2529 case Stmt::UnaryExprOrTypeTraitExprClass:
2533 case Stmt::StmtExprClass:
2536 case Stmt::SwitchStmtClass:
2539 case Stmt::UnaryOperatorClass:
2542 case Stmt::WhileStmtClass:
2545 case Stmt::ArrayInitLoopExprClass:
2550CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
2551 if (asc.alwaysAdd(*
this, S)) {
2553 appendStmt(
Block, S);
2556 return VisitChildren(S);
2560CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
2561 CFGBlock *B =
Block;
2565 reverse_children RChildren(S, *Context);
2566 for (Stmt *Child : RChildren) {
2568 if (CFGBlock *R = Visit(Child))
2574CFGBlock *CFGBuilder::VisitCallExprChildren(CallExpr *
C) {
2578 if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
C);
2579 OCE && OCE->isAssignmentOp()) {
2580 Visit(OCE->getArg(0));
2581 Visit(OCE->getArg(1));
2582 return Visit(OCE->getCallee());
2584 return VisitChildren(
C);
2587CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
2588 if (asc.alwaysAdd(*
this, ILE)) {
2590 appendStmt(
Block, ILE);
2592 CFGBlock *B =
Block;
2594 reverse_children RChildren(ILE, *Context);
2595 for (Stmt *Child : RChildren) {
2598 if (CFGBlock *R = Visit(Child))
2601 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2602 if (Stmt *Child = DIE->getExpr())
2603 if (CFGBlock *R = Visit(Child))
2610CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
2611 AddStmtChoice asc) {
2612 AddressTakenLabels.insert(A->
getLabel());
2614 if (asc.alwaysAdd(*
this, A)) {
2616 appendStmt(
Block, A);
2625 "expected fallthrough not to have children");
2626 return isFallthrough;
2633 "expected [[assume]] not to have children");
2634 return hasAssumeAttr;
2637CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
2638 AddStmtChoice asc) {
2648 if (isInterestingAttribute && asc.alwaysAdd(*
this, A)) {
2650 appendStmt(
Block, A);
2653 return VisitChildren(A);
2656CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {
2657 if (asc.alwaysAdd(*
this, U)) {
2659 appendStmt(
Block, U);
2665 return Visit(U->
getSubExpr(), AddStmtChoice());
2668CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
2669 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
2670 appendStmt(ConfluenceBlock, B);
2675 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2676 ConfluenceBlock).first;
2679std::pair<CFGBlock*, CFGBlock*>
2680CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
2682 CFGBlock *TrueBlock,
2683 CFGBlock *FalseBlock) {
2688 CFGBlock *RHSBlock, *ExitBlock;
2691 if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
2692 if (B_RHS->isLogicalOp()) {
2693 std::tie(RHSBlock, ExitBlock) =
2694 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2702 ExitBlock = RHSBlock = createBlock(
false);
2707 TryResult KnownVal = tryEvaluateBool(RHS);
2708 if (!KnownVal.isKnown())
2709 KnownVal = tryEvaluateBool(B);
2712 assert(TrueBlock == FalseBlock);
2713 addSuccessor(RHSBlock, TrueBlock);
2717 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2718 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2722 RHSBlock = addStmt(RHS);
2727 return std::make_pair(
nullptr,
nullptr);
2732 if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
2733 if (B_LHS->isLogicalOp()) {
2735 FalseBlock = RHSBlock;
2737 TrueBlock = RHSBlock;
2742 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2747 CFGBlock *LHSBlock = createBlock(
false);
2751 CFGBlock *EntryLHSBlock = addStmt(LHS);
2754 return std::make_pair(
nullptr,
nullptr);
2757 TryResult KnownVal = tryEvaluateBool(LHS);
2761 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2762 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2765 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2766 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2769 return std::make_pair(EntryLHSBlock, ExitBlock);
2772CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
2773 AddStmtChoice asc) {
2776 return VisitLogicalOperator(B);
2780 appendStmt(
Block, B);
2782 return addStmt(B->
getLHS());
2786 if (asc.alwaysAdd(*
this, B)) {
2788 appendStmt(
Block, B);
2791 return Visit(B->
getRHS());
2794 if (asc.alwaysAdd(*
this, B)) {
2796 appendStmt(
Block, B);
2802 CFGBlock *RBlock = Visit(B->
getRHS());
2803 CFGBlock *LBlock = Visit(B->
getLHS());
2807 return (LBlock ? LBlock : RBlock);
2810CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
2811 if (asc.alwaysAdd(*
this, E)) {
2813 appendStmt(
Block, E);
2818CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
2825 Block = createBlock(
false);
2826 Block->setTerminator(B);
2830 if (BreakJumpTarget.block) {
2831 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2832 addSuccessor(
Block, BreakJumpTarget.block);
2857 if (BuiltinID != Builtin::BI__assume &&
2858 BuiltinID != Builtin::BI__builtin_assume)
2864CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *
C, AddStmtChoice asc) {
2866 QualType calleeType =
C->getCallee()->getType();
2872 if (!boundType.
isNull()) calleeType = boundType;
2878 bool AddEHEdge =
false;
2888 bool OmitArguments =
false;
2890 if (FunctionDecl *FD =
C->getDirectCallee()) {
2895 if (!FD->isVariadic())
2896 findConstructionContextsForArguments(
C);
2898 if (FD->isNoReturn() || FD->isAnalyzerNoReturn() ||
2899 C->isBuiltinAssumeFalse(*Context))
2901 if (FD->
hasAttr<NoThrowAttr>())
2904 FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2905 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2906 OmitArguments =
true;
2909 if (!
CanThrow(
C->getCallee(), *Context))
2912 if (OmitArguments) {
2913 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2914 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2917 return Visit(
C->getCallee());
2920 if (!NoReturn && !AddEHEdge) {
2924 return VisitCallExprChildren(
C);
2934 Block = createNoReturnBlock();
2936 Block = createBlock();
2942 if (TryTerminatedBlock)
2943 addSuccessor(
Block, TryTerminatedBlock);
2945 addSuccessor(
Block, &cfg->getExit());
2948 return VisitCallExprChildren(
C);
2951CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *
C,
2952 AddStmtChoice asc) {
2953 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
2954 appendStmt(ConfluenceBlock,
C);
2958 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2959 Succ = ConfluenceBlock;
2961 CFGBlock *LHSBlock = Visit(
C->getLHS(), alwaysAdd);
2965 Succ = ConfluenceBlock;
2967 CFGBlock *RHSBlock = Visit(
C->getRHS(), alwaysAdd);
2971 Block = createBlock(
false);
2973 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2974 addSuccessor(
Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2975 addSuccessor(
Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2977 return addStmt(
C->getCond());
2981 bool ExternallyDestructed) {
2982 LocalScope::const_iterator scopeBeginPos = ScopePos;
2983 addLocalScopeForStmt(
C);
2988 addAutomaticObjHandling(ScopePos, scopeBeginPos,
C);
2991 CFGBlock *LastBlock =
Block;
2993 for (Stmt *S : llvm::reverse(
C->body())) {
2996 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2997 ExternallyDestructed);
3000 LastBlock = newBlock;
3005 ExternallyDestructed =
false;
3011CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *
C,
3012 AddStmtChoice asc) {
3013 const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(
C);
3014 const OpaqueValueExpr *opaqueValue = (BCO ? BCO->
getOpaqueValue() :
nullptr);
3018 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
3019 appendStmt(ConfluenceBlock,
C);
3023 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
3029 Succ = ConfluenceBlock;
3031 CFGBlock *LHSBlock =
nullptr;
3032 const Expr *trueExpr =
C->getTrueExpr();
3033 if (trueExpr != opaqueValue) {
3034 LHSBlock = Visit(
C->getTrueExpr(), alwaysAdd);
3040 LHSBlock = ConfluenceBlock;
3043 Succ = ConfluenceBlock;
3044 CFGBlock *RHSBlock = Visit(
C->getFalseExpr(), alwaysAdd);
3049 if (BinaryOperator *
Cond =
3050 dyn_cast<BinaryOperator>(
C->getCond()->IgnoreParens()))
3051 if (
Cond->isLogicalOp())
3052 return VisitLogicalOperator(
Cond,
C, LHSBlock, RHSBlock).first;
3055 Block = createBlock(
false);
3058 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
3059 addSuccessor(
Block, LHSBlock, !KnownVal.isFalse());
3060 addSuccessor(
Block, RHSBlock, !KnownVal.isTrue());
3062 Expr *condExpr =
C->getCond();
3067 if (condExpr != opaqueValue)
3075 return addStmt(condExpr);
3078CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
3086 return VisitDeclSubExpr(DS);
3088 CFGBlock *B =
nullptr;
3097 DeclGroupRef DG(*I);
3100 cfg->addSyntheticDeclStmt(DSNew, DS);
3103 B = VisitDeclSubExpr(DSNew);
3111CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
3112 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
3114 if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl())) {
3116 const Type *T = TND->getUnderlyingType().getTypePtr();
3121 appendStmt(
Block, DS);
3123 CFGBlock *LastBlock =
Block;
3124 for (
const VariableArrayType *VA =
FindVA(T); VA !=
nullptr;
3125 VA =
FindVA(VA->getElementType().getTypePtr())) {
3126 if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
3127 LastBlock = NewBlock;
3140 bool HasTemporaries =
false;
3143 CFGBlock *blockAfterStaticInit =
nullptr;
3154 blockAfterStaticInit = Succ;
3163 if (HasTemporaries &&
3166 TempDtorContext Context;
3170 addFullExprCleanupMarker(Context);
3176 if (
const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
3177 for (
auto *BD : llvm::reverse(DD->bindings())) {
3178 if (
auto *VD = BD->getHoldingVar()) {
3179 DeclGroupRef DG(VD);
3182 cfg->addSyntheticDeclStmt(DSNew, DS);
3183 Block = VisitDeclSubExpr(DSNew);
3189 appendStmt(
Block, DS);
3193 const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(
Init);
3195 findConstructionContexts(
3197 AILE ? AILE->getSubExpr() :
Init);
3202 CFGBlock *LastBlock =
Block;
3205 if (HasTemporaries) {
3209 if (CFGBlock *newBlock = Visit(EC->
getSubExpr()))
3210 LastBlock = newBlock;
3213 if (CFGBlock *newBlock = Visit(
Init))
3214 LastBlock = newBlock;
3222 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
3223 if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3224 LastBlock = newBlock;
3227 maybeAddScopeBeginForVarDecl(
Block, VD, DS);
3230 if (ScopePos && VD == *ScopePos)
3233 CFGBlock *B = LastBlock;
3234 if (blockAfterStaticInit) {
3236 Block = createBlock(
false);
3237 Block->setTerminator(DS);
3238 addSuccessor(
Block, blockAfterStaticInit);
3239 addSuccessor(
Block, B);
3246CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
3256 SaveAndRestore save_scope_pos(ScopePos);
3260 addLocalScopeForStmt(
Init);
3265 addLocalScopeForVarDecl(VD);
3267 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3278 CFGBlock *ElseBlock = Succ;
3280 if (Stmt *Else = I->
getElse()) {
3281 SaveAndRestore sv(Succ);
3290 addLocalScopeAndDtors(Else);
3292 ElseBlock = addStmt(Else);
3295 ElseBlock = sv.get();
3303 CFGBlock *ThenBlock;
3307 SaveAndRestore sv(Succ);
3313 addLocalScopeAndDtors(Then);
3315 ThenBlock = addStmt(Then);
3321 ThenBlock = createBlock(
false);
3322 addSuccessor(ThenBlock, sv.get());
3336 BinaryOperator *
Cond =
3340 CFGBlock *LastBlock;
3342 LastBlock = VisitLogicalOperator(
Cond, I, ThenBlock, ElseBlock).first;
3345 Block = createBlock(
false);
3348 Block->setTerminator(I);
3353 KnownVal = tryEvaluateBool(I->
getCond());
3357 addSuccessor(
Block, ThenBlock, !KnownVal.isFalse());
3358 addSuccessor(
Block, ElseBlock, !KnownVal.isTrue());
3366 LastBlock = addStmt(I->
getCond());
3372 LastBlock = addStmt(
const_cast<DeclStmt *
>(DS));
3379 LastBlock = addStmt(
Init);
3385CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
3395 Block = createBlock(
false);
3397 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3399 if (
auto *R = dyn_cast<ReturnStmt>(S))
3400 findConstructionContexts(
3406 if (!
Block->hasNoReturnElement())
3407 addSuccessor(
Block, &cfg->getExit());
3410 appendStmt(
Block, S);
3413 if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3414 if (Expr *O = RS->getRetValue())
3415 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3427 if (CFGBlock *R = Visit(RV))
3433CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
3434 AddStmtChoice asc) {
3438 if (asc.alwaysAdd(*
this, E)) {
3440 appendStmt(
Block, E);
3442 CFGBlock *B =
Block;
3454CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
3460 SaveAndRestore save_scope_pos(ScopePos);
3463 CFGBlock *SEHExceptBlock =
Block;
3464 if (!SEHExceptBlock)
3465 SEHExceptBlock = createBlock();
3467 appendStmt(SEHExceptBlock, ES);
3479 return SEHExceptBlock;
3482CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
3483 return VisitCompoundStmt(FS->
getBlock(),
false);
3486CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
3493 Block = createBlock(
false);
3494 Block->setTerminator(LS);
3498 if (SEHLeaveJumpTarget.block) {
3499 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3500 addSuccessor(
Block, SEHLeaveJumpTarget.block);
3507CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
3510 CFGBlock *SEHTrySuccessor =
nullptr;
3515 SEHTrySuccessor =
Block;
3516 }
else SEHTrySuccessor = Succ;
3522 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3525 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3532 Succ = SEHTrySuccessor;
3534 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3539 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3541 if (PrevSEHTryTerminatedBlock)
3542 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3544 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3547 Succ = SEHTrySuccessor;
3550 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3551 cfg->addTryDispatchBlock(TryTerminatedBlock);
3556 SaveAndRestore save_break(SEHLeaveJumpTarget);
3557 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3559 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3564CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
3567 CFGBlock *LabelBlock =
Block;
3570 LabelBlock = createBlock();
3572 assert(!LabelMap.contains(L->
getDecl()) &&
"label already in map");
3573 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3592CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
3593 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3595 if (Expr *CopyExpr = CI.getCopyExpr()) {
3596 CFGBlock *Tmp = Visit(CopyExpr);
3604CFGBlock *CFGBuilder::VisitLambdaExpr(
LambdaExpr *E, AddStmtChoice asc) {
3605 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3610 it != et; ++it, ++Idx) {
3611 if (Expr *
Init = *it) {
3615 dyn_cast<ArrayInitLoopExpr>(
Init));
3618 cfg->getBumpVectorContext(), {E, Idx}),
3619 AILEInit ? AILEInit :
Init);
3621 CFGBlock *Tmp = Visit(
Init);
3629CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
3633 Block = createBlock(
false);
3634 Block->setTerminator(G);
3637 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3639 if (I == LabelMap.end())
3641 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3643 JumpTarget JT = I->second;
3644 addSuccessor(
Block, JT.block);
3645 addScopeChangesHandling(ScopePos, JT.scopePosition, G);
3651CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
3656 return VisitStmt(G, asc);
3663 Block = createBlock();
3664 Block->setTerminator(G);
3666 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3669 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3670 return VisitChildren(G);
3673CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
3674 CFGBlock *LoopSuccessor =
nullptr;
3678 SaveAndRestore save_scope_pos(ScopePos);
3684 addLocalScopeForStmt(
Init);
3685 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3688 addLocalScopeForVarDecl(VD);
3689 LocalScope::const_iterator ContinueScopePos = ScopePos;
3691 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3700 LoopSuccessor =
Block;
3702 LoopSuccessor = Succ;
3706 SaveAndRestore save_break(BreakJumpTarget);
3707 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3709 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3716 SaveAndRestore save_Block(
Block), save_Succ(Succ);
3717 SaveAndRestore save_continue(ContinueJumpTarget);
3722 Block = Succ = TransitionBlock = createBlock(
false);
3723 TransitionBlock->setLoopTarget(F);
3728 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3730 if (Stmt *I = F->
getInc()) {
3738 assert(
Block == Succ);
3746 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3747 ContinueJumpTarget.block->setLoopTarget(F);
3753 addLocalScopeAndDtors(F->
getBody());
3757 BodyBlock = addStmt(F->
getBody());
3762 BodyBlock = ContinueJumpTarget.block;
3771 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3775 SaveAndRestore save_scope_pos(ScopePos);
3779 if (BinaryOperator *
Cond =
3780 dyn_cast_or_null<BinaryOperator>(
C ?
C->IgnoreParens() :
nullptr))
3781 if (
Cond->isLogicalOp()) {
3782 std::tie(EntryConditionBlock, ExitConditionBlock) =
3783 VisitLogicalOperator(
Cond, F, BodyBlock, LoopSuccessor);
3788 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3789 ExitConditionBlock->setTerminator(F);
3792 TryResult KnownVal(
true);
3798 Block = ExitConditionBlock;
3799 EntryConditionBlock = addStmt(
C);
3808 findConstructionContexts(
3811 appendStmt(
Block, DS);
3812 EntryConditionBlock = addStmt(
Init);
3813 assert(
Block == EntryConditionBlock);
3814 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3818 if (
Block && badCFG)
3821 KnownVal = tryEvaluateBool(
C);
3825 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3828 addSuccessor(ExitConditionBlock,
3829 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3833 addSuccessor(TransitionBlock, EntryConditionBlock);
3836 Succ = EntryConditionBlock;
3841 SaveAndRestore save_scope_pos(ScopePos);
3842 ScopePos = LoopBeginScopePos;
3843 Block = createBlock();
3850 Succ = EntryConditionBlock;
3851 return EntryConditionBlock;
3855CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
3856 AddStmtChoice asc) {
3857 findConstructionContexts(
3861 return VisitStmt(MTE, asc);
3864CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
3865 if (asc.alwaysAdd(*
this, M)) {
3867 appendStmt(
Block, M);
3872CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
3904 CFGBlock *LoopSuccessor =
nullptr;
3909 LoopSuccessor =
Block;
3912 LoopSuccessor = Succ;
3915 CFGBlock *ExitConditionBlock = createBlock(
false);
3923 appendStmt(ExitConditionBlock, S);
3924 Block = ExitConditionBlock;
3929 CFGBlock *EntryConditionBlock = Visit(S->
getElement(),
3930 AddStmtChoice::NotAlwaysAdd);
3939 Succ = EntryConditionBlock;
3944 SaveAndRestore save_Block(
Block), save_Succ(Succ);
3945 SaveAndRestore save_continue(ContinueJumpTarget),
3946 save_break(BreakJumpTarget);
3951 CFGBlock *LoopBackBlock =
nullptr;
3952 Succ = LoopBackBlock = createBlock();
3955 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3956 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3958 CFGBlock *BodyBlock = addStmt(S->
getBody());
3961 BodyBlock = ContinueJumpTarget.block;
3968 addSuccessor(ExitConditionBlock, BodyBlock);
3973 addSuccessor(ExitConditionBlock, LoopSuccessor);
3976 Block = createBlock();
3980CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
3986CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
4004 appendStmt(
Block, S);
4010CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
4014 appendStmt(
Block, E);
4016 CFGBlock *lastBlock =
Block;
4025 if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
4026 Semantic = OVE->getSourceExpr();
4028 if (CFGBlock *B = Visit(Semantic))
4035CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
4036 CFGBlock *LoopSuccessor =
nullptr;
4040 SaveAndRestore save_scope_pos(ScopePos);
4044 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
4046 addLocalScopeForVarDecl(VD);
4047 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4056 LoopSuccessor =
Block;
4059 LoopSuccessor = Succ;
4062 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
4069 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4070 SaveAndRestore save_continue(ContinueJumpTarget),
4071 save_break(BreakJumpTarget);
4075 Succ = TransitionBlock = createBlock(
false);
4076 TransitionBlock->setLoopTarget(W);
4077 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
4080 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4083 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4088 addLocalScopeAndDtors(W->
getBody());
4091 BodyBlock = addStmt(W->
getBody());
4094 BodyBlock = ContinueJumpTarget.block;
4095 else if (
Block && badCFG)
4102 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
4109 if (BinaryOperator *
Cond = dyn_cast<BinaryOperator>(
C->IgnoreParens()))
4110 if (
Cond->isLogicalOp()) {
4111 std::tie(EntryConditionBlock, ExitConditionBlock) =
4112 VisitLogicalOperator(
Cond, W, BodyBlock, LoopSuccessor);
4117 ExitConditionBlock = createBlock(
false);
4123 Block = ExitConditionBlock;
4124 Block = EntryConditionBlock = addStmt(
C);
4133 findConstructionContexts(
4135 const_cast<DeclStmt *
>(DS)),
4137 appendStmt(
Block, DS);
4138 EntryConditionBlock = addStmt(
Init);
4139 assert(
Block == EntryConditionBlock);
4140 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
4144 if (
Block && badCFG)
4148 const TryResult& KnownVal = tryEvaluateBool(
C);
4151 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
4154 addSuccessor(ExitConditionBlock,
4155 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4159 addSuccessor(TransitionBlock, EntryConditionBlock);
4166 Succ = EntryConditionBlock;
4167 return EntryConditionBlock;
4170CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
4171 AddStmtChoice asc) {
4172 if (asc.alwaysAdd(*
this, A)) {
4174 appendStmt(
Block, A);
4177 CFGBlock *B =
Block;
4189CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {
4195 SaveAndRestore save_scope_pos(ScopePos);
4200 CFGBlock *CatchBlock =
Block;
4202 CatchBlock = createBlock();
4204 appendStmt(CatchBlock, CS);
4219CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
4225 Block = createBlock(
false);
4227 if (TryTerminatedBlock)
4229 addSuccessor(
Block, TryTerminatedBlock);
4232 addSuccessor(
Block, &cfg->getExit());
4236 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4239CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {
4242 CFGBlock *TrySuccessor =
nullptr;
4247 TrySuccessor =
Block;
4249 TrySuccessor = Succ;
4255 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4258 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4262 bool HasCatchAll =
false;
4263 for (ObjCAtCatchStmt *CS : Terminator->
catch_stmts()) {
4265 Succ = TrySuccessor;
4270 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4275 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4280 if (PrevTryTerminatedBlock)
4281 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4283 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4287 Succ = TrySuccessor;
4290 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4291 cfg->addTryDispatchBlock(TryTerminatedBlock);
4293 assert(Terminator->
getTryBody() &&
"try must contain a non-NULL body");
4298CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
4299 AddStmtChoice asc) {
4300 findConstructionContextsForArguments(ME);
4303 appendObjCMessage(
Block, ME);
4305 return VisitChildren(ME);
4308CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
4314 Block = createBlock(
false);
4316 if (TryTerminatedBlock)
4318 addSuccessor(
Block, TryTerminatedBlock);
4321 addSuccessor(
Block, &cfg->getExit());
4325 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4328CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {
4329 if (asc.alwaysAdd(*
this, S)) {
4331 appendStmt(
Block, S);
4341 return VisitChildren(S);
4347CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
4348 CFGBlock *LoopSuccessor =
nullptr;
4357 LoopSuccessor =
Block;
4359 LoopSuccessor = Succ;
4364 CFGBlock *ExitConditionBlock = createBlock(
false);
4365 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4373 Block = ExitConditionBlock;
4374 EntryConditionBlock = addStmt(
C);
4382 Succ = EntryConditionBlock;
4385 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
4388 CFGBlock *BodyBlock =
nullptr;
4393 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4394 SaveAndRestore save_continue(ContinueJumpTarget),
4395 save_break(BreakJumpTarget);
4398 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4401 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4409 addLocalScopeAndDtors(D->
getBody());
4412 BodyBlock = addStmt(D->
getBody());
4415 BodyBlock = EntryConditionBlock;
4428 CFGBlock *LoopBackBlock = createBlock();
4431 if (!KnownVal.isFalse())
4433 addSuccessor(ExitConditionBlock, LoopBackBlock);
4435 addSuccessor(ExitConditionBlock,
nullptr);
4440 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4451CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *
C) {
4458 Block = createBlock(
false);
4463 if (ContinueJumpTarget.block) {
4464 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,
C);
4465 addSuccessor(
Block, ContinueJumpTarget.block);
4472CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
4473 AddStmtChoice asc) {
4474 if (asc.alwaysAdd(*
this, E)) {
4476 appendStmt(
Block, E);
4482 if (E->
getKind() != UETT_SizeOf)
4485 CFGBlock *lastBlock =
Block;
4489 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4490 lastBlock = addStmt(VA->getSizeExpr());
4497CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
4498 if (asc.alwaysAdd(*
this, SE)) {
4500 appendStmt(
Block, SE);
4502 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4505CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
4508 CFGBlock *SwitchSuccessor =
nullptr;
4512 SaveAndRestore save_scope_pos(ScopePos);
4516 addLocalScopeForStmt(
Init);
4521 addLocalScopeForVarDecl(VD);
4523 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4528 SwitchSuccessor =
Block;
4529 }
else SwitchSuccessor = Succ;
4532 SaveAndRestore save_switch(SwitchTerminatedBlock),
4533 save_default(DefaultCaseBlock);
4534 SaveAndRestore save_break(BreakJumpTarget);
4539 DefaultCaseBlock = SwitchSuccessor;
4542 SwitchTerminatedBlock = createBlock(
false);
4546 Succ = SwitchSuccessor;
4547 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4552 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4557 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered,
false);
4560 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4561 Expr::EvalResult result;
4562 bool b = tryEvaluate(Terminator->
getCond(), result);
4563 SaveAndRestore save_switchCond(switchCond,
b ? &result :
nullptr);
4568 addLocalScopeAndDtors(Terminator->
getBody());
4570 addStmt(Terminator->
getBody());
4584 bool SwitchAlwaysHasSuccessor =
false;
4585 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4586 SwitchAlwaysHasSuccessor |=
4589 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4590 !SwitchAlwaysHasSuccessor);
4594 Block = SwitchTerminatedBlock;
4595 CFGBlock *LastBlock = addStmt(Terminator->
getCond());
4603 LastBlock = addStmt(
Init);
4604 maybeAddScopeBeginForVarDecl(LastBlock, VD,
Init);
4611 LastBlock = addStmt(
Init);
4624 bool addCase =
false;
4626 if (!switchExclusivelyCovered) {
4630 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4632 if (condInt == lhsInt) {
4634 switchExclusivelyCovered =
true;
4636 else if (condInt > lhsInt) {
4640 if (V2 >= condInt) {
4642 switchExclusivelyCovered =
true;
4653CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
4656 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4663 CFGBlock *currentBlock = createBlock(
false);
4667 addSuccessor(LastBlock, currentBlock);
4669 TopBlock = currentBlock;
4671 addSuccessor(SwitchTerminatedBlock,
4674 ? currentBlock :
nullptr);
4676 LastBlock = currentBlock;
4684 CFGBlock *CaseBlock =
Block;
4686 CaseBlock = createBlock();
4697 assert(SwitchTerminatedBlock);
4698 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4706 addSuccessor(LastBlock, CaseBlock);
4716CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
4720 DefaultCaseBlock =
Block;
4722 if (!DefaultCaseBlock)
4723 DefaultCaseBlock = createBlock();
4727 DefaultCaseBlock->
setLabel(Terminator);
4742 Succ = DefaultCaseBlock;
4744 return DefaultCaseBlock;
4747CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
4750 CFGBlock *TrySuccessor =
nullptr;
4755 TrySuccessor =
Block;
4757 TrySuccessor = Succ;
4759 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4762 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4766 bool HasCatchAll =
false;
4767 for (
unsigned I = 0, E = Terminator->
getNumHandlers(); I != E; ++I) {
4769 Succ = TrySuccessor;
4770 CXXCatchStmt *CS = Terminator->
getHandler(I);
4775 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4780 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4783 if (PrevTryTerminatedBlock)
4784 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4786 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4790 Succ = TrySuccessor;
4793 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4794 cfg->addTryDispatchBlock(TryTerminatedBlock);
4796 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4801CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
4807 SaveAndRestore save_scope_pos(ScopePos);
4812 LocalScope::const_iterator BeginScopePos = ScopePos;
4813 addLocalScopeForVarDecl(VD);
4814 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4820 CFGBlock *CatchBlock =
Block;
4822 CatchBlock = createBlock();
4828 appendStmt(CatchBlock, CS);
4844CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
4859 SaveAndRestore save_scope_pos(ScopePos);
4864 addLocalScopeForStmt(
Init);
4866 addLocalScopeForStmt(Range);
4868 addLocalScopeForStmt(Begin);
4870 addLocalScopeForStmt(End);
4871 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4873 LocalScope::const_iterator ContinueScopePos = ScopePos;
4877 CFGBlock *LoopSuccessor =
nullptr;
4881 LoopSuccessor =
Block;
4883 LoopSuccessor = Succ;
4887 SaveAndRestore save_break(BreakJumpTarget);
4888 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4891 CFGBlock *ConditionBlock = createBlock(
false);
4896 Block = ConditionBlock;
4897 CFGBlock *BeginConditionBlock = addStmt(
C);
4900 assert(BeginConditionBlock == ConditionBlock &&
4901 "condition block in for-range was unexpectedly complex");
4902 (void)BeginConditionBlock;
4907 Succ = ConditionBlock;
4910 TryResult KnownVal(
true);
4913 KnownVal = tryEvaluateBool(S->
getCond());
4920 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4921 SaveAndRestore save_continue(ContinueJumpTarget);
4926 Succ = addStmt(S->
getInc());
4929 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4933 ContinueJumpTarget.block->setLoopTarget(S);
4947 addLocalScopeAndDtors(S->
getBody());
4959 addSuccessor(ConditionBlock,
4960 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
4965 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4968 Block = createBlock();
4977CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
4979 bool ExternallyDestructed) {
4983 TempDtorContext Context;
4984 VisitForTemporaries(E->
getSubExpr(), ExternallyDestructed, Context);
4986 addFullExprCleanupMarker(Context);
4990 asc = asc.withAlwaysAdd(
true);
4995CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
4996 AddStmtChoice asc) {
4997 if (asc.alwaysAdd(*
this, E)) {
4999 appendStmt(
Block, E);
5001 findConstructionContexts(
5006 asc = asc.withAlwaysAdd(
false);
5011CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *
C,
5012 AddStmtChoice asc) {
5016 findConstructionContextsForArguments(
C);
5017 appendConstructor(
C);
5019 return VisitChildren(
C);
5022CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
5023 AddStmtChoice asc) {
5025 appendStmt(
Block, NE);
5027 findConstructionContexts(
5029 const_cast<CXXConstructExpr *
>(
NE->getConstructExpr()));
5031 if (
NE->getInitializer())
5032 Block = Visit(
NE->getInitializer());
5035 appendNewAllocator(
Block, NE);
5037 if (
NE->isArray() && *
NE->getArraySize())
5038 Block = Visit(*
NE->getArraySize());
5041 E =
NE->placement_arg_end(); I != E; ++I)
5047CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
5048 AddStmtChoice asc) {
5050 appendStmt(
Block, DE);
5057 appendDeleteDtor(
Block, RD, DE);
5061 return VisitChildren(DE);
5064CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
5065 AddStmtChoice asc) {
5066 if (asc.alwaysAdd(*
this, E)) {
5068 appendStmt(
Block, E);
5070 asc = asc.withAlwaysAdd(
false);
5075CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
5076 AddStmtChoice asc) {
5080 findConstructionContextsForArguments(E);
5081 appendConstructor(E);
5083 return VisitChildren(E);
5086CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
5087 AddStmtChoice asc) {
5088 if (asc.alwaysAdd(*
this, E)) {
5090 appendStmt(
Block, E);
5096 return Visit(E->
getSubExpr(), AddStmtChoice());
5099CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
5100 return Visit(E->
getSubExpr(), AddStmtChoice());
5103CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5105 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
5108 IBlock = createBlock(
false);
5109 cfg->setIndirectGotoBlock(IBlock);
5117 Block = createBlock(
false);
5118 Block->setTerminator(I);
5119 addSuccessor(
Block, IBlock);
5123CFGBlock *CFGBuilder::VisitForTemporaries(Stmt *E,
bool ExternallyDestructed,
5124 TempDtorContext &Context) {
5133 return VisitChildrenForTemporaries(E,
false, Context);
5135 case Stmt::InitListExprClass:
5136 return VisitChildrenForTemporaries(E, ExternallyDestructed, Context);
5138 case Stmt::BinaryOperatorClass:
5140 ExternallyDestructed, Context);
5142 case Stmt::CXXOperatorCallExprClass:
5143 return VisitCXXOperatorCallExprForTemporaryDtors(
5146 case Stmt::CXXBindTemporaryExprClass:
5147 return VisitCXXBindTemporaryExprForTemporaryDtors(
5150 case Stmt::BinaryConditionalOperatorClass:
5151 case Stmt::ConditionalOperatorClass:
5152 return VisitConditionalOperatorForTemporaries(
5155 case Stmt::ImplicitCastExprClass:
5160 case Stmt::CXXFunctionalCastExprClass:
5165 case Stmt::ConstantExprClass:
5169 case Stmt::ParenExprClass:
5173 case Stmt::MaterializeTemporaryExprClass: {
5176 if (BuildOpts.
AddLifetime && !ExternallyDestructed)
5178 SmallVector<const Expr *, 2> CommaLHSs;
5179 SmallVector<SubobjectAdjustment, 2> Adjustments;
5181 E =
const_cast<Expr *
>(
5184 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
5186 for (
const Expr *CommaLHS : CommaLHSs) {
5187 VisitForTemporaries(
const_cast<Expr *
>(CommaLHS),
5193 case Stmt::BlockExprClass:
5198 case Stmt::LambdaExprClass: {
5202 CFGBlock *B =
Block;
5203 for (Expr *
Init :
LE->capture_inits()) {
5205 if (CFGBlock *R = VisitForTemporaries(
5206 Init,
true, Context))
5213 case Stmt::StmtExprClass:
5218 case Stmt::CXXDefaultArgExprClass:
5222 case Stmt::CXXDefaultInitExprClass:
5228CFGBlock *CFGBuilder::VisitChildrenForTemporaries(Stmt *E,
5229 bool ExternallyDestructed,
5230 TempDtorContext &Context) {
5240 CFGBlock *B =
Block;
5244 VisitForTemporaries(Child, ExternallyDestructed, Context))
5250CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaries(
5251 BinaryOperator *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5255 CFGBlock *LHSBlock = VisitForTemporaries(E->
getLHS(),
false, Context);
5256 CFGBlock *RHSBlock =
5257 VisitForTemporaries(E->
getRHS(), ExternallyDestructed, Context);
5258 return RHSBlock ? RHSBlock : LHSBlock;
5262 VisitForTemporaries(E->
getLHS(),
false, Context);
5263 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
5264 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
5265 RHSExecuted.negate();
5270 TempDtorContext RHSContext(
5272 VisitForTemporaries(E->
getRHS(),
false, RHSContext);
5273 InsertTempDecisionBlock(RHSContext);
5276 Context.CollectedMTEs.append(RHSContext.CollectedMTEs);
5284 CFGBlock *RHSBlock = VisitForTemporaries(E->
getRHS(),
false, Context);
5285 CFGBlock *LHSBlock = VisitForTemporaries(E->
getLHS(),
false, Context);
5286 return LHSBlock ? LHSBlock : RHSBlock;
5290 return VisitChildrenForTemporaries(E, ExternallyDestructed, Context);
5293CFGBlock *CFGBuilder::VisitCXXOperatorCallExprForTemporaryDtors(
5294 CXXOperatorCallExpr *E, TempDtorContext &Context) {
5298 CFGBlock *RHSBlock = VisitForTemporaries(E->
getArg(1),
false, Context);
5299 CFGBlock *LHSBlock = VisitForTemporaries(E->
getArg(0),
false, Context);
5300 return LHSBlock ? LHSBlock : RHSBlock;
5302 return VisitChildrenForTemporaries(E,
false, Context);
5305CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5306 CXXBindTemporaryExpr *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5309 CFGBlock *B = VisitForTemporaries(E->
getSubExpr(),
true, Context);
5323 Block = createNoReturnBlock();
5324 }
else if (Context.needsTempDtorBranch()) {
5328 Block = createBlock();
5332 if (Context.needsTempDtorBranch()) {
5333 Context.setDecisionPoint(Succ, E);
5335 appendTemporaryDtor(
Block, E);
5341void CFGBuilder::InsertTempDecisionBlock(
const TempDtorContext &Context,
5342 CFGBlock *FalseSucc) {
5343 if (!Context.TerminatorExpr) {
5347 assert(Context.TerminatorExpr);
5348 CFGBlock *Decision = createBlock(
false);
5349 Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,
5351 addSuccessor(Decision,
Block, !Context.KnownExecuted.isFalse());
5352 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5353 !Context.KnownExecuted.isTrue());
5357CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaries(
5358 AbstractConditionalOperator *E,
bool ExternallyDestructed,
5359 TempDtorContext &Context) {
5360 VisitForTemporaries(E->
getCond(),
false, Context);
5361 CFGBlock *ConditionBlock =
Block;
5362 CFGBlock *ConditionSucc = Succ;
5363 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
5364 TryResult NegatedVal = ConditionVal;
5365 if (NegatedVal.isKnown()) NegatedVal.negate();
5367 TempDtorContext TrueContext(
5369 VisitForTemporaries(E->
getTrueExpr(), ExternallyDestructed, TrueContext);
5370 CFGBlock *TrueBlock =
Block;
5372 Block = ConditionBlock;
5373 Succ = ConditionSucc;
5374 TempDtorContext FalseContext(
5376 VisitForTemporaries(E->
getFalseExpr(), ExternallyDestructed, FalseContext);
5378 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5379 InsertTempDecisionBlock(FalseContext, TrueBlock);
5380 }
else if (TrueContext.TerminatorExpr) {
5382 InsertTempDecisionBlock(TrueContext);
5384 InsertTempDecisionBlock(FalseContext);
5387 Context.CollectedMTEs.append(TrueContext.CollectedMTEs);
5388 Context.CollectedMTEs.append(FalseContext.CollectedMTEs);
5394CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
5395 AddStmtChoice asc) {
5396 if (asc.alwaysAdd(*
this, D)) {
5398 appendStmt(
Block, D);
5402 CFGBlock *B =
Block;
5406 SmallVector<Stmt *, 8>
Used(
5407 OMPExecutableDirective::used_clauses_children(D->clauses()));
5408 for (Stmt *S : llvm::reverse(
Used)) {
5409 assert(S &&
"Expected non-null used-in-clause child.");
5410 if (CFGBlock *R = Visit(S))
5414 if (!D->isStandaloneDirective()) {
5415 Stmt *S = D->getRawStmt();
5417 addLocalScopeAndDtors(S);
5418 if (CFGBlock *R = addStmt(S))
5429 bool first_block =
begin() ==
end();
5433 Blocks.push_back(Mem, BlkBVC);
5437 Entry = Exit = &
back();
5446 llvm::TimeTraceScope TimeProfile(
"BuildCFG");
5447 CFGBuilder Builder(
C, BO);
5448 return Builder.buildCFG(D, Statement);
5463 auto IteratorAndFlag = Visited.insert(B);
5464 if (!IteratorAndFlag.second) {
5470 const CFGBlock *FirstReachableB =
nullptr;
5472 if (!AB.isReachable())
5475 if (FirstReachableB ==
nullptr) {
5476 FirstReachableB = &*AB;
5483 if (!FirstReachableB) {
5489 B = FirstReachableB;
5510 llvm_unreachable(
"getDestructorDecl should only be used with "
5521 if (
const Expr *
Init = var->getInit()) {
5568 llvm_unreachable(
"getKind() returned bogus value");
5576 : ReachableBlock(IsReachable ? B :
nullptr),
5577 UnreachableBlock(!IsReachable ? B :
nullptr,
5578 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5581 : ReachableBlock(B),
5582 UnreachableBlock(B == AlternateBlock ?
nullptr : AlternateBlock,
5583 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5593 Succs.push_back(Succ,
C);
5606 if (S->isAllEnumCasesCovered()) {
5624 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5625 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5629 signed currentBlock = 0;
5630 unsigned currStmt = 0;
5640 for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
5641 BI != BEnd; ++BI, ++j ) {
5642 if (std::optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
5643 const Stmt *stmt= SE->getStmt();
5644 std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
5647 switch (stmt->getStmtClass()) {
5648 case Stmt::DeclStmtClass:
5649 DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
5651 case Stmt::IfStmtClass: {
5652 const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
5657 case Stmt::ForStmtClass: {
5658 const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
5663 case Stmt::WhileStmtClass: {
5664 const VarDecl *var =
5665 cast<WhileStmt>(stmt)->getConditionVariable();
5670 case Stmt::SwitchStmtClass: {
5671 const VarDecl *var =
5672 cast<SwitchStmt>(stmt)->getConditionVariable();
5677 case Stmt::CXXCatchStmtClass: {
5678 const VarDecl *var =
5679 cast<CXXCatchStmt>(stmt)->getExceptionDecl();
5692 ~StmtPrinterHelper()
override =
default;
5694 const LangOptions &getLangOpts()
const {
return LangOpts; }
5695 void setBlockID(
signed i) { currentBlock = i; }
5696 void setStmtID(
unsigned i) { currStmt = i; }
5698 bool handledStmt(Stmt *S, raw_ostream &OS)
override {
5699 StmtMapTy::iterator I = StmtMap.find(S);
5701 if (I == StmtMap.end())
5704 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5705 && I->second.second == currStmt) {
5709 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5713 bool handleDecl(
const Decl *D, raw_ostream &OS) {
5714 DeclMapTy::iterator I = DeclMap.find(D);
5716 if (I == DeclMap.end()) {
5719 if (
auto *PVD = dyn_cast_or_null<ParmVarDecl>(D)) {
5720 OS <<
"[Parm: " << PVD->getNameAsString() <<
"]";
5726 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5727 && I->second.second == currStmt) {
5731 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5736class CFGBlockTerminatorPrint
5737 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5739 StmtPrinterHelper* Helper;
5740 PrintingPolicy Policy;
5743 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5744 const PrintingPolicy &Policy)
5745 :
OS(os), Helper(helper), Policy(Policy) {
5749 void VisitIfStmt(IfStmt *I) {
5752 C->printPretty(OS, Helper, Policy);
5756 void VisitStmt(Stmt *Terminator) {
5760 void VisitDeclStmt(DeclStmt *DS) {
5765 void VisitForStmt(ForStmt *F) {
5771 C->printPretty(OS, Helper, Policy);
5778 void VisitWhileStmt(WhileStmt *W) {
5781 C->printPretty(OS, Helper, Policy);
5784 void VisitDoStmt(DoStmt *D) {
5785 OS <<
"do ... while ";
5787 C->printPretty(OS, Helper, Policy);
5790 void VisitSwitchStmt(SwitchStmt *Terminator) {
5795 void VisitCXXTryStmt(CXXTryStmt *) {
OS <<
"try ..."; }
5797 void VisitObjCAtTryStmt(ObjCAtTryStmt *) {
OS <<
"@try ..."; }
5799 void VisitSEHTryStmt(SEHTryStmt *CS) {
OS <<
"__try ..."; }
5801 void VisitAbstractConditionalOperator(AbstractConditionalOperator*
C) {
5802 if (Stmt *
Cond =
C->getCond())
5804 OS <<
" ? ... : ...";
5807 void VisitChooseExpr(ChooseExpr *
C) {
5808 OS <<
"__builtin_choose_expr( ";
5809 if (Stmt *
Cond =
C->getCond())
5814 void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5820 void VisitBinaryOperator(BinaryOperator* B) {
5837 llvm_unreachable(
"Invalid logical operator.");
5841 void VisitExpr(Expr *E) {
5846 void print(CFGTerminator T) {
5852 OS <<
"(Temp Dtor) ";
5856 OS <<
"(See if most derived ctor has already initialized vbases)";
5878 OS <<
" (Base initializer)";
5880 OS <<
" (Delegating initializer)";
5882 OS <<
" (Member initializer)";
5886 StmtPrinterHelper &Helper,
5901 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5906 Stmts.push_back(SDSCC->getDeclStmt());
5911 Stmts.push_back(CDSCC->getDeclStmt());
5912 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5917 Stmts.push_back(NECC->getCXXNewExpr());
5922 Stmts.push_back(RSCC->getReturnStmt());
5928 Stmts.push_back(RSCC->getReturnStmt());
5929 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5934 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5935 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5940 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5941 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5942 Stmts.push_back(TOCC->getConstructorAfterElision());
5947 Helper.handledStmt(
const_cast<LambdaExpr *
>(LCC->getLambdaExpr()), OS);
5948 OS <<
"+" << LCC->getIndex();
5953 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5955 Helper.handledStmt(
const_cast<Stmt *
>(BTE), OS);
5958 Helper.handledStmt(
const_cast<Expr *
>(ACC->getCallLikeExpr()), OS);
5959 OS <<
"+" << ACC->getIndex();
5966 Helper.handledStmt(
const_cast<Stmt *
>(I), OS);
5970static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5971 const CFGElement &E,
bool TerminateWithNewLine =
true);
5974 bool TerminateWithNewLine)
const {
5976 StmtPrinterHelper Helper(
nullptr, LangOpts);
5977 print_elem(OS, Helper, *
this, TerminateWithNewLine);
5980static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5981 const CFGElement &E,
bool TerminateWithNewLine) {
5988 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5991 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5999 if (TerminateWithNewLine)
6008 Helper.handledStmt(B->
getRHS(),OS);
6009 if (TerminateWithNewLine)
6014 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
6018 OS <<
" (OperatorCall)";
6019 OS <<
" (CXXRecordTypedCall";
6023 OS <<
" (OperatorCall)";
6025 OS <<
" (BindTemporary)";
6027 OS <<
" (CXXConstructExpr";
6031 OS <<
", " << CCE->getType() <<
")";
6032 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
6034 <<
", " << CE->
getType() <<
")";
6038 if (
isa<Expr>(S) && TerminateWithNewLine)
6051 Helper.handleDecl(VD, OS);
6054 if (T->isReferenceType())
6058 T.getUnqualifiedType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
6059 OS <<
"() (Implicit destructor)";
6064 OS <<
"CleanupFunction ("
6070 OS <<
" (Lifetime ends)";
6075 size_t MTECount = MTEs.size();
6076 OS <<
"(FullExprCleanup collected " << MTECount
6077 << (MTECount > 1 ?
" MTEs: " :
" MTE: ");
6078 bool FirstMTE =
true;
6082 if (!Helper.handledStmt(MTE->
getSubExpr(), OS)) {
6100 OS <<
"CFGScopeBegin(";
6107 OS <<
"CFGScopeEnd(";
6114 OS <<
"CFGNewAllocator(";
6116 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
6128 OS <<
"->~" << RD->getName().str() <<
"()";
6129 OS <<
" (Implicit destructor)";
6136 OS <<
" (Base object destructor)";
6143 OS <<
"this->" << FD->
getName();
6144 OS <<
".~" << T->getAsCXXRecordDecl()->getName() <<
"()";
6145 OS <<
" (Member object destructor)";
6154 OS <<
"() (Temporary object destructor)";
6158 if (TerminateWithNewLine)
6164 StmtPrinterHelper &Helper,
bool print_edges,
6170 OS.changeColor(raw_ostream::YELLOW,
true);
6175 OS <<
" (ENTRY)]\n";
6176 else if (&B == &cfg->
getExit())
6179 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
6181 OS <<
" (NORETURN)]\n";
6197 if (
const Expr *LHS =
C->getLHS())
6199 if (
const Expr *RHS =
C->getRHS()) {
6214 if (
const VarDecl *PD = CS->getCatchParamDecl())
6225 llvm_unreachable(
"Invalid label statement in CFGBlock.");
6234 I != E ; ++I, ++j ) {
6239 OS << llvm::format(
"%3d", j) <<
": ";
6241 Helper.setStmtID(j);
6249 OS.changeColor(raw_ostream::GREEN);
6253 Helper.setBlockID(-1);
6256 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
6267 const raw_ostream::Colors Color = raw_ostream::BLUE;
6269 OS.changeColor(Color);
6277 OS.changeColor(Color);
6285 bool Reachable =
true;
6288 B = I->getPossiblyUnreachableBlock();
6293 OS <<
"(Unreachable)";
6304 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
6306 OS.changeColor(Color);
6314 OS.changeColor(Color);
6323 bool Reachable =
true;
6326 B = I->getPossiblyUnreachableBlock();
6332 OS <<
"(Unreachable)";
6348 print(llvm::errs(), LO, ShowColors);
6353 StmtPrinterHelper Helper(
this, LO);
6359 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
6364 print_block(OS,
this, **I, Helper,
true, ShowColors);
6379 bool ShowColors)
const {
6380 print(llvm::errs(), cfg, LO, ShowColors);
6391 StmtPrinterHelper Helper(cfg, LO);
6392 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
6399 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
6405 bool AddQuotes)
const {
6407 llvm::raw_string_ostream TempOut(Buf);
6430 if (llvm::any_of(*Blk, [](
const CFGElement &Elm) {
6431 if (std::optional<CFGStmt> StmtElm = Elm.
getAs<
CFGStmt>())
6451 DFSWorkList.push_back(StartBlk);
6452 while (!DFSWorkList.empty()) {
6453 const CFGBlock *Blk = DFSWorkList.pop_back_val();
6454 Visited.insert(Blk);
6463 for (
const auto &Succ : Blk->
succs()) {
6464 if (
const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
6468 DFSWorkList.push_back(SuccBlk);
6497 const Stmt *
Cond = StmtElem->getStmt();
6511 const Expr *E =
nullptr;
6517 case Stmt::CXXForRangeStmtClass:
6521 case Stmt::ForStmtClass:
6525 case Stmt::WhileStmtClass:
6529 case Stmt::DoStmtClass:
6533 case Stmt::IfStmtClass:
6537 case Stmt::ChooseExprClass:
6541 case Stmt::IndirectGotoStmtClass:
6545 case Stmt::SwitchStmtClass:
6549 case Stmt::BinaryConditionalOperatorClass:
6553 case Stmt::ConditionalOperatorClass:
6557 case Stmt::BinaryOperatorClass:
6561 case Stmt::ObjCForCollectionStmtClass:
6578 StmtPrinterHelper H(
this, LO);
6580 llvm::ViewGraph(
this,
"CFG");
6592 llvm::raw_string_ostream Out(OutStr);
6595 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
6598 for (
unsigned i = 0; i != OutStr.length(); ++i)
6599 if (OutStr[i] ==
'\n') {
6601 OutStr.insert(OutStr.begin()+i+1,
'l');
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static StmtPrinterHelper * GraphHelper
static bool isCXXAssumeAttr(const AttributedStmt *A)
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E, bool TerminateWithNewLine=true)
static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXCtorInitializer *I)
static SourceLocation GetEndLoc(Decl *D)
static bool isBuiltinAssumeWithSideEffects(const ASTContext &Ctx, const CallExpr *CE)
static bool CanThrow(Expr *E, ASTContext &Ctx)
static bool isFallthroughStatement(const AttributedStmt *A)
static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)
static bool isImmediateSinkBlock(const CFGBlock *Blk)
static const Expr * tryTransformToLiteralConstant(const Expr *E)
Helper for tryNormalizeBinaryOperator.
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...
static const VariableArrayType * FindVA(const Type *t)
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...
static bool IsLiteralConstantExpr(const Expr *E)
Returns true on constant values based around a single IntegerLiteral, CharacterLiteral,...
static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC)
static bool shouldAddCase(bool &switchExclusivelyCovered, const Expr::EvalResult *switchCond, const CaseStmt *CS, ASTContext &Ctx)
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...
static TryResult bothKnownTrue(TryResult R1, TryResult R2)
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.
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.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
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.
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.
void setLoopTarget(const Stmt *loopTarget)
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
size_t getIndexInCFG() const
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
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.
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.
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)
const Stmt * getTerminatorCondition(bool StripParens=true) const
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
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
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
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
BumpVector< const MaterializeTemporaryExpr * > MTEVecTy
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Represents C++ base or member initializer from constructor's initialization list.
const 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 AddParameterLifetimes
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.
bool isLinear() const
Returns true if the CFG has no branches.
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
llvm::BumpPtrAllocator & getAllocator()
CFGBlock * createBlock()
Create a new block in the CFG.
CFGBlock * getIndirectGotoBlock()
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
void viewCFG(const LangOptions &LO) const
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
static bool isAssignmentOp(OverloadedOperatorKind Opc)
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
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
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<specific type>'.
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.
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)
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)
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)