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;
1833 Expr *ActualInit =
Init;
1835 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init))
1836 ActualInit = DIE->getExpr();
1840 if (HasTemporaries &&
1843 TempDtorContext Context;
1847 addFullExprCleanupMarker(Context);
1852 appendInitializer(
Block, I);
1858 dyn_cast<ArrayInitLoopExpr>(
Init));
1860 findConstructionContexts(
1862 AILEInit ? AILEInit :
Init);
1865 if (CXXDefaultInitExpr *
Default = dyn_cast<CXXDefaultInitExpr>(
Init)) {
1871 if (Stmt *Child =
Default->getExpr()) {
1874 if (CFGBlock *R = Visit(Child))
1881 if (HasTemporaries) {
1895 bool *FoundMTE =
nullptr) {
1902 Init = EWC->getSubExpr();
1908 = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
1909 Init = MTE->getSubExpr();
1916 const Expr *SkippedInit =
Init->skipRValueSubobjectAdjustments();
1917 if (SkippedInit !=
Init) {
1925 return Init->getType();
1930void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1934 appendLoopExit(
Block, LoopStmt);
1942void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1943 LocalScope::const_iterator E,
1953 if (B.inSameLocalScope(E)) {
1954 addAutomaticObjDestruction(B, E, S);
1959 SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;
1960 LocalScopeEndMarkers.push_back(B);
1961 for (LocalScope::const_iterator I = B; I != E; ++I) {
1962 if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
1963 LocalScopeEndMarkers.push_back(I);
1965 LocalScopeEndMarkers.push_back(E);
1969 std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
1971 llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
1972 for (
auto [E, B] : Pairwise) {
1973 if (!B.inSameLocalScope(E))
1974 addScopeExitHandling(B, E, S);
1975 addAutomaticObjDestruction(B, E, S);
1982void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
1983 LocalScope::const_iterator E,
1991 SmallVector<VarDecl *, 10> DeclsNeedDestruction;
1992 DeclsNeedDestruction.reserve(B.distance(E));
1994 for (VarDecl* D : llvm::make_range(B, E))
1995 if (needsAutomaticDestruction(D))
1996 DeclsNeedDestruction.push_back(D);
1998 for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
2011 Block = createNoReturnBlock();
2020 appendLifetimeEnds(
Block, VD, S);
2022 appendAutomaticObjDtor(
Block, VD, S);
2023 if (VD->
hasAttr<CleanupAttr>())
2024 appendCleanupFunction(
Block, VD);
2033void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
2034 LocalScope::const_iterator E, Stmt *S) {
2035 assert(!B.inSameLocalScope(E));
2041 appendScopeEnd(
Block, B.getFirstVarInScope(), S);
2048 SmallVector<VarDecl *, 10> DeclsTrivial;
2049 DeclsTrivial.reserve(B.distance(E));
2054 for (VarDecl* D : llvm::make_range(B, E))
2055 if (!needsAutomaticDestruction(D))
2056 DeclsTrivial.push_back(D);
2058 if (DeclsTrivial.empty())
2062 for (VarDecl *VD : llvm::reverse(DeclsTrivial))
2063 appendLifetimeEnds(
Block, VD, S);
2071void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
2072 LocalScope::const_iterator DstPos,
2074 assert(
Block &&
"Source block should be always crated");
2080 if (SrcPos == DstPos)
2085 LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
2088 if (BuildOpts.
AddScopes && !DstPos.inSameLocalScope(BasePos)) {
2089 for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
2090 if (I.pointsToFirstDeclaredVar())
2091 appendScopeBegin(
Block, *I, S);
2096 addAutomaticObjHandling(SrcPos, BasePos, S);
2099void CFGBuilder::addFullExprCleanupMarker(TempDtorContext &Context) {
2101 BumpVectorContext &BVC = cfg->getBumpVectorContext();
2103 size_t NumCollected = Context.CollectedMTEs.size();
2104 if (NumCollected > 0) {
2106 ExpiringMTEs =
new (cfg->getAllocator())
2108 for (
const MaterializeTemporaryExpr *MTE : Context.CollectedMTEs)
2110 Block->appendFullExprCleanup(ExpiringMTEs, BVC);
2119CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
2120 LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,
2121 LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {
2122 if (SrcPos == DstPos)
2126 (!BuildOpts.
AddScopes || SrcPos.inSameLocalScope(DstPos)))
2131 SaveAndRestore save_Block(
Block), save_Succ(Succ);
2134 Block = createBlock(
false);
2137 addSuccessor(
Block, DstBlk);
2140 addScopeChangesHandling(SrcPos, DstPos,
Block->getTerminatorStmt());
2142 assert(
Block &&
"There should be at least one scope changing Block");
2148void CFGBuilder::addImplicitDtorsForDestructor(
const CXXDestructorDecl *DD) {
2150 "Can be called only when dtors should be added");
2151 const CXXRecordDecl *RD = DD->
getParent();
2154 for (
const auto &VI : RD->
vbases()) {
2158 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2161 appendBaseDtor(
Block, &VI);
2166 for (
const auto &BI : RD->
bases()) {
2167 if (!BI.isVirtual()) {
2168 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2171 appendBaseDtor(
Block, &BI);
2179 for (
auto *FI : RD->
fields()) {
2181 QualType QT = FI->getType();
2184 if (AT->isZeroSize())
2186 QT = AT->getElementType();
2192 appendMemberDtor(
Block, FI);
2199LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
2202 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
2203 return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);
2208void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
2213 LocalScope *Scope =
nullptr;
2217 for (
auto *BI : CS->body()) {
2218 Stmt *SI = BI->stripLabelLikeStatements();
2219 if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2220 Scope = addLocalScopeForDeclStmt(DS, Scope);
2228 addLocalScopeForDeclStmt(DS);
2233LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
2234 LocalScope* Scope) {
2239 for (
auto *DI : DS->
decls())
2240 if (VarDecl *VD = dyn_cast<VarDecl>(DI))
2241 Scope = addLocalScopeForVarDecl(VD, Scope);
2245bool CFGBuilder::needsAutomaticDestruction(
const VarDecl *VD)
const {
2246 return !hasTrivialDestructor(VD) || VD->
hasAttr<CleanupAttr>();
2249bool CFGBuilder::hasTrivialDestructor(
const VarDecl *VD)
const {
2270 bool FoundMTE =
false;
2278 if (AT->isZeroSize())
2280 QT = AT->getElementType();
2292LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
2293 LocalScope* Scope) {
2308 !needsAutomaticDestruction(VD)) {
2314 Scope = createOrReuseLocalScope(Scope);
2316 ScopePos = Scope->begin();
2322void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
2323 LocalScope::const_iterator scopeBeginPos = ScopePos;
2324 addLocalScopeForStmt(S);
2325 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2331CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2332 bool ExternallyDestructed) {
2338 if (Expr *E = dyn_cast<Expr>(S))
2339 S = E->IgnoreParens();
2342 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2343 return VisitOMPExecutableDirective(D, asc);
2347 return VisitStmt(S, asc);
2349 case Stmt::ImplicitValueInitExprClass:
2352 return VisitStmt(S, asc);
2354 case Stmt::InitListExprClass:
2357 case Stmt::AttributedStmtClass:
2360 case Stmt::AddrLabelExprClass:
2363 case Stmt::BinaryConditionalOperatorClass:
2366 case Stmt::BinaryOperatorClass:
2369 case Stmt::BlockExprClass:
2372 case Stmt::BreakStmtClass:
2375 case Stmt::CallExprClass:
2376 case Stmt::CXXOperatorCallExprClass:
2377 case Stmt::CXXMemberCallExprClass:
2378 case Stmt::UserDefinedLiteralClass:
2381 case Stmt::CaseStmtClass:
2384 case Stmt::ChooseExprClass:
2387 case Stmt::CompoundStmtClass:
2390 case Stmt::ConditionalOperatorClass:
2393 case Stmt::ContinueStmtClass:
2396 case Stmt::CXXCatchStmtClass:
2399 case Stmt::ExprWithCleanupsClass:
2401 asc, ExternallyDestructed);
2403 case Stmt::CXXDefaultArgExprClass:
2404 case Stmt::CXXDefaultInitExprClass:
2413 return VisitStmt(S, asc);
2415 case Stmt::CXXBindTemporaryExprClass:
2418 case Stmt::CXXConstructExprClass:
2421 case Stmt::CXXNewExprClass:
2424 case Stmt::CXXDeleteExprClass:
2427 case Stmt::CXXFunctionalCastExprClass:
2430 case Stmt::CXXTemporaryObjectExprClass:
2433 case Stmt::CXXThrowExprClass:
2436 case Stmt::CXXTryStmtClass:
2439 case Stmt::CXXTypeidExprClass:
2442 case Stmt::CXXForRangeStmtClass:
2445 case Stmt::DeclStmtClass:
2448 case Stmt::DefaultStmtClass:
2451 case Stmt::DoStmtClass:
2454 case Stmt::ForStmtClass:
2457 case Stmt::GotoStmtClass:
2460 case Stmt::GCCAsmStmtClass:
2463 case Stmt::IfStmtClass:
2466 case Stmt::ImplicitCastExprClass:
2469 case Stmt::ConstantExprClass:
2472 case Stmt::IndirectGotoStmtClass:
2475 case Stmt::LabelStmtClass:
2478 case Stmt::LambdaExprClass:
2481 case Stmt::MaterializeTemporaryExprClass:
2485 case Stmt::MemberExprClass:
2488 case Stmt::NullStmtClass:
2491 case Stmt::ObjCAtCatchStmtClass:
2494 case Stmt::ObjCAutoreleasePoolStmtClass:
2497 case Stmt::ObjCAtSynchronizedStmtClass:
2500 case Stmt::ObjCAtThrowStmtClass:
2503 case Stmt::ObjCAtTryStmtClass:
2506 case Stmt::ObjCForCollectionStmtClass:
2509 case Stmt::ObjCMessageExprClass:
2512 case Stmt::OpaqueValueExprClass:
2515 case Stmt::PseudoObjectExprClass:
2518 case Stmt::ReturnStmtClass:
2519 case Stmt::CoreturnStmtClass:
2520 return VisitReturnStmt(S);
2522 case Stmt::CoyieldExprClass:
2523 case Stmt::CoawaitExprClass:
2526 case Stmt::SEHExceptStmtClass:
2529 case Stmt::SEHFinallyStmtClass:
2532 case Stmt::SEHLeaveStmtClass:
2535 case Stmt::SEHTryStmtClass:
2538 case Stmt::UnaryExprOrTypeTraitExprClass:
2542 case Stmt::StmtExprClass:
2545 case Stmt::SwitchStmtClass:
2548 case Stmt::UnaryOperatorClass:
2551 case Stmt::WhileStmtClass:
2554 case Stmt::ArrayInitLoopExprClass:
2559CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
2560 if (asc.alwaysAdd(*
this, S)) {
2562 appendStmt(
Block, S);
2565 return VisitChildren(S);
2569CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
2570 CFGBlock *B =
Block;
2574 reverse_children RChildren(S, *Context);
2575 for (Stmt *Child : RChildren) {
2577 if (CFGBlock *R = Visit(Child))
2583CFGBlock *CFGBuilder::VisitCallExprChildren(CallExpr *
C) {
2587 if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
C);
2588 OCE && OCE->isAssignmentOp()) {
2589 Visit(OCE->getArg(0));
2590 Visit(OCE->getArg(1));
2591 return Visit(OCE->getCallee());
2593 return VisitChildren(
C);
2596CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
2597 if (asc.alwaysAdd(*
this, ILE)) {
2599 appendStmt(
Block, ILE);
2601 CFGBlock *B =
Block;
2603 reverse_children RChildren(ILE, *Context);
2604 for (Stmt *Child : RChildren) {
2607 if (CFGBlock *R = Visit(Child))
2610 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2611 if (Stmt *Child = DIE->getExpr())
2612 if (CFGBlock *R = Visit(Child))
2619CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
2620 AddStmtChoice asc) {
2621 AddressTakenLabels.insert(A->
getLabel());
2623 if (asc.alwaysAdd(*
this, A)) {
2625 appendStmt(
Block, A);
2634 "expected fallthrough not to have children");
2635 return isFallthrough;
2642 "expected [[assume]] not to have children");
2643 return hasAssumeAttr;
2646CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
2647 AddStmtChoice asc) {
2657 if (isInterestingAttribute && asc.alwaysAdd(*
this, A)) {
2659 appendStmt(
Block, A);
2662 return VisitChildren(A);
2665CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {
2666 if (asc.alwaysAdd(*
this, U)) {
2668 appendStmt(
Block, U);
2674 return Visit(U->
getSubExpr(), AddStmtChoice());
2677CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
2678 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
2679 appendStmt(ConfluenceBlock, B);
2684 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2685 ConfluenceBlock).first;
2688std::pair<CFGBlock*, CFGBlock*>
2689CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
2691 CFGBlock *TrueBlock,
2692 CFGBlock *FalseBlock) {
2697 CFGBlock *RHSBlock, *ExitBlock;
2700 if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
2701 if (B_RHS->isLogicalOp()) {
2702 std::tie(RHSBlock, ExitBlock) =
2703 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2711 ExitBlock = RHSBlock = createBlock(
false);
2716 TryResult KnownVal = tryEvaluateBool(RHS);
2717 if (!KnownVal.isKnown())
2718 KnownVal = tryEvaluateBool(B);
2721 assert(TrueBlock == FalseBlock);
2722 addSuccessor(RHSBlock, TrueBlock);
2726 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2727 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2731 RHSBlock = addStmt(RHS);
2736 return std::make_pair(
nullptr,
nullptr);
2741 if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
2742 if (B_LHS->isLogicalOp()) {
2744 FalseBlock = RHSBlock;
2746 TrueBlock = RHSBlock;
2751 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2756 CFGBlock *LHSBlock = createBlock(
false);
2760 CFGBlock *EntryLHSBlock = addStmt(LHS);
2763 return std::make_pair(
nullptr,
nullptr);
2766 TryResult KnownVal = tryEvaluateBool(LHS);
2770 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2771 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2774 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2775 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2778 return std::make_pair(EntryLHSBlock, ExitBlock);
2781CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
2782 AddStmtChoice asc) {
2785 return VisitLogicalOperator(B);
2789 appendStmt(
Block, B);
2791 return addStmt(B->
getLHS());
2795 if (asc.alwaysAdd(*
this, B)) {
2797 appendStmt(
Block, B);
2800 return Visit(B->
getRHS());
2803 if (asc.alwaysAdd(*
this, B)) {
2805 appendStmt(
Block, B);
2811 CFGBlock *RBlock = Visit(B->
getRHS());
2812 CFGBlock *LBlock = Visit(B->
getLHS());
2816 return (LBlock ? LBlock : RBlock);
2819CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
2820 if (asc.alwaysAdd(*
this, E)) {
2822 appendStmt(
Block, E);
2827CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
2834 Block = createBlock(
false);
2835 Block->setTerminator(B);
2839 if (BreakJumpTarget.block) {
2840 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2841 addSuccessor(
Block, BreakJumpTarget.block);
2866 if (BuiltinID != Builtin::BI__assume &&
2867 BuiltinID != Builtin::BI__builtin_assume)
2873CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *
C, AddStmtChoice asc) {
2875 QualType calleeType =
C->getCallee()->getType();
2881 if (!boundType.
isNull()) calleeType = boundType;
2887 bool AddEHEdge =
false;
2897 bool OmitArguments =
false;
2899 if (FunctionDecl *FD =
C->getDirectCallee()) {
2904 if (!FD->isVariadic())
2905 findConstructionContextsForArguments(
C);
2907 if (FD->isNoReturn() || FD->isAnalyzerNoReturn() ||
2908 C->isBuiltinAssumeFalse(*Context))
2910 if (FD->
hasAttr<NoThrowAttr>())
2913 FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2914 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2915 OmitArguments =
true;
2918 if (!
CanThrow(
C->getCallee(), *Context))
2921 if (OmitArguments) {
2922 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2923 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2926 return Visit(
C->getCallee());
2929 if (!NoReturn && !AddEHEdge) {
2933 return VisitCallExprChildren(
C);
2943 Block = createNoReturnBlock();
2945 Block = createBlock();
2951 if (TryTerminatedBlock)
2952 addSuccessor(
Block, TryTerminatedBlock);
2954 addSuccessor(
Block, &cfg->getExit());
2957 return VisitCallExprChildren(
C);
2960CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *
C,
2961 AddStmtChoice asc) {
2962 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
2963 appendStmt(ConfluenceBlock,
C);
2967 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2968 Succ = ConfluenceBlock;
2970 CFGBlock *LHSBlock = Visit(
C->getLHS(), alwaysAdd);
2974 Succ = ConfluenceBlock;
2976 CFGBlock *RHSBlock = Visit(
C->getRHS(), alwaysAdd);
2980 Block = createBlock(
false);
2982 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2983 addSuccessor(
Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2984 addSuccessor(
Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2986 return addStmt(
C->getCond());
2990 bool ExternallyDestructed) {
2991 LocalScope::const_iterator scopeBeginPos = ScopePos;
2992 addLocalScopeForStmt(
C);
2997 addAutomaticObjHandling(ScopePos, scopeBeginPos,
C);
3000 CFGBlock *LastBlock =
Block;
3002 for (Stmt *S : llvm::reverse(
C->body())) {
3005 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
3006 ExternallyDestructed);
3009 LastBlock = newBlock;
3014 ExternallyDestructed =
false;
3020CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *
C,
3021 AddStmtChoice asc) {
3022 const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(
C);
3023 const OpaqueValueExpr *opaqueValue = (BCO ? BCO->
getOpaqueValue() :
nullptr);
3027 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
3028 appendStmt(ConfluenceBlock,
C);
3032 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
3038 Succ = ConfluenceBlock;
3040 CFGBlock *LHSBlock =
nullptr;
3041 const Expr *trueExpr =
C->getTrueExpr();
3042 if (trueExpr != opaqueValue) {
3043 LHSBlock = Visit(
C->getTrueExpr(), alwaysAdd);
3049 LHSBlock = ConfluenceBlock;
3052 Succ = ConfluenceBlock;
3053 CFGBlock *RHSBlock = Visit(
C->getFalseExpr(), alwaysAdd);
3058 if (BinaryOperator *
Cond =
3059 dyn_cast<BinaryOperator>(
C->getCond()->IgnoreParens()))
3060 if (
Cond->isLogicalOp())
3061 return VisitLogicalOperator(
Cond,
C, LHSBlock, RHSBlock).first;
3064 Block = createBlock(
false);
3067 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
3068 addSuccessor(
Block, LHSBlock, !KnownVal.isFalse());
3069 addSuccessor(
Block, RHSBlock, !KnownVal.isTrue());
3071 Expr *condExpr =
C->getCond();
3076 if (condExpr != opaqueValue)
3084 return addStmt(condExpr);
3087CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
3095 return VisitDeclSubExpr(DS);
3097 CFGBlock *B =
nullptr;
3106 DeclGroupRef DG(*I);
3109 cfg->addSyntheticDeclStmt(DSNew, DS);
3112 B = VisitDeclSubExpr(DSNew);
3120CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
3121 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
3123 if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl())) {
3125 const Type *T = TND->getUnderlyingType().getTypePtr();
3130 appendStmt(
Block, DS);
3132 CFGBlock *LastBlock =
Block;
3133 for (
const VariableArrayType *VA =
FindVA(T); VA !=
nullptr;
3134 VA =
FindVA(VA->getElementType().getTypePtr())) {
3135 if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
3136 LastBlock = NewBlock;
3149 bool HasTemporaries =
false;
3152 CFGBlock *blockAfterStaticInit =
nullptr;
3163 blockAfterStaticInit = Succ;
3172 if (HasTemporaries &&
3175 TempDtorContext Context;
3179 addFullExprCleanupMarker(Context);
3185 if (
const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
3186 for (
auto *BD : llvm::reverse(DD->bindings())) {
3187 if (
auto *VD = BD->getHoldingVar()) {
3188 DeclGroupRef DG(VD);
3191 cfg->addSyntheticDeclStmt(DSNew, DS);
3192 Block = VisitDeclSubExpr(DSNew);
3198 appendStmt(
Block, DS);
3202 const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(
Init);
3204 findConstructionContexts(
3206 AILE ? AILE->getSubExpr() :
Init);
3211 CFGBlock *LastBlock =
Block;
3214 if (HasTemporaries) {
3218 if (CFGBlock *newBlock = Visit(EC->
getSubExpr()))
3219 LastBlock = newBlock;
3222 if (CFGBlock *newBlock = Visit(
Init))
3223 LastBlock = newBlock;
3231 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
3232 if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3233 LastBlock = newBlock;
3236 maybeAddScopeBeginForVarDecl(
Block, VD, DS);
3239 if (ScopePos && VD == *ScopePos)
3242 CFGBlock *B = LastBlock;
3243 if (blockAfterStaticInit) {
3245 Block = createBlock(
false);
3246 Block->setTerminator(DS);
3247 addSuccessor(
Block, blockAfterStaticInit);
3248 addSuccessor(
Block, B);
3255CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
3265 SaveAndRestore save_scope_pos(ScopePos);
3269 addLocalScopeForStmt(
Init);
3274 addLocalScopeForVarDecl(VD);
3276 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3287 CFGBlock *ElseBlock = Succ;
3289 if (Stmt *Else = I->
getElse()) {
3290 SaveAndRestore sv(Succ);
3299 addLocalScopeAndDtors(Else);
3301 ElseBlock = addStmt(Else);
3304 ElseBlock = sv.get();
3312 CFGBlock *ThenBlock;
3316 SaveAndRestore sv(Succ);
3322 addLocalScopeAndDtors(Then);
3324 ThenBlock = addStmt(Then);
3330 ThenBlock = createBlock(
false);
3331 addSuccessor(ThenBlock, sv.get());
3345 BinaryOperator *
Cond =
3349 CFGBlock *LastBlock;
3351 LastBlock = VisitLogicalOperator(
Cond, I, ThenBlock, ElseBlock).first;
3354 Block = createBlock(
false);
3357 Block->setTerminator(I);
3362 KnownVal = tryEvaluateBool(I->
getCond());
3366 addSuccessor(
Block, ThenBlock, !KnownVal.isFalse());
3367 addSuccessor(
Block, ElseBlock, !KnownVal.isTrue());
3375 LastBlock = addStmt(I->
getCond());
3381 LastBlock = addStmt(
const_cast<DeclStmt *
>(DS));
3388 LastBlock = addStmt(
Init);
3394CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
3404 Block = createBlock(
false);
3406 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3408 if (
auto *R = dyn_cast<ReturnStmt>(S))
3409 findConstructionContexts(
3415 if (!
Block->hasNoReturnElement())
3416 addSuccessor(
Block, &cfg->getExit());
3419 appendStmt(
Block, S);
3422 if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3423 if (Expr *O = RS->getRetValue())
3424 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3436 if (CFGBlock *R = Visit(RV))
3442CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
3443 AddStmtChoice asc) {
3447 if (asc.alwaysAdd(*
this, E)) {
3449 appendStmt(
Block, E);
3451 CFGBlock *B =
Block;
3463CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
3469 SaveAndRestore save_scope_pos(ScopePos);
3472 CFGBlock *SEHExceptBlock =
Block;
3473 if (!SEHExceptBlock)
3474 SEHExceptBlock = createBlock();
3476 appendStmt(SEHExceptBlock, ES);
3488 return SEHExceptBlock;
3491CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
3492 return VisitCompoundStmt(FS->
getBlock(),
false);
3495CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
3502 Block = createBlock(
false);
3503 Block->setTerminator(LS);
3507 if (SEHLeaveJumpTarget.block) {
3508 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3509 addSuccessor(
Block, SEHLeaveJumpTarget.block);
3516CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
3519 CFGBlock *SEHTrySuccessor =
nullptr;
3524 SEHTrySuccessor =
Block;
3525 }
else SEHTrySuccessor = Succ;
3531 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3534 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3541 Succ = SEHTrySuccessor;
3543 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3548 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3550 if (PrevSEHTryTerminatedBlock)
3551 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3553 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3556 Succ = SEHTrySuccessor;
3559 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3560 cfg->addTryDispatchBlock(TryTerminatedBlock);
3565 SaveAndRestore save_break(SEHLeaveJumpTarget);
3566 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3568 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3573CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
3576 CFGBlock *LabelBlock =
Block;
3579 LabelBlock = createBlock();
3581 assert(!LabelMap.contains(L->
getDecl()) &&
"label already in map");
3582 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3601CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
3602 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3604 if (Expr *CopyExpr = CI.getCopyExpr()) {
3605 CFGBlock *Tmp = Visit(CopyExpr);
3613CFGBlock *CFGBuilder::VisitLambdaExpr(
LambdaExpr *E, AddStmtChoice asc) {
3614 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3619 it != et; ++it, ++Idx) {
3620 if (Expr *
Init = *it) {
3624 dyn_cast<ArrayInitLoopExpr>(
Init));
3627 cfg->getBumpVectorContext(), {E, Idx}),
3628 AILEInit ? AILEInit :
Init);
3630 CFGBlock *Tmp = Visit(
Init);
3638CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
3642 Block = createBlock(
false);
3643 Block->setTerminator(G);
3646 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3648 if (I == LabelMap.end())
3650 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3652 JumpTarget JT = I->second;
3653 addSuccessor(
Block, JT.block);
3654 addScopeChangesHandling(ScopePos, JT.scopePosition, G);
3660CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
3665 return VisitStmt(G, asc);
3672 Block = createBlock();
3673 Block->setTerminator(G);
3675 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3678 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3679 return VisitChildren(G);
3682CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
3683 CFGBlock *LoopSuccessor =
nullptr;
3687 SaveAndRestore save_scope_pos(ScopePos);
3693 addLocalScopeForStmt(
Init);
3694 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3697 addLocalScopeForVarDecl(VD);
3698 LocalScope::const_iterator ContinueScopePos = ScopePos;
3700 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3709 LoopSuccessor =
Block;
3711 LoopSuccessor = Succ;
3715 SaveAndRestore save_break(BreakJumpTarget);
3716 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3718 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3725 SaveAndRestore save_Block(
Block), save_Succ(Succ);
3726 SaveAndRestore save_continue(ContinueJumpTarget);
3731 Block = Succ = TransitionBlock = createBlock(
false);
3732 TransitionBlock->setLoopTarget(F);
3737 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3739 if (Stmt *I = F->
getInc()) {
3747 assert(
Block == Succ);
3755 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3756 ContinueJumpTarget.block->setLoopTarget(F);
3762 addLocalScopeAndDtors(F->
getBody());
3766 BodyBlock = addStmt(F->
getBody());
3771 BodyBlock = ContinueJumpTarget.block;
3780 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3784 SaveAndRestore save_scope_pos(ScopePos);
3788 if (BinaryOperator *
Cond =
3789 dyn_cast_or_null<BinaryOperator>(
C ?
C->IgnoreParens() :
nullptr))
3790 if (
Cond->isLogicalOp()) {
3791 std::tie(EntryConditionBlock, ExitConditionBlock) =
3792 VisitLogicalOperator(
Cond, F, BodyBlock, LoopSuccessor);
3797 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3798 ExitConditionBlock->setTerminator(F);
3801 TryResult KnownVal(
true);
3807 Block = ExitConditionBlock;
3808 EntryConditionBlock = addStmt(
C);
3817 findConstructionContexts(
3820 appendStmt(
Block, DS);
3821 EntryConditionBlock = addStmt(
Init);
3822 assert(
Block == EntryConditionBlock);
3823 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3827 if (
Block && badCFG)
3830 KnownVal = tryEvaluateBool(
C);
3834 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3837 addSuccessor(ExitConditionBlock,
3838 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3842 addSuccessor(TransitionBlock, EntryConditionBlock);
3845 Succ = EntryConditionBlock;
3850 SaveAndRestore save_scope_pos(ScopePos);
3851 ScopePos = LoopBeginScopePos;
3852 Block = createBlock();
3859 Succ = EntryConditionBlock;
3860 return EntryConditionBlock;
3864CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
3865 AddStmtChoice asc) {
3866 findConstructionContexts(
3870 return VisitStmt(MTE, asc);
3873CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
3874 if (asc.alwaysAdd(*
this, M)) {
3876 appendStmt(
Block, M);
3881CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
3913 CFGBlock *LoopSuccessor =
nullptr;
3918 LoopSuccessor =
Block;
3921 LoopSuccessor = Succ;
3924 CFGBlock *ExitConditionBlock = createBlock(
false);
3932 appendStmt(ExitConditionBlock, S);
3933 Block = ExitConditionBlock;
3938 CFGBlock *EntryConditionBlock = Visit(S->
getElement(),
3939 AddStmtChoice::NotAlwaysAdd);
3948 Succ = EntryConditionBlock;
3953 SaveAndRestore save_Block(
Block), save_Succ(Succ);
3954 SaveAndRestore save_continue(ContinueJumpTarget),
3955 save_break(BreakJumpTarget);
3960 CFGBlock *LoopBackBlock =
nullptr;
3961 Succ = LoopBackBlock = createBlock();
3964 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3965 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3967 CFGBlock *BodyBlock = addStmt(S->
getBody());
3970 BodyBlock = ContinueJumpTarget.block;
3977 addSuccessor(ExitConditionBlock, BodyBlock);
3982 addSuccessor(ExitConditionBlock, LoopSuccessor);
3985 Block = createBlock();
3989CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
3995CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
4013 appendStmt(
Block, S);
4019CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
4023 appendStmt(
Block, E);
4025 CFGBlock *lastBlock =
Block;
4034 if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
4035 Semantic = OVE->getSourceExpr();
4037 if (CFGBlock *B = Visit(Semantic))
4044CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
4045 CFGBlock *LoopSuccessor =
nullptr;
4049 SaveAndRestore save_scope_pos(ScopePos);
4053 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
4055 addLocalScopeForVarDecl(VD);
4056 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4065 LoopSuccessor =
Block;
4068 LoopSuccessor = Succ;
4071 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
4078 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4079 SaveAndRestore save_continue(ContinueJumpTarget),
4080 save_break(BreakJumpTarget);
4084 Succ = TransitionBlock = createBlock(
false);
4085 TransitionBlock->setLoopTarget(W);
4086 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
4089 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4092 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4097 addLocalScopeAndDtors(W->
getBody());
4100 BodyBlock = addStmt(W->
getBody());
4103 BodyBlock = ContinueJumpTarget.block;
4104 else if (
Block && badCFG)
4111 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
4118 if (BinaryOperator *
Cond = dyn_cast<BinaryOperator>(
C->IgnoreParens()))
4119 if (
Cond->isLogicalOp()) {
4120 std::tie(EntryConditionBlock, ExitConditionBlock) =
4121 VisitLogicalOperator(
Cond, W, BodyBlock, LoopSuccessor);
4126 ExitConditionBlock = createBlock(
false);
4132 Block = ExitConditionBlock;
4133 Block = EntryConditionBlock = addStmt(
C);
4142 findConstructionContexts(
4144 const_cast<DeclStmt *
>(DS)),
4146 appendStmt(
Block, DS);
4147 EntryConditionBlock = addStmt(
Init);
4148 assert(
Block == EntryConditionBlock);
4149 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
4153 if (
Block && badCFG)
4157 const TryResult& KnownVal = tryEvaluateBool(
C);
4160 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
4163 addSuccessor(ExitConditionBlock,
4164 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4168 addSuccessor(TransitionBlock, EntryConditionBlock);
4175 Succ = EntryConditionBlock;
4176 return EntryConditionBlock;
4179CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
4180 AddStmtChoice asc) {
4181 if (asc.alwaysAdd(*
this, A)) {
4183 appendStmt(
Block, A);
4186 CFGBlock *B =
Block;
4198CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {
4204 SaveAndRestore save_scope_pos(ScopePos);
4209 CFGBlock *CatchBlock =
Block;
4211 CatchBlock = createBlock();
4213 appendStmt(CatchBlock, CS);
4228CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
4234 Block = createBlock(
false);
4236 if (TryTerminatedBlock)
4238 addSuccessor(
Block, TryTerminatedBlock);
4241 addSuccessor(
Block, &cfg->getExit());
4245 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4248CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {
4251 CFGBlock *TrySuccessor =
nullptr;
4256 TrySuccessor =
Block;
4258 TrySuccessor = Succ;
4264 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4267 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4271 bool HasCatchAll =
false;
4272 for (ObjCAtCatchStmt *CS : Terminator->
catch_stmts()) {
4274 Succ = TrySuccessor;
4279 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4284 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4289 if (PrevTryTerminatedBlock)
4290 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4292 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4296 Succ = TrySuccessor;
4299 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4300 cfg->addTryDispatchBlock(TryTerminatedBlock);
4302 assert(Terminator->
getTryBody() &&
"try must contain a non-NULL body");
4307CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
4308 AddStmtChoice asc) {
4309 findConstructionContextsForArguments(ME);
4312 appendObjCMessage(
Block, ME);
4314 return VisitChildren(ME);
4317CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
4323 Block = createBlock(
false);
4325 if (TryTerminatedBlock)
4327 addSuccessor(
Block, TryTerminatedBlock);
4330 addSuccessor(
Block, &cfg->getExit());
4334 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4337CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {
4338 if (asc.alwaysAdd(*
this, S)) {
4340 appendStmt(
Block, S);
4350 return VisitChildren(S);
4356CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
4357 CFGBlock *LoopSuccessor =
nullptr;
4366 LoopSuccessor =
Block;
4368 LoopSuccessor = Succ;
4373 CFGBlock *ExitConditionBlock = createBlock(
false);
4374 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4382 Block = ExitConditionBlock;
4383 EntryConditionBlock = addStmt(
C);
4391 Succ = EntryConditionBlock;
4394 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
4397 CFGBlock *BodyBlock =
nullptr;
4402 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4403 SaveAndRestore save_continue(ContinueJumpTarget),
4404 save_break(BreakJumpTarget);
4407 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4410 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4418 addLocalScopeAndDtors(D->
getBody());
4421 BodyBlock = addStmt(D->
getBody());
4424 BodyBlock = EntryConditionBlock;
4437 CFGBlock *LoopBackBlock = createBlock();
4440 if (!KnownVal.isFalse())
4442 addSuccessor(ExitConditionBlock, LoopBackBlock);
4444 addSuccessor(ExitConditionBlock,
nullptr);
4449 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4460CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *
C) {
4467 Block = createBlock(
false);
4472 if (ContinueJumpTarget.block) {
4473 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,
C);
4474 addSuccessor(
Block, ContinueJumpTarget.block);
4481CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
4482 AddStmtChoice asc) {
4483 if (asc.alwaysAdd(*
this, E)) {
4485 appendStmt(
Block, E);
4491 if (E->
getKind() != UETT_SizeOf)
4494 CFGBlock *lastBlock =
Block;
4498 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4499 lastBlock = addStmt(VA->getSizeExpr());
4506CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
4507 if (asc.alwaysAdd(*
this, SE)) {
4509 appendStmt(
Block, SE);
4511 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4514CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
4517 CFGBlock *SwitchSuccessor =
nullptr;
4521 SaveAndRestore save_scope_pos(ScopePos);
4525 addLocalScopeForStmt(
Init);
4530 addLocalScopeForVarDecl(VD);
4532 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4537 SwitchSuccessor =
Block;
4538 }
else SwitchSuccessor = Succ;
4541 SaveAndRestore save_switch(SwitchTerminatedBlock),
4542 save_default(DefaultCaseBlock);
4543 SaveAndRestore save_break(BreakJumpTarget);
4548 DefaultCaseBlock = SwitchSuccessor;
4551 SwitchTerminatedBlock = createBlock(
false);
4555 Succ = SwitchSuccessor;
4556 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4561 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4566 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered,
false);
4569 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4570 Expr::EvalResult result;
4571 bool b = tryEvaluate(Terminator->
getCond(), result);
4572 SaveAndRestore save_switchCond(switchCond,
b ? &result :
nullptr);
4577 addLocalScopeAndDtors(Terminator->
getBody());
4579 addStmt(Terminator->
getBody());
4593 bool SwitchAlwaysHasSuccessor =
false;
4594 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4595 SwitchAlwaysHasSuccessor |=
4598 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4599 !SwitchAlwaysHasSuccessor);
4603 Block = SwitchTerminatedBlock;
4604 CFGBlock *LastBlock = addStmt(Terminator->
getCond());
4612 LastBlock = addStmt(
Init);
4613 maybeAddScopeBeginForVarDecl(LastBlock, VD,
Init);
4620 LastBlock = addStmt(
Init);
4633 bool addCase =
false;
4635 if (!switchExclusivelyCovered) {
4639 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4641 if (condInt == lhsInt) {
4643 switchExclusivelyCovered =
true;
4645 else if (condInt > lhsInt) {
4649 if (V2 >= condInt) {
4651 switchExclusivelyCovered =
true;
4662CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
4665 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4672 CFGBlock *currentBlock = createBlock(
false);
4676 addSuccessor(LastBlock, currentBlock);
4678 TopBlock = currentBlock;
4680 addSuccessor(SwitchTerminatedBlock,
4683 ? currentBlock :
nullptr);
4685 LastBlock = currentBlock;
4693 CFGBlock *CaseBlock =
Block;
4695 CaseBlock = createBlock();
4706 assert(SwitchTerminatedBlock);
4707 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4715 addSuccessor(LastBlock, CaseBlock);
4725CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
4729 DefaultCaseBlock =
Block;
4731 if (!DefaultCaseBlock)
4732 DefaultCaseBlock = createBlock();
4736 DefaultCaseBlock->
setLabel(Terminator);
4751 Succ = DefaultCaseBlock;
4753 return DefaultCaseBlock;
4756CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
4759 CFGBlock *TrySuccessor =
nullptr;
4764 TrySuccessor =
Block;
4766 TrySuccessor = Succ;
4768 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4771 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4775 bool HasCatchAll =
false;
4776 for (
unsigned I = 0, E = Terminator->
getNumHandlers(); I != E; ++I) {
4778 Succ = TrySuccessor;
4779 CXXCatchStmt *CS = Terminator->
getHandler(I);
4784 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4789 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4792 if (PrevTryTerminatedBlock)
4793 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4795 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4799 Succ = TrySuccessor;
4802 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4803 cfg->addTryDispatchBlock(TryTerminatedBlock);
4805 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4810CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
4816 SaveAndRestore save_scope_pos(ScopePos);
4821 LocalScope::const_iterator BeginScopePos = ScopePos;
4822 addLocalScopeForVarDecl(VD);
4823 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4829 CFGBlock *CatchBlock =
Block;
4831 CatchBlock = createBlock();
4837 appendStmt(CatchBlock, CS);
4853CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
4868 SaveAndRestore save_scope_pos(ScopePos);
4873 addLocalScopeForStmt(
Init);
4875 addLocalScopeForStmt(Range);
4877 addLocalScopeForStmt(Begin);
4879 addLocalScopeForStmt(End);
4880 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4882 LocalScope::const_iterator ContinueScopePos = ScopePos;
4886 CFGBlock *LoopSuccessor =
nullptr;
4890 LoopSuccessor =
Block;
4892 LoopSuccessor = Succ;
4896 SaveAndRestore save_break(BreakJumpTarget);
4897 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4900 CFGBlock *ConditionBlock = createBlock(
false);
4905 Block = ConditionBlock;
4906 CFGBlock *BeginConditionBlock = addStmt(
C);
4909 assert(BeginConditionBlock == ConditionBlock &&
4910 "condition block in for-range was unexpectedly complex");
4911 (void)BeginConditionBlock;
4916 Succ = ConditionBlock;
4919 TryResult KnownVal(
true);
4922 KnownVal = tryEvaluateBool(S->
getCond());
4929 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4930 SaveAndRestore save_continue(ContinueJumpTarget);
4935 Succ = addStmt(S->
getInc());
4938 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4942 ContinueJumpTarget.block->setLoopTarget(S);
4956 addLocalScopeAndDtors(S->
getBody());
4968 addSuccessor(ConditionBlock,
4969 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
4974 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4977 Block = createBlock();
4986CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
4988 bool ExternallyDestructed) {
4992 TempDtorContext Context;
4993 VisitForTemporaries(E->
getSubExpr(), ExternallyDestructed, Context);
4995 addFullExprCleanupMarker(Context);
4999 asc = asc.withAlwaysAdd(
true);
5004CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
5005 AddStmtChoice asc) {
5006 if (asc.alwaysAdd(*
this, E)) {
5008 appendStmt(
Block, E);
5010 findConstructionContexts(
5015 asc = asc.withAlwaysAdd(
false);
5020CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *
C,
5021 AddStmtChoice asc) {
5025 findConstructionContextsForArguments(
C);
5026 appendConstructor(
C);
5028 return VisitChildren(
C);
5031CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
5032 AddStmtChoice asc) {
5034 appendStmt(
Block, NE);
5036 findConstructionContexts(
5038 const_cast<CXXConstructExpr *
>(
NE->getConstructExpr()));
5040 if (
NE->getInitializer())
5041 Block = Visit(
NE->getInitializer());
5044 appendNewAllocator(
Block, NE);
5046 if (
NE->isArray() && *
NE->getArraySize())
5047 Block = Visit(*
NE->getArraySize());
5050 E =
NE->placement_arg_end(); I != E; ++I)
5056CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
5057 AddStmtChoice asc) {
5059 appendStmt(
Block, DE);
5066 appendDeleteDtor(
Block, RD, DE);
5070 return VisitChildren(DE);
5073CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
5074 AddStmtChoice asc) {
5075 if (asc.alwaysAdd(*
this, E)) {
5077 appendStmt(
Block, E);
5079 asc = asc.withAlwaysAdd(
false);
5084CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
5085 AddStmtChoice asc) {
5089 findConstructionContextsForArguments(E);
5090 appendConstructor(E);
5092 return VisitChildren(E);
5095CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
5096 AddStmtChoice asc) {
5097 if (asc.alwaysAdd(*
this, E)) {
5099 appendStmt(
Block, E);
5105 return Visit(E->
getSubExpr(), AddStmtChoice());
5108CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
5109 return Visit(E->
getSubExpr(), AddStmtChoice());
5112CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5114 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
5117 IBlock = createBlock(
false);
5118 cfg->setIndirectGotoBlock(IBlock);
5126 Block = createBlock(
false);
5127 Block->setTerminator(I);
5128 addSuccessor(
Block, IBlock);
5132CFGBlock *CFGBuilder::VisitForTemporaries(Stmt *E,
bool ExternallyDestructed,
5133 TempDtorContext &Context) {
5142 return VisitChildrenForTemporaries(E,
false, Context);
5144 case Stmt::InitListExprClass:
5145 return VisitChildrenForTemporaries(E, ExternallyDestructed, Context);
5147 case Stmt::BinaryOperatorClass:
5149 ExternallyDestructed, Context);
5151 case Stmt::CXXOperatorCallExprClass:
5152 return VisitCXXOperatorCallExprForTemporaryDtors(
5155 case Stmt::CXXBindTemporaryExprClass:
5156 return VisitCXXBindTemporaryExprForTemporaryDtors(
5159 case Stmt::BinaryConditionalOperatorClass:
5160 case Stmt::ConditionalOperatorClass:
5161 return VisitConditionalOperatorForTemporaries(
5164 case Stmt::ImplicitCastExprClass:
5169 case Stmt::CXXFunctionalCastExprClass:
5174 case Stmt::ConstantExprClass:
5178 case Stmt::ParenExprClass:
5182 case Stmt::MaterializeTemporaryExprClass: {
5185 if (BuildOpts.
AddLifetime && !ExternallyDestructed)
5187 SmallVector<const Expr *, 2> CommaLHSs;
5188 SmallVector<SubobjectAdjustment, 2> Adjustments;
5190 E =
const_cast<Expr *
>(
5193 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
5195 for (
const Expr *CommaLHS : CommaLHSs) {
5196 VisitForTemporaries(
const_cast<Expr *
>(CommaLHS),
5202 case Stmt::BlockExprClass:
5207 case Stmt::LambdaExprClass: {
5211 CFGBlock *B =
Block;
5212 for (Expr *
Init :
LE->capture_inits()) {
5214 if (CFGBlock *R = VisitForTemporaries(
5215 Init,
true, Context))
5222 case Stmt::StmtExprClass:
5227 case Stmt::CXXDefaultArgExprClass:
5231 case Stmt::CXXDefaultInitExprClass:
5237CFGBlock *CFGBuilder::VisitChildrenForTemporaries(Stmt *E,
5238 bool ExternallyDestructed,
5239 TempDtorContext &Context) {
5249 CFGBlock *B =
Block;
5253 VisitForTemporaries(Child, ExternallyDestructed, Context))
5259CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaries(
5260 BinaryOperator *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5264 CFGBlock *LHSBlock = VisitForTemporaries(E->
getLHS(),
false, Context);
5265 CFGBlock *RHSBlock =
5266 VisitForTemporaries(E->
getRHS(), ExternallyDestructed, Context);
5267 return RHSBlock ? RHSBlock : LHSBlock;
5271 VisitForTemporaries(E->
getLHS(),
false, Context);
5272 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
5273 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
5274 RHSExecuted.negate();
5279 TempDtorContext RHSContext(
5281 VisitForTemporaries(E->
getRHS(),
false, RHSContext);
5282 InsertTempDecisionBlock(RHSContext);
5285 Context.CollectedMTEs.append(RHSContext.CollectedMTEs);
5293 CFGBlock *RHSBlock = VisitForTemporaries(E->
getRHS(),
false, Context);
5294 CFGBlock *LHSBlock = VisitForTemporaries(E->
getLHS(),
false, Context);
5295 return LHSBlock ? LHSBlock : RHSBlock;
5299 return VisitChildrenForTemporaries(E, ExternallyDestructed, Context);
5302CFGBlock *CFGBuilder::VisitCXXOperatorCallExprForTemporaryDtors(
5303 CXXOperatorCallExpr *E, TempDtorContext &Context) {
5307 CFGBlock *RHSBlock = VisitForTemporaries(E->
getArg(1),
false, Context);
5308 CFGBlock *LHSBlock = VisitForTemporaries(E->
getArg(0),
false, Context);
5309 return LHSBlock ? LHSBlock : RHSBlock;
5311 return VisitChildrenForTemporaries(E,
false, Context);
5314CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5315 CXXBindTemporaryExpr *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5318 CFGBlock *B = VisitForTemporaries(E->
getSubExpr(),
true, Context);
5332 Block = createNoReturnBlock();
5333 }
else if (Context.needsTempDtorBranch()) {
5337 Block = createBlock();
5341 if (Context.needsTempDtorBranch()) {
5342 Context.setDecisionPoint(Succ, E);
5344 appendTemporaryDtor(
Block, E);
5350void CFGBuilder::InsertTempDecisionBlock(
const TempDtorContext &Context,
5351 CFGBlock *FalseSucc) {
5352 if (!Context.TerminatorExpr) {
5356 assert(Context.TerminatorExpr);
5357 CFGBlock *Decision = createBlock(
false);
5358 Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,
5360 addSuccessor(Decision,
Block, !Context.KnownExecuted.isFalse());
5361 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5362 !Context.KnownExecuted.isTrue());
5366CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaries(
5367 AbstractConditionalOperator *E,
bool ExternallyDestructed,
5368 TempDtorContext &Context) {
5369 VisitForTemporaries(E->
getCond(),
false, Context);
5370 CFGBlock *ConditionBlock =
Block;
5371 CFGBlock *ConditionSucc = Succ;
5372 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
5373 TryResult NegatedVal = ConditionVal;
5374 if (NegatedVal.isKnown()) NegatedVal.negate();
5376 TempDtorContext TrueContext(
5378 VisitForTemporaries(E->
getTrueExpr(), ExternallyDestructed, TrueContext);
5379 CFGBlock *TrueBlock =
Block;
5381 Block = ConditionBlock;
5382 Succ = ConditionSucc;
5383 TempDtorContext FalseContext(
5385 VisitForTemporaries(E->
getFalseExpr(), ExternallyDestructed, FalseContext);
5387 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5388 InsertTempDecisionBlock(FalseContext, TrueBlock);
5389 }
else if (TrueContext.TerminatorExpr) {
5391 InsertTempDecisionBlock(TrueContext);
5393 InsertTempDecisionBlock(FalseContext);
5396 Context.CollectedMTEs.append(TrueContext.CollectedMTEs);
5397 Context.CollectedMTEs.append(FalseContext.CollectedMTEs);
5403CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
5404 AddStmtChoice asc) {
5405 if (asc.alwaysAdd(*
this, D)) {
5407 appendStmt(
Block, D);
5411 CFGBlock *B =
Block;
5415 SmallVector<Stmt *, 8>
Used(
5416 OMPExecutableDirective::used_clauses_children(D->clauses()));
5417 for (Stmt *S : llvm::reverse(
Used)) {
5418 assert(S &&
"Expected non-null used-in-clause child.");
5419 if (CFGBlock *R = Visit(S))
5423 if (!D->isStandaloneDirective()) {
5424 Stmt *S = D->getRawStmt();
5426 addLocalScopeAndDtors(S);
5427 if (CFGBlock *R = addStmt(S))
5438 bool first_block =
begin() ==
end();
5442 Blocks.push_back(Mem, BlkBVC);
5446 Entry = Exit = &
back();
5455 llvm::TimeTraceScope TimeProfile(
"BuildCFG");
5456 CFGBuilder Builder(
C, BO);
5457 return Builder.buildCFG(D, Statement);
5472 auto IteratorAndFlag = Visited.insert(B);
5473 if (!IteratorAndFlag.second) {
5479 const CFGBlock *FirstReachableB =
nullptr;
5481 if (!AB.isReachable())
5484 if (FirstReachableB ==
nullptr) {
5485 FirstReachableB = &*AB;
5492 if (!FirstReachableB) {
5498 B = FirstReachableB;
5519 llvm_unreachable(
"getDestructorDecl should only be used with "
5530 if (
const Expr *
Init = var->getInit()) {
5577 llvm_unreachable(
"getKind() returned bogus value");
5585 : ReachableBlock(IsReachable ? B :
nullptr),
5586 UnreachableBlock(!IsReachable ? B :
nullptr,
5587 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5590 : ReachableBlock(B),
5591 UnreachableBlock(B == AlternateBlock ?
nullptr : AlternateBlock,
5592 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5602 Succs.push_back(Succ,
C);
5615 if (S->isAllEnumCasesCovered()) {
5633 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5634 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5638 signed currentBlock = 0;
5639 unsigned currStmt = 0;
5649 for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
5650 BI != BEnd; ++BI, ++j ) {
5651 if (std::optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
5652 const Stmt *stmt= SE->getStmt();
5653 std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
5656 switch (stmt->getStmtClass()) {
5657 case Stmt::DeclStmtClass:
5658 DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
5660 case Stmt::IfStmtClass: {
5661 const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
5666 case Stmt::ForStmtClass: {
5667 const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
5672 case Stmt::WhileStmtClass: {
5673 const VarDecl *var =
5674 cast<WhileStmt>(stmt)->getConditionVariable();
5679 case Stmt::SwitchStmtClass: {
5680 const VarDecl *var =
5681 cast<SwitchStmt>(stmt)->getConditionVariable();
5686 case Stmt::CXXCatchStmtClass: {
5687 const VarDecl *var =
5688 cast<CXXCatchStmt>(stmt)->getExceptionDecl();
5701 ~StmtPrinterHelper()
override =
default;
5703 const LangOptions &getLangOpts()
const {
return LangOpts; }
5704 void setBlockID(
signed i) { currentBlock = i; }
5705 void setStmtID(
unsigned i) { currStmt = i; }
5707 bool handledStmt(Stmt *S, raw_ostream &OS)
override {
5708 StmtMapTy::iterator I = StmtMap.find(S);
5710 if (I == StmtMap.end())
5713 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5714 && I->second.second == currStmt) {
5718 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5722 bool handleDecl(
const Decl *D, raw_ostream &OS) {
5723 DeclMapTy::iterator I = DeclMap.find(D);
5725 if (I == DeclMap.end()) {
5728 if (
auto *PVD = dyn_cast_or_null<ParmVarDecl>(D)) {
5729 OS <<
"[Parm: " << PVD->getNameAsString() <<
"]";
5735 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5736 && I->second.second == currStmt) {
5740 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5745class CFGBlockTerminatorPrint
5746 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5748 StmtPrinterHelper* Helper;
5749 PrintingPolicy Policy;
5752 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5753 const PrintingPolicy &Policy)
5754 :
OS(os), Helper(helper), Policy(Policy) {
5758 void VisitIfStmt(IfStmt *I) {
5761 C->printPretty(OS, Helper, Policy);
5765 void VisitStmt(Stmt *Terminator) {
5769 void VisitDeclStmt(DeclStmt *DS) {
5774 void VisitForStmt(ForStmt *F) {
5780 C->printPretty(OS, Helper, Policy);
5787 void VisitWhileStmt(WhileStmt *W) {
5790 C->printPretty(OS, Helper, Policy);
5793 void VisitDoStmt(DoStmt *D) {
5794 OS <<
"do ... while ";
5796 C->printPretty(OS, Helper, Policy);
5799 void VisitSwitchStmt(SwitchStmt *Terminator) {
5804 void VisitCXXTryStmt(CXXTryStmt *) {
OS <<
"try ..."; }
5806 void VisitObjCAtTryStmt(ObjCAtTryStmt *) {
OS <<
"@try ..."; }
5808 void VisitSEHTryStmt(SEHTryStmt *CS) {
OS <<
"__try ..."; }
5810 void VisitAbstractConditionalOperator(AbstractConditionalOperator*
C) {
5811 if (Stmt *
Cond =
C->getCond())
5813 OS <<
" ? ... : ...";
5816 void VisitChooseExpr(ChooseExpr *
C) {
5817 OS <<
"__builtin_choose_expr( ";
5818 if (Stmt *
Cond =
C->getCond())
5823 void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5829 void VisitBinaryOperator(BinaryOperator* B) {
5846 llvm_unreachable(
"Invalid logical operator.");
5850 void VisitExpr(Expr *E) {
5855 void print(CFGTerminator T) {
5861 OS <<
"(Temp Dtor) ";
5865 OS <<
"(See if most derived ctor has already initialized vbases)";
5887 OS <<
" (Base initializer)";
5889 OS <<
" (Delegating initializer)";
5891 OS <<
" (Member initializer)";
5895 StmtPrinterHelper &Helper,
5910 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5915 Stmts.push_back(SDSCC->getDeclStmt());
5920 Stmts.push_back(CDSCC->getDeclStmt());
5921 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5926 Stmts.push_back(NECC->getCXXNewExpr());
5931 Stmts.push_back(RSCC->getReturnStmt());
5937 Stmts.push_back(RSCC->getReturnStmt());
5938 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5943 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5944 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5949 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5950 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5951 Stmts.push_back(TOCC->getConstructorAfterElision());
5956 Helper.handledStmt(
const_cast<LambdaExpr *
>(LCC->getLambdaExpr()), OS);
5957 OS <<
"+" << LCC->getIndex();
5962 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5964 Helper.handledStmt(
const_cast<Stmt *
>(BTE), OS);
5967 Helper.handledStmt(
const_cast<Expr *
>(ACC->getCallLikeExpr()), OS);
5968 OS <<
"+" << ACC->getIndex();
5975 Helper.handledStmt(
const_cast<Stmt *
>(I), OS);
5979static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5980 const CFGElement &E,
bool TerminateWithNewLine =
true);
5983 bool TerminateWithNewLine)
const {
5985 StmtPrinterHelper Helper(
nullptr, LangOpts);
5986 print_elem(OS, Helper, *
this, TerminateWithNewLine);
5989static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5990 const CFGElement &E,
bool TerminateWithNewLine) {
5997 assert(S !=
nullptr &&
"Expecting non-null Stmt");
6000 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
6008 if (TerminateWithNewLine)
6017 Helper.handledStmt(B->
getRHS(),OS);
6018 if (TerminateWithNewLine)
6023 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
6027 OS <<
" (OperatorCall)";
6028 OS <<
" (CXXRecordTypedCall";
6032 OS <<
" (OperatorCall)";
6034 OS <<
" (BindTemporary)";
6036 OS <<
" (CXXConstructExpr";
6040 OS <<
", " << CCE->getType() <<
")";
6041 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
6043 <<
", " << CE->
getType() <<
")";
6047 if (
isa<Expr>(S) && TerminateWithNewLine)
6060 Helper.handleDecl(VD, OS);
6063 if (T->isReferenceType())
6067 T.getUnqualifiedType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
6068 OS <<
"() (Implicit destructor)";
6073 OS <<
"CleanupFunction ("
6079 OS <<
" (Lifetime ends)";
6084 size_t MTECount = MTEs.size();
6085 OS <<
"(FullExprCleanup collected " << MTECount
6086 << (MTECount > 1 ?
" MTEs: " :
" MTE: ");
6087 bool FirstMTE =
true;
6091 if (!Helper.handledStmt(MTE->
getSubExpr(), OS)) {
6109 OS <<
"CFGScopeBegin(";
6116 OS <<
"CFGScopeEnd(";
6123 OS <<
"CFGNewAllocator(";
6125 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
6137 OS <<
"->~" << RD->getName().str() <<
"()";
6138 OS <<
" (Implicit destructor)";
6145 OS <<
" (Base object destructor)";
6152 OS <<
"this->" << FD->
getName();
6153 OS <<
".~" << T->getAsCXXRecordDecl()->getName() <<
"()";
6154 OS <<
" (Member object destructor)";
6163 OS <<
"() (Temporary object destructor)";
6167 if (TerminateWithNewLine)
6173 StmtPrinterHelper &Helper,
bool print_edges,
6179 OS.changeColor(raw_ostream::YELLOW,
true);
6184 OS <<
" (ENTRY)]\n";
6185 else if (&B == &cfg->
getExit())
6188 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
6190 OS <<
" (NORETURN)]\n";
6206 if (
const Expr *LHS =
C->getLHS())
6208 if (
const Expr *RHS =
C->getRHS()) {
6223 if (
const VarDecl *PD = CS->getCatchParamDecl())
6234 llvm_unreachable(
"Invalid label statement in CFGBlock.");
6243 I != E ; ++I, ++j ) {
6248 OS << llvm::format(
"%3d", j) <<
": ";
6250 Helper.setStmtID(j);
6258 OS.changeColor(raw_ostream::GREEN);
6262 Helper.setBlockID(-1);
6265 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
6276 const raw_ostream::Colors Color = raw_ostream::BLUE;
6278 OS.changeColor(Color);
6286 OS.changeColor(Color);
6294 bool Reachable =
true;
6297 B = I->getPossiblyUnreachableBlock();
6302 OS <<
"(Unreachable)";
6313 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
6315 OS.changeColor(Color);
6323 OS.changeColor(Color);
6332 bool Reachable =
true;
6335 B = I->getPossiblyUnreachableBlock();
6341 OS <<
"(Unreachable)";
6357 print(llvm::errs(), LO, ShowColors);
6362 StmtPrinterHelper Helper(
this, LO);
6368 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
6373 print_block(OS,
this, **I, Helper,
true, ShowColors);
6388 bool ShowColors)
const {
6389 print(llvm::errs(), cfg, LO, ShowColors);
6400 StmtPrinterHelper Helper(cfg, LO);
6401 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
6408 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
6414 bool AddQuotes)
const {
6416 llvm::raw_string_ostream TempOut(Buf);
6439 if (llvm::any_of(*Blk, [](
const CFGElement &Elm) {
6440 if (std::optional<CFGStmt> StmtElm = Elm.
getAs<
CFGStmt>())
6460 DFSWorkList.push_back(StartBlk);
6461 while (!DFSWorkList.empty()) {
6462 const CFGBlock *Blk = DFSWorkList.pop_back_val();
6463 Visited.insert(Blk);
6472 for (
const auto &Succ : Blk->
succs()) {
6473 if (
const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
6477 DFSWorkList.push_back(SuccBlk);
6506 const Stmt *
Cond = StmtElem->getStmt();
6520 const Expr *E =
nullptr;
6526 case Stmt::CXXForRangeStmtClass:
6530 case Stmt::ForStmtClass:
6534 case Stmt::WhileStmtClass:
6538 case Stmt::DoStmtClass:
6542 case Stmt::IfStmtClass:
6546 case Stmt::ChooseExprClass:
6550 case Stmt::IndirectGotoStmtClass:
6554 case Stmt::SwitchStmtClass:
6558 case Stmt::BinaryConditionalOperatorClass:
6562 case Stmt::ConditionalOperatorClass:
6566 case Stmt::BinaryOperatorClass:
6570 case Stmt::ObjCForCollectionStmtClass:
6587 StmtPrinterHelper H(
this, LO);
6589 llvm::ViewGraph(
this,
"CFG");
6601 llvm::raw_string_ostream Out(OutStr);
6604 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
6607 for (
unsigned i = 0; i != OutStr.length(); ++i)
6608 if (OutStr[i] ==
'\n') {
6610 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)