39#include "llvm/ADT/APFloat.h"
40#include "llvm/ADT/APInt.h"
41#include "llvm/ADT/APSInt.h"
42#include "llvm/ADT/ArrayRef.h"
43#include "llvm/ADT/DenseMap.h"
44#include "llvm/ADT/STLExtras.h"
45#include "llvm/ADT/SetVector.h"
46#include "llvm/ADT/SmallPtrSet.h"
47#include "llvm/ADT/SmallVector.h"
48#include "llvm/Support/Allocator.h"
49#include "llvm/Support/Compiler.h"
50#include "llvm/Support/DOTGraphTraits.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/Format.h"
53#include "llvm/Support/GraphWriter.h"
54#include "llvm/Support/SaveAndRestore.h"
55#include "llvm/Support/TimeProfiler.h"
56#include "llvm/Support/raw_ostream.h"
70 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
71 if (
Expr *Ex = VD->getInit())
72 return Ex->getSourceRange().getEnd();
86 if (
const auto *CE = dyn_cast<CastExpr>(E)) {
87 if (CE->getCastKind() != CK_IntegralCast &&
88 CE->getCastKind() != CK_IntegralToFloating)
94 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
95 if (UO->getOpcode() != UO_Minus)
119static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
126 if (Constant ==
nullptr) {
130 else if (Op == BO_GE)
132 else if (Op == BO_LT)
134 else if (Op == BO_LE)
141 return std::make_tuple(MaybeDecl, Op, Constant);
192 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
194 AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
196 bool alwaysAdd(CFGBuilder &builder,
197 const Stmt *
stmt)
const;
201 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
202 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
232 using AutomaticVarsTy = BumpVector<VarDecl *>;
236 class const_iterator {
237 const LocalScope* Scope =
nullptr;
241 unsigned VarIter = 0;
247 const_iterator() =
default;
251 const_iterator(
const LocalScope& S,
unsigned I)
252 : Scope(&S), VarIter(I) {
255 if (VarIter == 0 && Scope)
259 VarDecl *
const* operator->()
const {
260 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
261 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
262 return &Scope->Vars[VarIter - 1];
265 const VarDecl *getFirstVarInScope()
const {
266 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
267 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
268 return Scope->Vars[0];
272 return *this->operator->();
275 const_iterator &operator++() {
279 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
285 const_iterator operator++(
int) {
286 const_iterator P = *
this;
291 bool operator==(
const const_iterator &rhs)
const {
292 return Scope == rhs.Scope && VarIter == rhs.VarIter;
294 bool operator!=(
const const_iterator &rhs)
const {
295 return !(*
this == rhs);
298 explicit operator bool()
const {
299 return *
this != const_iterator();
303 const_iterator shared_parent(const_iterator L);
304 bool pointsToFirstDeclaredVar() {
return VarIter == 1; }
305 bool inSameLocalScope(const_iterator rhs) {
return Scope == rhs.Scope; }
309 BumpVectorContext ctx;
312 AutomaticVarsTy Vars;
320 LocalScope(BumpVectorContext ctx, const_iterator P)
321 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
324 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
326 void addVar(VarDecl *VD) {
327 Vars.push_back(VD, ctx);
336int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
338 const_iterator F = *
this;
339 while (F.Scope != L.Scope) {
340 assert(F != const_iterator() &&
341 "L iterator is not reachable from F iterator.");
345 D += F.VarIter - L.VarIter;
353LocalScope::const_iterator
354LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
357 if ((*
this == const_iterator()) || (L == const_iterator())) {
358 return const_iterator();
361 const_iterator F = *
this;
362 if (F.inSameLocalScope(L)) {
364 F.VarIter = std::min(F.VarIter, L.VarIter);
368 llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;
370 ScopesOfL.try_emplace(L.Scope, L.VarIter);
371 if (L == const_iterator())
377 if (
auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {
379 F.VarIter = std::min(F.VarIter, LIt->getSecond());
382 assert(F != const_iterator() &&
383 "L iterator is not reachable from F iterator.");
393struct BlockScopePosPair {
394 CFGBlock *block =
nullptr;
395 LocalScope::const_iterator scopePosition;
397 BlockScopePosPair() =
default;
398 BlockScopePosPair(CFGBlock *
b, LocalScope::const_iterator scopePos)
399 : block(
b), scopePosition(scopePos) {}
410 TryResult() =
default;
411 TryResult(
bool b) :
X(
b ? 1 : 0) {}
413 bool isTrue()
const {
return X == 1; }
414 bool isFalse()
const {
return X == 0; }
415 bool isKnown()
const {
return X >= 0; }
426 if (!R1.isKnown() || !R2.isKnown())
428 return TryResult(R1.isTrue() && R2.isTrue());
433class reverse_children {
434 llvm::SmallVector<Stmt *, 12> childrenBuf;
438 reverse_children(Stmt *S, ASTContext &Ctx);
440 using iterator = ArrayRef<Stmt *>::reverse_iterator;
442 iterator begin()
const {
return children.rbegin(); }
443 iterator end()
const {
return children.rend(); }
448reverse_children::reverse_children(Stmt *S, ASTContext &Ctx) {
449 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
456 case Stmt::InitListExprClass: {
463 case Stmt::AttributedStmtClass: {
469 for (
const auto *Attr : AS->getAttrs()) {
470 if (
const auto *AssumeAttr = dyn_cast<CXXAssumeAttr>(Attr)) {
471 Expr *AssumeExpr = AssumeAttr->getAssumption();
473 childrenBuf.push_back(AssumeExpr);
480 llvm::append_range(childrenBuf, AS->children());
489 llvm::append_range(childrenBuf, S->
children());
511 using JumpTarget = BlockScopePosPair;
512 using JumpSource = BlockScopePosPair;
515 std::unique_ptr<CFG> cfg;
518 CFGBlock *
Block =
nullptr;
521 CFGBlock *Succ =
nullptr;
523 JumpTarget ContinueJumpTarget;
524 JumpTarget BreakJumpTarget;
525 JumpTarget SEHLeaveJumpTarget;
526 CFGBlock *SwitchTerminatedBlock =
nullptr;
527 CFGBlock *DefaultCaseBlock =
nullptr;
533 CFGBlock *TryTerminatedBlock =
nullptr;
536 LocalScope::const_iterator ScopePos;
539 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
544 using BackpatchBlocksTy = std::vector<JumpSource>;
545 BackpatchBlocksTy BackpatchBlocks;
548 using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
549 LabelSetTy AddressTakenLabels;
554 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
555 ConstructionContextMap;
558 const CFG::BuildOptions &BuildOpts;
561 bool switchExclusivelyCovered =
false;
562 Expr::EvalResult *switchCond =
nullptr;
564 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
565 const Stmt *lastLookup =
nullptr;
569 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
570 CachedBoolEvalsTy CachedBoolEvals;
573 explicit CFGBuilder(ASTContext *astContext,
574 const CFG::BuildOptions &buildOpts)
575 : Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}
578 std::unique_ptr<CFG> buildCFG(
const Decl *D, Stmt *Statement);
580 bool alwaysAdd(
const Stmt *
stmt);
584 CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
585 CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
586 CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
587 CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
588 CFGBlock *VisitBreakStmt(BreakStmt *B);
589 CFGBlock *VisitCallExpr(CallExpr *
C, AddStmtChoice asc);
590 CFGBlock *VisitCaseStmt(CaseStmt *
C);
591 CFGBlock *VisitChooseExpr(ChooseExpr *
C, AddStmtChoice asc);
592 CFGBlock *VisitCompoundStmt(
CompoundStmt *
C,
bool ExternallyDestructed);
593 CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *
C,
595 CFGBlock *VisitContinueStmt(ContinueStmt *
C);
596 CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
598 CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
599 CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *
C, AddStmtChoice asc);
600 CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
601 CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
602 CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
603 CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
605 CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *
C,
607 CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
608 CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
609 CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);
610 CFGBlock *VisitDeclStmt(DeclStmt *DS);
611 CFGBlock *VisitDeclSubExpr(DeclStmt *DS);
612 CFGBlock *VisitDefaultStmt(DefaultStmt *D);
613 CFGBlock *VisitDoStmt(DoStmt *D);
614 CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,
615 AddStmtChoice asc,
bool ExternallyDestructed);
616 CFGBlock *VisitForStmt(ForStmt *F);
617 CFGBlock *VisitGotoStmt(GotoStmt *G);
618 CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);
619 CFGBlock *VisitIfStmt(IfStmt *I);
620 CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
621 CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);
622 CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
623 CFGBlock *VisitLabelStmt(LabelStmt *L);
624 CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
625 CFGBlock *VisitLambdaExpr(
LambdaExpr *E, AddStmtChoice asc);
626 CFGBlock *VisitLogicalOperator(BinaryOperator *B);
627 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
630 CFGBlock *FalseBlock);
631 CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
633 CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
634 CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
635 CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
636 CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
637 CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
638 CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
639 CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
640 CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
641 CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
642 CFGBlock *VisitReturnStmt(Stmt *S);
643 CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,
645 CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
646 CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
647 CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
648 CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);
649 CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
650 CFGBlock *VisitSwitchStmt(SwitchStmt *S);
651 CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
653 CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
654 CFGBlock *VisitWhileStmt(WhileStmt *W);
655 CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);
657 CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
658 bool ExternallyDestructed =
false);
659 CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
660 CFGBlock *VisitChildren(Stmt *S);
661 CFGBlock *VisitCallExprChildren(CallExpr *
C);
662 CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
663 CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,
666 void maybeAddScopeBeginForVarDecl(CFGBlock *B,
const VarDecl *VD,
668 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
669 appendScopeBegin(B, VD, S);
700 struct TempDtorContext {
701 TempDtorContext() =
default;
702 TempDtorContext(TryResult KnownExecuted)
703 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
710 bool needsTempDtorBranch()
const {
711 return IsConditional && !TerminatorExpr;
716 void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {
721 void track(
const MaterializeTemporaryExpr *MTE) {
722 CollectedMTEs.push_back(MTE);
725 const bool IsConditional =
false;
726 SmallVector<const MaterializeTemporaryExpr *, 5> CollectedMTEs;
727 const TryResult KnownExecuted =
true;
728 CFGBlock *Succ =
nullptr;
729 CXXBindTemporaryExpr *TerminatorExpr =
nullptr;
734 CFGBlock *VisitForTemporaries(Stmt *E,
bool ExternallyDestructed,
735 TempDtorContext &Context);
736 CFGBlock *VisitChildrenForTemporaries(Stmt *E,
bool ExternallyDestructed,
737 TempDtorContext &Context);
738 CFGBlock *VisitBinaryOperatorForTemporaries(BinaryOperator *E,
739 bool ExternallyDestructed,
740 TempDtorContext &Context);
741 CFGBlock *VisitCXXOperatorCallExprForTemporaryDtors(CXXOperatorCallExpr *E,
742 TempDtorContext &Context);
743 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
744 CXXBindTemporaryExpr *E,
bool ExternallyDestructed, TempDtorContext &Context);
746 VisitConditionalOperatorForTemporaries(AbstractConditionalOperator *E,
747 bool ExternallyDestructed,
748 TempDtorContext &Context);
749 void InsertTempDecisionBlock(
const TempDtorContext &Context,
750 CFGBlock *FalseSucc =
nullptr);
760 void consumeConstructionContext(
const ConstructionContextLayer *Layer,
768 void findConstructionContexts(
const ConstructionContextLayer *Layer,
774 template <
typename CallLikeExpr,
775 typename = std::enable_if_t<
776 std::is_base_of_v<CallExpr, CallLikeExpr> ||
777 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
778 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
779 void findConstructionContextsForArguments(CallLikeExpr *E) {
780 for (
unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
781 Expr *Arg = E->getArg(i);
783 findConstructionContexts(
785 ConstructionContextItem(E, i)),
793 void cleanupConstructionContext(Expr *E);
795 void autoCreateBlock() {
if (!
Block)
Block = createBlock(); }
797 CFGBlock *createBlock(
bool add_successor =
true);
798 CFGBlock *createNoReturnBlock();
800 CFGBlock *addStmt(Stmt *S) {
801 return Visit(S, AddStmtChoice::AlwaysAdd);
804 CFGBlock *addInitializer(CXXCtorInitializer *I);
805 void addLoopExit(
const Stmt *LoopStmt);
806 void addAutomaticObjHandling(LocalScope::const_iterator B,
807 LocalScope::const_iterator E, Stmt *S);
808 void addAutomaticObjDestruction(LocalScope::const_iterator B,
809 LocalScope::const_iterator E, Stmt *S);
810 void addScopeExitHandling(LocalScope::const_iterator B,
811 LocalScope::const_iterator E, Stmt *S);
812 void addImplicitDtorsForDestructor(
const CXXDestructorDecl *DD);
813 void addScopeChangesHandling(LocalScope::const_iterator SrcPos,
814 LocalScope::const_iterator DstPos,
816 void addFullExprCleanupMarker(TempDtorContext &Context);
817 CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,
819 LocalScope::const_iterator DstPost,
823 LocalScope* createOrReuseLocalScope(LocalScope* Scope);
825 void addLocalScopeForStmt(Stmt *S);
826 LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
827 LocalScope* Scope =
nullptr);
828 LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope =
nullptr);
830 void addLocalScopeAndDtors(Stmt *S);
832 const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {
836 const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);
840 cleanupConstructionContext(E);
847 void appendStmt(CFGBlock *B,
const Stmt *S) {
848 if (alwaysAdd(S) && cachedEntry)
849 cachedEntry->second = B;
853 B->
appendStmt(
const_cast<Stmt*
>(S), cfg->getBumpVectorContext());
856 void appendConstructor(CXXConstructExpr *CE) {
858 if (
C &&
C->isNoReturn())
859 Block = createNoReturnBlock();
863 if (
const ConstructionContext *CC =
864 retrieveAndCleanupConstructionContext(CE)) {
865 Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());
870 Block->appendStmt(CE, cfg->getBumpVectorContext());
873 void appendCall(CFGBlock *B, CallExpr *CE) {
874 if (alwaysAdd(CE) && cachedEntry)
875 cachedEntry->second = B;
877 if (
const ConstructionContext *CC =
878 retrieveAndCleanupConstructionContext(CE)) {
884 B->
appendStmt(CE, cfg->getBumpVectorContext());
887 void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
891 void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
895 void appendBaseDtor(CFGBlock *B,
const CXXBaseSpecifier *BS) {
899 void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
903 void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {
904 if (alwaysAdd(ME) && cachedEntry)
905 cachedEntry->second = B;
907 if (
const ConstructionContext *CC =
908 retrieveAndCleanupConstructionContext(ME)) {
913 B->
appendStmt(ME, cfg->getBumpVectorContext());
916 void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
920 void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
924 void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {
928 void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
932 void appendLoopExit(CFGBlock *B,
const Stmt *LoopStmt) {
936 void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
940 void addSuccessor(CFGBlock *B, CFGBlock *S,
bool IsReachable =
true) {
941 B->
addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
942 cfg->getBumpVectorContext());
947 void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
948 B->
addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
949 cfg->getBumpVectorContext());
952 void appendScopeBegin(CFGBlock *B,
const VarDecl *VD,
const Stmt *S) {
957 void appendScopeEnd(CFGBlock *B,
const VarDecl *VD,
const Stmt *S) {
965 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
969 const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
970 const Expr *BoolExpr = RHSExpr;
971 bool IntFirst =
true;
973 IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
981 llvm::APInt IntValue = IntLiteral->
getValue();
982 if ((IntValue == 1) || (IntValue == 0))
986 !IntValue.isNegative();
989 if (Bok == BO_GT || Bok == BO_GE) {
992 return TryResult(IntFirst == IntLarger);
996 return TryResult(IntFirst != IntLarger);
1004 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
1008 std::optional<llvm::APInt> IntLiteral1 =
1009 getIntegerLiteralSubexpressionValue(LHSExpr);
1010 const Expr *BoolExpr = RHSExpr;
1013 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
1020 const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);
1021 if (BitOp && (BitOp->
getOpcode() == BO_And ||
1026 std::optional<llvm::APInt> IntLiteral2 =
1027 getIntegerLiteralSubexpressionValue(LHSExpr2);
1030 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
1036 (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
1038 (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1042 return TryResult(B->
getOpcode() != BO_EQ);
1045 if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1048 return TryResult(B->
getOpcode() != BO_EQ);
1060 std::optional<llvm::APInt>
1061 getIntegerLiteralSubexpressionValue(
const Expr *E) {
1064 if (
const auto *UnOp = dyn_cast<UnaryOperator>(E->
IgnoreParens())) {
1067 const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();
1069 if (
const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1074 switch (UnOp->getOpcode()) {
1084 assert(
false &&
"Unexpected unary operator!");
1085 return std::nullopt;
1088 }
else if (
const auto *IntLiteral =
1092 return std::nullopt;
1095 template <
typename APFloatOrInt>
1097 const APFloatOrInt &Value1,
1098 const APFloatOrInt &Value2) {
1103 return TryResult(Value1 == Value2);
1105 return TryResult(Value1 != Value2);
1107 return TryResult(Value1 < Value2);
1109 return TryResult(Value1 <= Value2);
1111 return TryResult(Value1 > Value2);
1113 return TryResult(Value1 >= Value2);
1124 TryResult checkIncorrectLogicOperator(
const BinaryOperator *B) {
1129 auto CheckLogicalOpWithNegatedVariable = [
this, B](
const Expr *E1,
1131 if (
const auto *Negate = dyn_cast<UnaryOperator>(E1)) {
1132 if (Negate->getOpcode() == UO_LNot &&
1134 bool AlwaysTrue = B->
getOpcode() == BO_LOr;
1137 return TryResult(AlwaysTrue);
1143 TryResult
Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);
1146 Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);
1150 const auto *LHS = dyn_cast<BinaryOperator>(LHSExpr);
1151 const auto *RHS = dyn_cast<BinaryOperator>(RHSExpr);
1155 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1158 const Expr *DeclExpr1;
1159 const Expr *NumExpr1;
1163 if (!DeclExpr1 || !NumExpr1)
1166 const Expr *DeclExpr2;
1167 const Expr *NumExpr2;
1171 if (!DeclExpr2 || !NumExpr2)
1184 Expr::EvalResult L1Result, L2Result;
1199 auto AnalyzeConditions = [&](
const auto &Values,
1202 bool AlwaysTrue =
true, AlwaysFalse =
true;
1205 bool LHSAlwaysTrue =
true, LHSAlwaysFalse =
true;
1206 bool RHSAlwaysTrue =
true, RHSAlwaysFalse =
true;
1208 for (
const auto &
Value : Values) {
1210 analyzeLogicOperatorCondition(*BO1,
Value, Values[1] );
1212 analyzeLogicOperatorCondition(*BO2,
Value, Values[3] );
1214 if (!Res1.isKnown() || !Res2.isKnown())
1217 const bool IsAnd = B->
getOpcode() == BO_LAnd;
1218 const bool Combine = IsAnd ? (Res1.isTrue() && Res2.isTrue())
1219 : (Res1.isTrue() || Res2.isTrue());
1221 AlwaysTrue &= Combine;
1222 AlwaysFalse &= !Combine;
1224 LHSAlwaysTrue &= Res1.isTrue();
1225 LHSAlwaysFalse &= Res1.isFalse();
1226 RHSAlwaysTrue &= Res2.isTrue();
1227 RHSAlwaysFalse &= Res2.isFalse();
1230 if (AlwaysTrue || AlwaysFalse) {
1231 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1232 !RHSAlwaysFalse && BuildOpts.
Observer) {
1235 return TryResult(AlwaysTrue);
1243 llvm::APSInt L1 = L1Result.
Val.
getInt();
1244 llvm::APSInt L2 = L2Result.
Val.
getInt();
1247 if (L1.isSigned() != L2.isSigned() ||
1248 L1.getBitWidth() != L2.getBitWidth())
1253 const llvm::APSInt Values[] = {
1255 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1259 ((L1 < L2) ? L1 : L2) +
1260 llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1), L1.isUnsigned()),
1264 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1267 return AnalyzeConditions(Values, &BO1, &BO2);
1286 if (llvm::APFloat::opOK !=
1287 L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1290 }
else if (Order < 0)
1292 if (llvm::APFloat::opOK !=
1293 L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1297 llvm::APFloat MidValue = L1;
1298 MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven);
1299 MidValue.divide(llvm::APFloat(MidValue.getSemantics(),
"2.0"),
1300 llvm::APFloat::rmNearestTiesToEven);
1302 const llvm::APFloat Values[] = {
1303 llvm::APFloat::getSmallest(L1.getSemantics(),
true), L1, MidValue, L2,
1304 llvm::APFloat::getLargest(L2.getSemantics(),
false),
1307 return AnalyzeConditions(Values, &BO1, &BO2);
1314 TryResult checkIncorrectBitwiseOrOperator(
const BinaryOperator *B) {
1315 const Expr *LHSConstant =
1317 const Expr *RHSConstant =
1320 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1323 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1329 if (
Result.Val.getInt() == 0)
1335 return TryResult(
true);
1339 bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
1349 TryResult tryEvaluateBool(Expr *S) {
1354 if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
1355 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1357 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1358 if (I != CachedBoolEvals.end())
1362 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
1363 CachedBoolEvals[S] =
Result;
1367 switch (Bop->getOpcode()) {
1375 Expr::EvalResult LHSResult;
1376 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1377 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1378 if (!IntVal.getBoolValue()) {
1379 return TryResult(
false);
1382 Expr::EvalResult RHSResult;
1383 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1384 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1385 if (!IntVal.getBoolValue()) {
1386 return TryResult(
false);
1395 return evaluateAsBooleanConditionNoCache(S);
1399 TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
1400 if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
1401 if (Bop->isLogicalOp()) {
1402 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1403 if (LHS.isKnown()) {
1406 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1407 return LHS.isTrue();
1409 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1410 if (RHS.isKnown()) {
1411 if (Bop->getOpcode() == BO_LOr)
1412 return LHS.isTrue() || RHS.isTrue();
1414 return LHS.isTrue() && RHS.isTrue();
1417 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1418 if (RHS.isKnown()) {
1421 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1422 return RHS.isTrue();
1424 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1425 if (BopRes.isKnown())
1426 return BopRes.isTrue();
1431 }
else if (Bop->isEqualityOp()) {
1432 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1433 if (BopRes.isKnown())
1434 return BopRes.isTrue();
1435 }
else if (Bop->isRelationalOp()) {
1436 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1437 if (BopRes.isKnown())
1438 return BopRes.isTrue();
1439 }
else if (Bop->getOpcode() == BO_Or) {
1440 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1441 if (BopRes.isKnown())
1442 return BopRes.isTrue();
1453 bool hasTrivialDestructor(
const VarDecl *VD)
const;
1454 bool needsAutomaticDestruction(
const VarDecl *VD)
const;
1465 while (
const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1466 AILEInit = E->getSubExpr();
1471inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1473 return builder.alwaysAdd(
stmt) ||
kind == AlwaysAdd;
1476bool CFGBuilder::alwaysAdd(
const Stmt *
stmt) {
1482 if (lastLookup ==
stmt) {
1484 assert(cachedEntry->first ==
stmt);
1497 assert(!cachedEntry);
1501 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(
stmt);
1502 if (itr == fb->end()) {
1503 cachedEntry =
nullptr;
1507 cachedEntry = &*itr;
1514 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1516 if (vat->getSizeExpr())
1519 t = vt->getElementType().getTypePtr();
1525void CFGBuilder::consumeConstructionContext(
1526 const ConstructionContextLayer *Layer, Expr *E) {
1529 if (
const ConstructionContextLayer *PreviouslyStoredLayer =
1530 ConstructionContextMap.lookup(E)) {
1531 (void)PreviouslyStoredLayer;
1534 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1535 "Already within a different construction context!");
1537 ConstructionContextMap[E] = Layer;
1541void CFGBuilder::findConstructionContexts(
1542 const ConstructionContextLayer *Layer, Stmt *Child) {
1549 auto withExtraLayer = [
this, Layer](
const ConstructionContextItem &Item) {
1554 switch(Child->getStmtClass()) {
1555 case Stmt::CXXConstructExprClass:
1556 case Stmt::CXXTemporaryObjectExprClass: {
1560 findConstructionContexts(withExtraLayer(CE), CE->
getArg(0));
1563 consumeConstructionContext(Layer, CE);
1569 case Stmt::CallExprClass:
1570 case Stmt::CXXMemberCallExprClass:
1571 case Stmt::CXXOperatorCallExprClass:
1572 case Stmt::UserDefinedLiteralClass:
1573 case Stmt::ObjCMessageExprClass: {
1576 consumeConstructionContext(Layer, E);
1579 case Stmt::ExprWithCleanupsClass: {
1581 findConstructionContexts(Layer, Cleanups->getSubExpr());
1584 case Stmt::CXXFunctionalCastExprClass: {
1586 findConstructionContexts(Layer,
Cast->getSubExpr());
1589 case Stmt::ImplicitCastExprClass: {
1592 switch (
Cast->getCastKind()) {
1594 case CK_ConstructorConversion:
1595 findConstructionContexts(Layer,
Cast->getSubExpr());
1602 case Stmt::CXXBindTemporaryExprClass: {
1604 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1607 case Stmt::MaterializeTemporaryExprClass: {
1615 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1619 case Stmt::ConditionalOperatorClass: {
1627 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1631 findConstructionContexts(Layer, CO->getLHS());
1632 findConstructionContexts(Layer, CO->getRHS());
1635 case Stmt::InitListExprClass: {
1637 if (ILE->isTransparent()) {
1638 findConstructionContexts(Layer, ILE->getInit(0));
1644 case Stmt::ParenExprClass: {
1648 findConstructionContexts(Layer, PE->getSubExpr());
1656void CFGBuilder::cleanupConstructionContext(Expr *E) {
1658 "We should not be managing construction contexts!");
1659 assert(ConstructionContextMap.count(E) &&
1660 "Cannot exit construction context without the context!");
1661 ConstructionContextMap.erase(E);
1669std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D, Stmt *Statement) {
1677 Succ = createBlock();
1678 assert(Succ == &cfg->getExit());
1683 LocalScope *paramScope =
nullptr;
1684 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
1685 for (ParmVarDecl *PD : FD->parameters()) {
1686 paramScope = addLocalScopeForVarDecl(PD, paramScope);
1688 if (
auto *
C = dyn_cast<CompoundStmt>(Statement))
1692 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(),
1696 if (
const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
1697 addImplicitDtorsForDestructor(DD);
1700 CFGBlock *B = addStmt(Statement);
1717 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1718 CFGBlock *VBaseSucc =
nullptr;
1719 for (
auto *I : llvm::reverse(CD->inits())) {
1721 I->isBaseInitializer() && I->isBaseVirtual()) {
1725 VBaseSucc = Succ = B ? B : &cfg->getExit();
1726 Block = createBlock();
1728 B = addInitializer(I);
1738 addSuccessor(B,
Block,
true);
1747 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1748 E = BackpatchBlocks.end(); I != E; ++I ) {
1750 CFGBlock *B = I->block;
1752 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1755 if (LI == LabelMap.end())
1757 JumpTarget JT = LI->second;
1759 CFGBlock *SuccBlk = createScopeChangesHandlingBlock(
1760 I->scopePosition, B, JT.scopePosition, JT.block);
1761 addSuccessor(B, SuccBlk);
1762 }
else if (
auto *G = dyn_cast<GCCAsmStmt>(B->
getTerminator())) {
1763 CFGBlock *Successor = (I+1)->block;
1764 for (
auto *L : G->labels()) {
1765 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1768 if (LI == LabelMap.end())
1770 JumpTarget JT = LI->second;
1772 if (JT.block == Successor)
1774 addSuccessor(B, JT.block);
1781 if (CFGBlock *B = cfg->getIndirectGotoBlock())
1782 for (LabelDecl *LD : AddressTakenLabels) {
1784 LabelMapTy::iterator LI = LabelMap.find(LD);
1788 if (LI == LabelMap.end())
continue;
1790 addSuccessor(B, LI->second.block);
1794 cfg->setEntry(createBlock());
1797 assert(ConstructionContextMap.empty() &&
1798 "Not all construction contexts were cleaned up!");
1800 return std::move(cfg);
1805CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1806 CFGBlock *B = cfg->createBlock();
1807 if (add_successor && Succ)
1808 addSuccessor(B, Succ);
1815CFGBlock *CFGBuilder::createNoReturnBlock() {
1816 CFGBlock *B = createBlock(
false);
1818 addSuccessor(B, &cfg->getExit(), Succ);
1823CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
1827 bool HasTemporaries =
false;
1835 if (HasTemporaries &&
1838 TempDtorContext Context;
1842 addFullExprCleanupMarker(Context);
1847 appendInitializer(
Block, I);
1853 dyn_cast<ArrayInitLoopExpr>(
Init));
1855 findConstructionContexts(
1857 AILEInit ? AILEInit :
Init);
1859 if (HasTemporaries) {
1865 if (CXXDefaultInitExpr *
Default = dyn_cast<CXXDefaultInitExpr>(
Init)) {
1871 if (Stmt *Child =
Default->getExpr())
1872 if (CFGBlock *R = Visit(Child))
1886 bool *FoundMTE =
nullptr) {
1893 Init = EWC->getSubExpr();
1899 = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
1900 Init = MTE->getSubExpr();
1907 const Expr *SkippedInit =
Init->skipRValueSubobjectAdjustments();
1908 if (SkippedInit !=
Init) {
1916 return Init->getType();
1921void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1925 appendLoopExit(
Block, LoopStmt);
1933void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1934 LocalScope::const_iterator E,
1944 if (B.inSameLocalScope(E)) {
1945 addAutomaticObjDestruction(B, E, S);
1950 SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;
1951 LocalScopeEndMarkers.push_back(B);
1952 for (LocalScope::const_iterator I = B; I != E; ++I) {
1953 if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
1954 LocalScopeEndMarkers.push_back(I);
1956 LocalScopeEndMarkers.push_back(E);
1960 std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
1962 llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
1963 for (
auto [E, B] : Pairwise) {
1964 if (!B.inSameLocalScope(E))
1965 addScopeExitHandling(B, E, S);
1966 addAutomaticObjDestruction(B, E, S);
1973void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
1974 LocalScope::const_iterator E,
1982 SmallVector<VarDecl *, 10> DeclsNeedDestruction;
1983 DeclsNeedDestruction.reserve(B.distance(E));
1985 for (VarDecl* D : llvm::make_range(B, E))
1986 if (needsAutomaticDestruction(D))
1987 DeclsNeedDestruction.push_back(D);
1989 for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
2002 Block = createNoReturnBlock();
2011 appendLifetimeEnds(
Block, VD, S);
2013 appendAutomaticObjDtor(
Block, VD, S);
2014 if (VD->
hasAttr<CleanupAttr>())
2015 appendCleanupFunction(
Block, VD);
2024void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
2025 LocalScope::const_iterator E, Stmt *S) {
2026 assert(!B.inSameLocalScope(E));
2032 appendScopeEnd(
Block, B.getFirstVarInScope(), S);
2039 SmallVector<VarDecl *, 10> DeclsTrivial;
2040 DeclsTrivial.reserve(B.distance(E));
2045 for (VarDecl* D : llvm::make_range(B, E))
2046 if (!needsAutomaticDestruction(D))
2047 DeclsTrivial.push_back(D);
2049 if (DeclsTrivial.empty())
2053 for (VarDecl *VD : llvm::reverse(DeclsTrivial))
2054 appendLifetimeEnds(
Block, VD, S);
2062void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
2063 LocalScope::const_iterator DstPos,
2065 assert(
Block &&
"Source block should be always crated");
2071 if (SrcPos == DstPos)
2076 LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
2079 if (BuildOpts.
AddScopes && !DstPos.inSameLocalScope(BasePos)) {
2080 for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
2081 if (I.pointsToFirstDeclaredVar())
2082 appendScopeBegin(
Block, *I, S);
2087 addAutomaticObjHandling(SrcPos, BasePos, S);
2090void CFGBuilder::addFullExprCleanupMarker(TempDtorContext &Context) {
2092 BumpVectorContext &BVC = cfg->getBumpVectorContext();
2094 size_t NumCollected = Context.CollectedMTEs.size();
2095 if (NumCollected > 0) {
2097 ExpiringMTEs =
new (cfg->getAllocator())
2099 for (
const MaterializeTemporaryExpr *MTE : Context.CollectedMTEs)
2101 Block->appendFullExprCleanup(ExpiringMTEs, BVC);
2110CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
2111 LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,
2112 LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {
2113 if (SrcPos == DstPos)
2117 (!BuildOpts.
AddScopes || SrcPos.inSameLocalScope(DstPos)))
2122 SaveAndRestore save_Block(
Block), save_Succ(Succ);
2125 Block = createBlock(
false);
2128 addSuccessor(
Block, DstBlk);
2131 addScopeChangesHandling(SrcPos, DstPos,
Block->getTerminatorStmt());
2133 assert(
Block &&
"There should be at least one scope changing Block");
2139void CFGBuilder::addImplicitDtorsForDestructor(
const CXXDestructorDecl *DD) {
2141 "Can be called only when dtors should be added");
2142 const CXXRecordDecl *RD = DD->
getParent();
2145 for (
const auto &VI : RD->
vbases()) {
2149 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2152 appendBaseDtor(
Block, &VI);
2157 for (
const auto &BI : RD->
bases()) {
2158 if (!BI.isVirtual()) {
2159 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2162 appendBaseDtor(
Block, &BI);
2170 for (
auto *FI : RD->
fields()) {
2172 QualType QT = FI->getType();
2175 if (AT->isZeroSize())
2177 QT = AT->getElementType();
2183 appendMemberDtor(
Block, FI);
2190LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
2193 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
2194 return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);
2199void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
2204 LocalScope *Scope =
nullptr;
2208 for (
auto *BI : CS->body()) {
2209 Stmt *SI = BI->stripLabelLikeStatements();
2210 if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2211 Scope = addLocalScopeForDeclStmt(DS, Scope);
2219 addLocalScopeForDeclStmt(DS);
2224LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
2225 LocalScope* Scope) {
2230 for (
auto *DI : DS->
decls())
2231 if (VarDecl *VD = dyn_cast<VarDecl>(DI))
2232 Scope = addLocalScopeForVarDecl(VD, Scope);
2236bool CFGBuilder::needsAutomaticDestruction(
const VarDecl *VD)
const {
2237 return !hasTrivialDestructor(VD) || VD->
hasAttr<CleanupAttr>();
2240bool CFGBuilder::hasTrivialDestructor(
const VarDecl *VD)
const {
2261 bool FoundMTE =
false;
2269 if (AT->isZeroSize())
2271 QT = AT->getElementType();
2283LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
2284 LocalScope* Scope) {
2299 !needsAutomaticDestruction(VD)) {
2305 Scope = createOrReuseLocalScope(Scope);
2307 ScopePos = Scope->begin();
2313void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
2314 LocalScope::const_iterator scopeBeginPos = ScopePos;
2315 addLocalScopeForStmt(S);
2316 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2322CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2323 bool ExternallyDestructed) {
2329 if (Expr *E = dyn_cast<Expr>(S))
2330 S = E->IgnoreParens();
2333 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2334 return VisitOMPExecutableDirective(D, asc);
2338 return VisitStmt(S, asc);
2340 case Stmt::ImplicitValueInitExprClass:
2343 return VisitStmt(S, asc);
2345 case Stmt::InitListExprClass:
2348 case Stmt::AttributedStmtClass:
2351 case Stmt::AddrLabelExprClass:
2354 case Stmt::BinaryConditionalOperatorClass:
2357 case Stmt::BinaryOperatorClass:
2360 case Stmt::BlockExprClass:
2363 case Stmt::BreakStmtClass:
2366 case Stmt::CallExprClass:
2367 case Stmt::CXXOperatorCallExprClass:
2368 case Stmt::CXXMemberCallExprClass:
2369 case Stmt::UserDefinedLiteralClass:
2372 case Stmt::CaseStmtClass:
2375 case Stmt::ChooseExprClass:
2378 case Stmt::CompoundStmtClass:
2381 case Stmt::ConditionalOperatorClass:
2384 case Stmt::ContinueStmtClass:
2387 case Stmt::CXXCatchStmtClass:
2390 case Stmt::ExprWithCleanupsClass:
2392 asc, ExternallyDestructed);
2394 case Stmt::CXXDefaultArgExprClass:
2395 case Stmt::CXXDefaultInitExprClass:
2404 return VisitStmt(S, asc);
2406 case Stmt::CXXBindTemporaryExprClass:
2409 case Stmt::CXXConstructExprClass:
2412 case Stmt::CXXNewExprClass:
2415 case Stmt::CXXDeleteExprClass:
2418 case Stmt::CXXFunctionalCastExprClass:
2421 case Stmt::CXXTemporaryObjectExprClass:
2424 case Stmt::CXXThrowExprClass:
2427 case Stmt::CXXTryStmtClass:
2430 case Stmt::CXXTypeidExprClass:
2433 case Stmt::CXXForRangeStmtClass:
2436 case Stmt::DeclStmtClass:
2439 case Stmt::DefaultStmtClass:
2442 case Stmt::DoStmtClass:
2445 case Stmt::ForStmtClass:
2448 case Stmt::GotoStmtClass:
2451 case Stmt::GCCAsmStmtClass:
2454 case Stmt::IfStmtClass:
2457 case Stmt::ImplicitCastExprClass:
2460 case Stmt::ConstantExprClass:
2463 case Stmt::IndirectGotoStmtClass:
2466 case Stmt::LabelStmtClass:
2469 case Stmt::LambdaExprClass:
2472 case Stmt::MaterializeTemporaryExprClass:
2476 case Stmt::MemberExprClass:
2479 case Stmt::NullStmtClass:
2482 case Stmt::ObjCAtCatchStmtClass:
2485 case Stmt::ObjCAutoreleasePoolStmtClass:
2488 case Stmt::ObjCAtSynchronizedStmtClass:
2491 case Stmt::ObjCAtThrowStmtClass:
2494 case Stmt::ObjCAtTryStmtClass:
2497 case Stmt::ObjCForCollectionStmtClass:
2500 case Stmt::ObjCMessageExprClass:
2503 case Stmt::OpaqueValueExprClass:
2506 case Stmt::PseudoObjectExprClass:
2509 case Stmt::ReturnStmtClass:
2510 case Stmt::CoreturnStmtClass:
2511 return VisitReturnStmt(S);
2513 case Stmt::CoyieldExprClass:
2514 case Stmt::CoawaitExprClass:
2517 case Stmt::SEHExceptStmtClass:
2520 case Stmt::SEHFinallyStmtClass:
2523 case Stmt::SEHLeaveStmtClass:
2526 case Stmt::SEHTryStmtClass:
2529 case Stmt::UnaryExprOrTypeTraitExprClass:
2533 case Stmt::StmtExprClass:
2536 case Stmt::SwitchStmtClass:
2539 case Stmt::UnaryOperatorClass:
2542 case Stmt::WhileStmtClass:
2545 case Stmt::ArrayInitLoopExprClass:
2550CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
2551 if (asc.alwaysAdd(*
this, S)) {
2553 appendStmt(
Block, S);
2556 return VisitChildren(S);
2560CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
2561 CFGBlock *B =
Block;
2565 reverse_children RChildren(S, *Context);
2566 for (Stmt *Child : RChildren) {
2568 if (CFGBlock *R = Visit(Child))
2574CFGBlock *CFGBuilder::VisitCallExprChildren(CallExpr *
C) {
2578 if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
C);
2579 OCE && OCE->isAssignmentOp()) {
2580 Visit(OCE->getArg(0));
2581 Visit(OCE->getArg(1));
2582 return Visit(OCE->getCallee());
2584 return VisitChildren(
C);
2587CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
2588 if (asc.alwaysAdd(*
this, ILE)) {
2590 appendStmt(
Block, ILE);
2592 CFGBlock *B =
Block;
2594 reverse_children RChildren(ILE, *Context);
2595 for (Stmt *Child : RChildren) {
2598 if (CFGBlock *R = Visit(Child))
2601 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2602 if (Stmt *Child = DIE->getExpr())
2603 if (CFGBlock *R = Visit(Child))
2610CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
2611 AddStmtChoice asc) {
2612 AddressTakenLabels.insert(A->
getLabel());
2614 if (asc.alwaysAdd(*
this, A)) {
2616 appendStmt(
Block, A);
2625 "expected fallthrough not to have children");
2626 return isFallthrough;
2633 "expected [[assume]] not to have children");
2634 return hasAssumeAttr;
2637CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
2638 AddStmtChoice asc) {
2648 if (isInterestingAttribute && asc.alwaysAdd(*
this, A)) {
2650 appendStmt(
Block, A);
2653 return VisitChildren(A);
2656CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {
2657 if (asc.alwaysAdd(*
this, U)) {
2659 appendStmt(
Block, U);
2665 return Visit(U->
getSubExpr(), AddStmtChoice());
2668CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
2669 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
2670 appendStmt(ConfluenceBlock, B);
2675 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2676 ConfluenceBlock).first;
2679std::pair<CFGBlock*, CFGBlock*>
2680CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
2682 CFGBlock *TrueBlock,
2683 CFGBlock *FalseBlock) {
2688 CFGBlock *RHSBlock, *ExitBlock;
2691 if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
2692 if (B_RHS->isLogicalOp()) {
2693 std::tie(RHSBlock, ExitBlock) =
2694 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2702 ExitBlock = RHSBlock = createBlock(
false);
2707 TryResult KnownVal = tryEvaluateBool(RHS);
2708 if (!KnownVal.isKnown())
2709 KnownVal = tryEvaluateBool(B);
2712 assert(TrueBlock == FalseBlock);
2713 addSuccessor(RHSBlock, TrueBlock);
2717 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2718 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2722 RHSBlock = addStmt(RHS);
2727 return std::make_pair(
nullptr,
nullptr);
2732 if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
2733 if (B_LHS->isLogicalOp()) {
2735 FalseBlock = RHSBlock;
2737 TrueBlock = RHSBlock;
2742 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2747 CFGBlock *LHSBlock = createBlock(
false);
2751 CFGBlock *EntryLHSBlock = addStmt(LHS);
2754 return std::make_pair(
nullptr,
nullptr);
2757 TryResult KnownVal = tryEvaluateBool(LHS);
2761 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2762 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2765 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2766 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2769 return std::make_pair(EntryLHSBlock, ExitBlock);
2772CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
2773 AddStmtChoice asc) {
2776 return VisitLogicalOperator(B);
2780 appendStmt(
Block, B);
2782 return addStmt(B->
getLHS());
2786 if (asc.alwaysAdd(*
this, B)) {
2788 appendStmt(
Block, B);
2791 return Visit(B->
getRHS());
2794 if (asc.alwaysAdd(*
this, B)) {
2796 appendStmt(
Block, B);
2802 CFGBlock *RBlock = Visit(B->
getRHS());
2803 CFGBlock *LBlock = Visit(B->
getLHS());
2807 return (LBlock ? LBlock : RBlock);
2810CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
2811 if (asc.alwaysAdd(*
this, E)) {
2813 appendStmt(
Block, E);
2818CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
2825 Block = createBlock(
false);
2826 Block->setTerminator(B);
2830 if (BreakJumpTarget.block) {
2831 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2832 addSuccessor(
Block, BreakJumpTarget.block);
2857 if (BuiltinID != Builtin::BI__assume &&
2858 BuiltinID != Builtin::BI__builtin_assume)
2864CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *
C, AddStmtChoice asc) {
2866 QualType calleeType =
C->getCallee()->getType();
2872 if (!boundType.
isNull()) calleeType = boundType;
2878 bool AddEHEdge =
false;
2888 bool OmitArguments =
false;
2890 if (FunctionDecl *FD =
C->getDirectCallee()) {
2895 if (!FD->isVariadic())
2896 findConstructionContextsForArguments(
C);
2898 if (FD->isNoReturn() || FD->isAnalyzerNoReturn() ||
2899 C->isBuiltinAssumeFalse(*Context))
2901 if (FD->
hasAttr<NoThrowAttr>())
2904 FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2905 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2906 OmitArguments =
true;
2909 if (!
CanThrow(
C->getCallee(), *Context))
2912 if (OmitArguments) {
2913 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2914 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2917 return Visit(
C->getCallee());
2920 if (!NoReturn && !AddEHEdge) {
2924 return VisitCallExprChildren(
C);
2934 Block = createNoReturnBlock();
2936 Block = createBlock();
2942 if (TryTerminatedBlock)
2943 addSuccessor(
Block, TryTerminatedBlock);
2945 addSuccessor(
Block, &cfg->getExit());
2948 return VisitCallExprChildren(
C);
2951CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *
C,
2952 AddStmtChoice asc) {
2953 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
2954 appendStmt(ConfluenceBlock,
C);
2958 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2959 Succ = ConfluenceBlock;
2961 CFGBlock *LHSBlock = Visit(
C->getLHS(), alwaysAdd);
2965 Succ = ConfluenceBlock;
2967 CFGBlock *RHSBlock = Visit(
C->getRHS(), alwaysAdd);
2971 Block = createBlock(
false);
2973 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2974 addSuccessor(
Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2975 addSuccessor(
Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2977 return addStmt(
C->getCond());
2981 bool ExternallyDestructed) {
2982 LocalScope::const_iterator scopeBeginPos = ScopePos;
2983 addLocalScopeForStmt(
C);
2988 addAutomaticObjHandling(ScopePos, scopeBeginPos,
C);
2991 CFGBlock *LastBlock =
Block;
2993 for (Stmt *S : llvm::reverse(
C->body())) {
2996 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2997 ExternallyDestructed);
3000 LastBlock = newBlock;
3005 ExternallyDestructed =
false;
3011CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *
C,
3012 AddStmtChoice asc) {
3013 const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(
C);
3014 const OpaqueValueExpr *opaqueValue = (BCO ? BCO->
getOpaqueValue() :
nullptr);
3018 CFGBlock *ConfluenceBlock =
Block ?
Block : createBlock();
3019 appendStmt(ConfluenceBlock,
C);
3023 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
3029 Succ = ConfluenceBlock;
3031 CFGBlock *LHSBlock =
nullptr;
3032 const Expr *trueExpr =
C->getTrueExpr();
3033 if (trueExpr != opaqueValue) {
3034 LHSBlock = Visit(
C->getTrueExpr(), alwaysAdd);
3040 LHSBlock = ConfluenceBlock;
3043 Succ = ConfluenceBlock;
3044 CFGBlock *RHSBlock = Visit(
C->getFalseExpr(), alwaysAdd);
3049 if (BinaryOperator *
Cond =
3050 dyn_cast<BinaryOperator>(
C->getCond()->IgnoreParens()))
3051 if (
Cond->isLogicalOp())
3052 return VisitLogicalOperator(
Cond,
C, LHSBlock, RHSBlock).first;
3055 Block = createBlock(
false);
3058 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
3059 addSuccessor(
Block, LHSBlock, !KnownVal.isFalse());
3060 addSuccessor(
Block, RHSBlock, !KnownVal.isTrue());
3062 Expr *condExpr =
C->getCond();
3067 if (condExpr != opaqueValue)
3075 return addStmt(condExpr);
3078CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
3086 return VisitDeclSubExpr(DS);
3088 CFGBlock *B =
nullptr;
3097 DeclGroupRef DG(*I);
3100 cfg->addSyntheticDeclStmt(DSNew, DS);
3103 B = VisitDeclSubExpr(DSNew);
3111CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
3112 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
3114 if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl())) {
3116 const Type *T = TND->getUnderlyingType().getTypePtr();
3121 appendStmt(
Block, DS);
3123 CFGBlock *LastBlock =
Block;
3124 for (
const VariableArrayType *VA =
FindVA(T); VA !=
nullptr;
3125 VA =
FindVA(VA->getElementType().getTypePtr())) {
3126 if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
3127 LastBlock = NewBlock;
3140 bool HasTemporaries =
false;
3143 CFGBlock *blockAfterStaticInit =
nullptr;
3154 blockAfterStaticInit = Succ;
3163 if (HasTemporaries &&
3166 TempDtorContext Context;
3170 addFullExprCleanupMarker(Context);
3176 if (
const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
3177 for (
auto *BD : llvm::reverse(DD->bindings())) {
3178 if (
auto *VD = BD->getHoldingVar()) {
3179 DeclGroupRef DG(VD);
3182 cfg->addSyntheticDeclStmt(DSNew, DS);
3183 Block = VisitDeclSubExpr(DSNew);
3189 appendStmt(
Block, DS);
3193 const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(
Init);
3195 findConstructionContexts(
3197 AILE ? AILE->getSubExpr() :
Init);
3202 CFGBlock *LastBlock =
Block;
3205 if (HasTemporaries) {
3209 if (CFGBlock *newBlock = Visit(EC->
getSubExpr()))
3210 LastBlock = newBlock;
3213 if (CFGBlock *newBlock = Visit(
Init))
3214 LastBlock = newBlock;
3222 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
3223 if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3224 LastBlock = newBlock;
3227 maybeAddScopeBeginForVarDecl(
Block, VD, DS);
3230 if (ScopePos && VD == *ScopePos)
3233 CFGBlock *B = LastBlock;
3234 if (blockAfterStaticInit) {
3236 Block = createBlock(
false);
3237 Block->setTerminator(DS);
3238 addSuccessor(
Block, blockAfterStaticInit);
3239 addSuccessor(
Block, B);
3246CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
3256 SaveAndRestore save_scope_pos(ScopePos);
3260 addLocalScopeForStmt(
Init);
3265 addLocalScopeForVarDecl(VD);
3267 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3278 CFGBlock *ElseBlock = Succ;
3280 if (Stmt *Else = I->
getElse()) {
3281 SaveAndRestore sv(Succ);
3290 addLocalScopeAndDtors(Else);
3292 ElseBlock = addStmt(Else);
3295 ElseBlock = sv.get();
3303 CFGBlock *ThenBlock;
3307 SaveAndRestore sv(Succ);
3313 addLocalScopeAndDtors(Then);
3315 ThenBlock = addStmt(Then);
3321 ThenBlock = createBlock(
false);
3322 addSuccessor(ThenBlock, sv.get());
3336 BinaryOperator *
Cond =
3340 CFGBlock *LastBlock;
3342 LastBlock = VisitLogicalOperator(
Cond, I, ThenBlock, ElseBlock).first;
3345 Block = createBlock(
false);
3348 Block->setTerminator(I);
3353 KnownVal = tryEvaluateBool(I->
getCond());
3357 addSuccessor(
Block, ThenBlock, !KnownVal.isFalse());
3358 addSuccessor(
Block, ElseBlock, !KnownVal.isTrue());
3366 LastBlock = addStmt(I->
getCond());
3372 LastBlock = addStmt(
const_cast<DeclStmt *
>(DS));
3379 LastBlock = addStmt(
Init);
3385CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
3395 Block = createBlock(
false);
3397 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3399 if (
auto *R = dyn_cast<ReturnStmt>(S))
3400 findConstructionContexts(
3406 if (!
Block->hasNoReturnElement())
3407 addSuccessor(
Block, &cfg->getExit());
3410 appendStmt(
Block, S);
3413 if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3414 if (Expr *O = RS->getRetValue())
3415 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3427 if (CFGBlock *R = Visit(RV))
3433CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
3434 AddStmtChoice asc) {
3438 if (asc.alwaysAdd(*
this, E)) {
3440 appendStmt(
Block, E);
3442 CFGBlock *B =
Block;
3454CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
3460 SaveAndRestore save_scope_pos(ScopePos);
3463 CFGBlock *SEHExceptBlock =
Block;
3464 if (!SEHExceptBlock)
3465 SEHExceptBlock = createBlock();
3467 appendStmt(SEHExceptBlock, ES);
3479 return SEHExceptBlock;
3482CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
3483 return VisitCompoundStmt(FS->
getBlock(),
false);
3486CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
3493 Block = createBlock(
false);
3494 Block->setTerminator(LS);
3498 if (SEHLeaveJumpTarget.block) {
3499 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3500 addSuccessor(
Block, SEHLeaveJumpTarget.block);
3507CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
3510 CFGBlock *SEHTrySuccessor =
nullptr;
3515 SEHTrySuccessor =
Block;
3516 }
else SEHTrySuccessor = Succ;
3522 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3525 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3532 Succ = SEHTrySuccessor;
3534 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3539 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3541 if (PrevSEHTryTerminatedBlock)
3542 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3544 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3547 Succ = SEHTrySuccessor;
3550 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3551 cfg->addTryDispatchBlock(TryTerminatedBlock);
3556 SaveAndRestore save_break(SEHLeaveJumpTarget);
3557 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3559 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3564CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
3567 CFGBlock *LabelBlock =
Block;
3570 LabelBlock = createBlock();
3572 assert(!LabelMap.contains(L->
getDecl()) &&
"label already in map");
3573 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3592CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
3593 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3595 if (Expr *CopyExpr = CI.getCopyExpr()) {
3596 CFGBlock *Tmp = Visit(CopyExpr);
3604CFGBlock *CFGBuilder::VisitLambdaExpr(
LambdaExpr *E, AddStmtChoice asc) {
3605 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3610 it != et; ++it, ++Idx) {
3611 if (Expr *
Init = *it) {
3615 dyn_cast<ArrayInitLoopExpr>(
Init));
3618 cfg->getBumpVectorContext(), {E, Idx}),
3619 AILEInit ? AILEInit :
Init);
3621 CFGBlock *Tmp = Visit(
Init);
3629CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
3633 Block = createBlock(
false);
3634 Block->setTerminator(G);
3637 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3639 if (I == LabelMap.end())
3641 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3643 JumpTarget JT = I->second;
3644 addSuccessor(
Block, JT.block);
3645 addScopeChangesHandling(ScopePos, JT.scopePosition, G);
3651CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
3656 return VisitStmt(G, asc);
3663 Block = createBlock();
3664 Block->setTerminator(G);
3666 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3669 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3670 return VisitChildren(G);
3673CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
3674 CFGBlock *LoopSuccessor =
nullptr;
3678 SaveAndRestore save_scope_pos(ScopePos);
3684 addLocalScopeForStmt(
Init);
3685 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3688 addLocalScopeForVarDecl(VD);
3689 LocalScope::const_iterator ContinueScopePos = ScopePos;
3691 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3700 LoopSuccessor =
Block;
3702 LoopSuccessor = Succ;
3706 SaveAndRestore save_break(BreakJumpTarget);
3707 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3709 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3716 SaveAndRestore save_Block(
Block), save_Succ(Succ);
3717 SaveAndRestore save_continue(ContinueJumpTarget);
3722 Block = Succ = TransitionBlock = createBlock(
false);
3723 TransitionBlock->setLoopTarget(F);
3728 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3730 if (Stmt *I = F->
getInc()) {
3738 assert(
Block == Succ);
3746 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3747 ContinueJumpTarget.block->setLoopTarget(F);
3753 addLocalScopeAndDtors(F->
getBody());
3757 BodyBlock = addStmt(F->
getBody());
3762 BodyBlock = ContinueJumpTarget.block;
3771 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3775 SaveAndRestore save_scope_pos(ScopePos);
3779 if (BinaryOperator *
Cond =
3780 dyn_cast_or_null<BinaryOperator>(
C ?
C->IgnoreParens() :
nullptr))
3781 if (
Cond->isLogicalOp()) {
3782 std::tie(EntryConditionBlock, ExitConditionBlock) =
3783 VisitLogicalOperator(
Cond, F, BodyBlock, LoopSuccessor);
3788 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3789 ExitConditionBlock->setTerminator(F);
3792 TryResult KnownVal(
true);
3798 Block = ExitConditionBlock;
3799 EntryConditionBlock = addStmt(
C);
3808 findConstructionContexts(
3811 appendStmt(
Block, DS);
3812 EntryConditionBlock = addStmt(
Init);
3813 assert(
Block == EntryConditionBlock);
3814 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3818 if (
Block && badCFG)
3821 KnownVal = tryEvaluateBool(
C);
3825 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3828 addSuccessor(ExitConditionBlock,
3829 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3833 addSuccessor(TransitionBlock, EntryConditionBlock);
3836 Succ = EntryConditionBlock;
3841 SaveAndRestore save_scope_pos(ScopePos);
3842 ScopePos = LoopBeginScopePos;
3843 Block = createBlock();
3850 Succ = EntryConditionBlock;
3851 return EntryConditionBlock;
3855CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
3856 AddStmtChoice asc) {
3857 findConstructionContexts(
3861 return VisitStmt(MTE, asc);
3864CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
3865 if (asc.alwaysAdd(*
this, M)) {
3867 appendStmt(
Block, M);
3872CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
3904 CFGBlock *LoopSuccessor =
nullptr;
3909 LoopSuccessor =
Block;
3912 LoopSuccessor = Succ;
3915 CFGBlock *ExitConditionBlock = createBlock(
false);
3923 appendStmt(ExitConditionBlock, S);
3924 Block = ExitConditionBlock;
3929 CFGBlock *EntryConditionBlock = Visit(S->
getElement(),
3930 AddStmtChoice::NotAlwaysAdd);
3939 Succ = EntryConditionBlock;
3944 SaveAndRestore save_Block(
Block), save_Succ(Succ);
3945 SaveAndRestore save_continue(ContinueJumpTarget),
3946 save_break(BreakJumpTarget);
3951 CFGBlock *LoopBackBlock =
nullptr;
3952 Succ = LoopBackBlock = createBlock();
3955 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3956 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3958 CFGBlock *BodyBlock = addStmt(S->
getBody());
3961 BodyBlock = ContinueJumpTarget.block;
3968 addSuccessor(ExitConditionBlock, BodyBlock);
3973 addSuccessor(ExitConditionBlock, LoopSuccessor);
3976 Block = createBlock();
3980CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
3986CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
4004 appendStmt(
Block, S);
4010CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
4014 appendStmt(
Block, E);
4016 CFGBlock *lastBlock =
Block;
4025 if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
4026 Semantic = OVE->getSourceExpr();
4028 if (CFGBlock *B = Visit(Semantic))
4035CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
4036 CFGBlock *LoopSuccessor =
nullptr;
4040 SaveAndRestore save_scope_pos(ScopePos);
4044 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
4046 addLocalScopeForVarDecl(VD);
4047 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4056 LoopSuccessor =
Block;
4059 LoopSuccessor = Succ;
4062 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
4069 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4070 SaveAndRestore save_continue(ContinueJumpTarget),
4071 save_break(BreakJumpTarget);
4075 Succ = TransitionBlock = createBlock(
false);
4076 TransitionBlock->setLoopTarget(W);
4077 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
4080 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4083 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
4088 addLocalScopeAndDtors(W->
getBody());
4091 BodyBlock = addStmt(W->
getBody());
4094 BodyBlock = ContinueJumpTarget.block;
4095 else if (
Block && badCFG)
4102 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
4109 if (BinaryOperator *
Cond = dyn_cast<BinaryOperator>(
C->IgnoreParens()))
4110 if (
Cond->isLogicalOp()) {
4111 std::tie(EntryConditionBlock, ExitConditionBlock) =
4112 VisitLogicalOperator(
Cond, W, BodyBlock, LoopSuccessor);
4117 ExitConditionBlock = createBlock(
false);
4123 Block = ExitConditionBlock;
4124 Block = EntryConditionBlock = addStmt(
C);
4133 findConstructionContexts(
4135 const_cast<DeclStmt *
>(DS)),
4137 appendStmt(
Block, DS);
4138 EntryConditionBlock = addStmt(
Init);
4139 assert(
Block == EntryConditionBlock);
4140 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
4144 if (
Block && badCFG)
4148 const TryResult& KnownVal = tryEvaluateBool(
C);
4151 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
4154 addSuccessor(ExitConditionBlock,
4155 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4159 addSuccessor(TransitionBlock, EntryConditionBlock);
4166 Succ = EntryConditionBlock;
4167 return EntryConditionBlock;
4170CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
4171 AddStmtChoice asc) {
4172 if (asc.alwaysAdd(*
this, A)) {
4174 appendStmt(
Block, A);
4177 CFGBlock *B =
Block;
4183 assert(OVE &&
"ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
4184 "OpaqueValueExpr!");
4185 if (CFGBlock *R = Visit(OVE->getSourceExpr()))
4191CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {
4197 SaveAndRestore save_scope_pos(ScopePos);
4202 CFGBlock *CatchBlock =
Block;
4204 CatchBlock = createBlock();
4206 appendStmt(CatchBlock, CS);
4221CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
4227 Block = createBlock(
false);
4229 if (TryTerminatedBlock)
4231 addSuccessor(
Block, TryTerminatedBlock);
4234 addSuccessor(
Block, &cfg->getExit());
4238 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4241CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {
4244 CFGBlock *TrySuccessor =
nullptr;
4249 TrySuccessor =
Block;
4251 TrySuccessor = Succ;
4257 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4260 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4264 bool HasCatchAll =
false;
4265 for (ObjCAtCatchStmt *CS : Terminator->
catch_stmts()) {
4267 Succ = TrySuccessor;
4272 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4277 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4282 if (PrevTryTerminatedBlock)
4283 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4285 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4289 Succ = TrySuccessor;
4292 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4293 cfg->addTryDispatchBlock(TryTerminatedBlock);
4295 assert(Terminator->
getTryBody() &&
"try must contain a non-NULL body");
4300CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
4301 AddStmtChoice asc) {
4302 findConstructionContextsForArguments(ME);
4305 appendObjCMessage(
Block, ME);
4307 return VisitChildren(ME);
4310CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
4316 Block = createBlock(
false);
4318 if (TryTerminatedBlock)
4320 addSuccessor(
Block, TryTerminatedBlock);
4323 addSuccessor(
Block, &cfg->getExit());
4327 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4330CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {
4331 if (asc.alwaysAdd(*
this, S)) {
4333 appendStmt(
Block, S);
4343 return VisitChildren(S);
4349CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
4350 CFGBlock *LoopSuccessor =
nullptr;
4359 LoopSuccessor =
Block;
4361 LoopSuccessor = Succ;
4366 CFGBlock *ExitConditionBlock = createBlock(
false);
4367 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4375 Block = ExitConditionBlock;
4376 EntryConditionBlock = addStmt(
C);
4384 Succ = EntryConditionBlock;
4387 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
4390 CFGBlock *BodyBlock =
nullptr;
4395 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4396 SaveAndRestore save_continue(ContinueJumpTarget),
4397 save_break(BreakJumpTarget);
4400 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4403 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4411 addLocalScopeAndDtors(D->
getBody());
4414 BodyBlock = addStmt(D->
getBody());
4417 BodyBlock = EntryConditionBlock;
4430 CFGBlock *LoopBackBlock = createBlock();
4433 if (!KnownVal.isFalse())
4435 addSuccessor(ExitConditionBlock, LoopBackBlock);
4437 addSuccessor(ExitConditionBlock,
nullptr);
4442 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4453CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *
C) {
4460 Block = createBlock(
false);
4465 if (ContinueJumpTarget.block) {
4466 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,
C);
4467 addSuccessor(
Block, ContinueJumpTarget.block);
4474CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
4475 AddStmtChoice asc) {
4476 if (asc.alwaysAdd(*
this, E)) {
4478 appendStmt(
Block, E);
4484 if (E->
getKind() != UETT_SizeOf)
4487 CFGBlock *lastBlock =
Block;
4491 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4492 lastBlock = addStmt(VA->getSizeExpr());
4499CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
4500 if (asc.alwaysAdd(*
this, SE)) {
4502 appendStmt(
Block, SE);
4504 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4507CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
4510 CFGBlock *SwitchSuccessor =
nullptr;
4514 SaveAndRestore save_scope_pos(ScopePos);
4518 addLocalScopeForStmt(
Init);
4523 addLocalScopeForVarDecl(VD);
4525 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4530 SwitchSuccessor =
Block;
4531 }
else SwitchSuccessor = Succ;
4534 SaveAndRestore save_switch(SwitchTerminatedBlock),
4535 save_default(DefaultCaseBlock);
4536 SaveAndRestore save_break(BreakJumpTarget);
4541 DefaultCaseBlock = SwitchSuccessor;
4544 SwitchTerminatedBlock = createBlock(
false);
4548 Succ = SwitchSuccessor;
4549 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4554 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4559 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered,
false);
4562 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4563 Expr::EvalResult result;
4564 bool b = tryEvaluate(Terminator->
getCond(), result);
4565 SaveAndRestore save_switchCond(switchCond,
b ? &result :
nullptr);
4570 addLocalScopeAndDtors(Terminator->
getBody());
4572 addStmt(Terminator->
getBody());
4586 bool SwitchAlwaysHasSuccessor =
false;
4587 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4588 SwitchAlwaysHasSuccessor |=
4591 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4592 !SwitchAlwaysHasSuccessor);
4596 Block = SwitchTerminatedBlock;
4597 CFGBlock *LastBlock = addStmt(Terminator->
getCond());
4605 LastBlock = addStmt(
Init);
4606 maybeAddScopeBeginForVarDecl(LastBlock, VD,
Init);
4613 LastBlock = addStmt(
Init);
4626 bool addCase =
false;
4628 if (!switchExclusivelyCovered) {
4632 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4634 if (condInt == lhsInt) {
4636 switchExclusivelyCovered =
true;
4638 else if (condInt > lhsInt) {
4642 if (V2 >= condInt) {
4644 switchExclusivelyCovered =
true;
4655CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
4658 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4665 CFGBlock *currentBlock = createBlock(
false);
4669 addSuccessor(LastBlock, currentBlock);
4671 TopBlock = currentBlock;
4673 addSuccessor(SwitchTerminatedBlock,
4676 ? currentBlock :
nullptr);
4678 LastBlock = currentBlock;
4686 CFGBlock *CaseBlock =
Block;
4688 CaseBlock = createBlock();
4699 assert(SwitchTerminatedBlock);
4700 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4708 addSuccessor(LastBlock, CaseBlock);
4718CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
4722 DefaultCaseBlock =
Block;
4724 if (!DefaultCaseBlock)
4725 DefaultCaseBlock = createBlock();
4729 DefaultCaseBlock->
setLabel(Terminator);
4744 Succ = DefaultCaseBlock;
4746 return DefaultCaseBlock;
4749CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
4752 CFGBlock *TrySuccessor =
nullptr;
4757 TrySuccessor =
Block;
4759 TrySuccessor = Succ;
4761 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4764 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4768 bool HasCatchAll =
false;
4769 for (
unsigned I = 0, E = Terminator->
getNumHandlers(); I != E; ++I) {
4771 Succ = TrySuccessor;
4772 CXXCatchStmt *CS = Terminator->
getHandler(I);
4777 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4782 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4785 if (PrevTryTerminatedBlock)
4786 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4788 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4792 Succ = TrySuccessor;
4795 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4796 cfg->addTryDispatchBlock(TryTerminatedBlock);
4798 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4803CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
4809 SaveAndRestore save_scope_pos(ScopePos);
4814 LocalScope::const_iterator BeginScopePos = ScopePos;
4815 addLocalScopeForVarDecl(VD);
4816 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4822 CFGBlock *CatchBlock =
Block;
4824 CatchBlock = createBlock();
4830 appendStmt(CatchBlock, CS);
4846CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
4861 SaveAndRestore save_scope_pos(ScopePos);
4866 addLocalScopeForStmt(
Init);
4868 addLocalScopeForStmt(Range);
4870 addLocalScopeForStmt(Begin);
4872 addLocalScopeForStmt(End);
4873 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4875 LocalScope::const_iterator ContinueScopePos = ScopePos;
4879 CFGBlock *LoopSuccessor =
nullptr;
4883 LoopSuccessor =
Block;
4885 LoopSuccessor = Succ;
4889 SaveAndRestore save_break(BreakJumpTarget);
4890 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4893 CFGBlock *ConditionBlock = createBlock(
false);
4898 Block = ConditionBlock;
4899 CFGBlock *BeginConditionBlock = addStmt(
C);
4902 assert(BeginConditionBlock == ConditionBlock &&
4903 "condition block in for-range was unexpectedly complex");
4904 (void)BeginConditionBlock;
4909 Succ = ConditionBlock;
4912 TryResult KnownVal(
true);
4915 KnownVal = tryEvaluateBool(S->
getCond());
4922 SaveAndRestore save_Block(
Block), save_Succ(Succ);
4923 SaveAndRestore save_continue(ContinueJumpTarget);
4928 Succ = addStmt(S->
getInc());
4931 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4935 ContinueJumpTarget.block->setLoopTarget(S);
4949 addLocalScopeAndDtors(S->
getBody());
4961 addSuccessor(ConditionBlock,
4962 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
4967 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4970 Block = createBlock();
4979CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
4981 bool ExternallyDestructed) {
4985 TempDtorContext Context;
4986 VisitForTemporaries(E->
getSubExpr(), ExternallyDestructed, Context);
4988 addFullExprCleanupMarker(Context);
4992 asc = asc.withAlwaysAdd(
true);
4997CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
4998 AddStmtChoice asc) {
4999 if (asc.alwaysAdd(*
this, E)) {
5001 appendStmt(
Block, E);
5003 findConstructionContexts(
5008 asc = asc.withAlwaysAdd(
false);
5013CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *
C,
5014 AddStmtChoice asc) {
5018 findConstructionContextsForArguments(
C);
5019 appendConstructor(
C);
5021 return VisitChildren(
C);
5024CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
5025 AddStmtChoice asc) {
5027 appendStmt(
Block, NE);
5029 findConstructionContexts(
5031 const_cast<CXXConstructExpr *
>(
NE->getConstructExpr()));
5033 if (
NE->getInitializer())
5034 Block = Visit(
NE->getInitializer());
5037 appendNewAllocator(
Block, NE);
5039 if (
NE->isArray() && *
NE->getArraySize())
5040 Block = Visit(*
NE->getArraySize());
5043 E =
NE->placement_arg_end(); I != E; ++I)
5049CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
5050 AddStmtChoice asc) {
5052 appendStmt(
Block, DE);
5059 appendDeleteDtor(
Block, RD, DE);
5063 return VisitChildren(DE);
5066CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
5067 AddStmtChoice asc) {
5068 if (asc.alwaysAdd(*
this, E)) {
5070 appendStmt(
Block, E);
5072 asc = asc.withAlwaysAdd(
false);
5077CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
5078 AddStmtChoice asc) {
5082 findConstructionContextsForArguments(E);
5083 appendConstructor(E);
5085 return VisitChildren(E);
5088CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
5089 AddStmtChoice asc) {
5090 if (asc.alwaysAdd(*
this, E)) {
5092 appendStmt(
Block, E);
5098 return Visit(E->
getSubExpr(), AddStmtChoice());
5101CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
5102 return Visit(E->
getSubExpr(), AddStmtChoice());
5105CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5107 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
5110 IBlock = createBlock(
false);
5111 cfg->setIndirectGotoBlock(IBlock);
5119 Block = createBlock(
false);
5120 Block->setTerminator(I);
5121 addSuccessor(
Block, IBlock);
5125CFGBlock *CFGBuilder::VisitForTemporaries(Stmt *E,
bool ExternallyDestructed,
5126 TempDtorContext &Context) {
5135 return VisitChildrenForTemporaries(E,
false, Context);
5137 case Stmt::InitListExprClass:
5138 return VisitChildrenForTemporaries(E, ExternallyDestructed, Context);
5140 case Stmt::BinaryOperatorClass:
5142 ExternallyDestructed, Context);
5144 case Stmt::CXXOperatorCallExprClass:
5145 return VisitCXXOperatorCallExprForTemporaryDtors(
5148 case Stmt::CXXBindTemporaryExprClass:
5149 return VisitCXXBindTemporaryExprForTemporaryDtors(
5152 case Stmt::BinaryConditionalOperatorClass:
5153 case Stmt::ConditionalOperatorClass:
5154 return VisitConditionalOperatorForTemporaries(
5157 case Stmt::ImplicitCastExprClass:
5162 case Stmt::CXXFunctionalCastExprClass:
5167 case Stmt::ConstantExprClass:
5171 case Stmt::ParenExprClass:
5175 case Stmt::MaterializeTemporaryExprClass: {
5178 if (BuildOpts.
AddLifetime && !ExternallyDestructed)
5180 SmallVector<const Expr *, 2> CommaLHSs;
5181 SmallVector<SubobjectAdjustment, 2> Adjustments;
5183 E =
const_cast<Expr *
>(
5186 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
5188 for (
const Expr *CommaLHS : CommaLHSs) {
5189 VisitForTemporaries(
const_cast<Expr *
>(CommaLHS),
5195 case Stmt::BlockExprClass:
5200 case Stmt::LambdaExprClass: {
5204 CFGBlock *B =
Block;
5205 for (Expr *
Init :
LE->capture_inits()) {
5207 if (CFGBlock *R = VisitForTemporaries(
5208 Init,
true, Context))
5215 case Stmt::StmtExprClass:
5220 case Stmt::CXXDefaultArgExprClass:
5224 case Stmt::CXXDefaultInitExprClass:
5230CFGBlock *CFGBuilder::VisitChildrenForTemporaries(Stmt *E,
5231 bool ExternallyDestructed,
5232 TempDtorContext &Context) {
5242 CFGBlock *B =
Block;
5246 VisitForTemporaries(Child, ExternallyDestructed, Context))
5252CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaries(
5253 BinaryOperator *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5257 CFGBlock *LHSBlock = VisitForTemporaries(E->
getLHS(),
false, Context);
5258 CFGBlock *RHSBlock =
5259 VisitForTemporaries(E->
getRHS(), ExternallyDestructed, Context);
5260 return RHSBlock ? RHSBlock : LHSBlock;
5264 VisitForTemporaries(E->
getLHS(),
false, Context);
5265 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
5266 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
5267 RHSExecuted.negate();
5272 TempDtorContext RHSContext(
5274 VisitForTemporaries(E->
getRHS(),
false, RHSContext);
5275 InsertTempDecisionBlock(RHSContext);
5278 Context.CollectedMTEs.append(RHSContext.CollectedMTEs);
5286 CFGBlock *RHSBlock = VisitForTemporaries(E->
getRHS(),
false, Context);
5287 CFGBlock *LHSBlock = VisitForTemporaries(E->
getLHS(),
false, Context);
5288 return LHSBlock ? LHSBlock : RHSBlock;
5292 return VisitChildrenForTemporaries(E, ExternallyDestructed, Context);
5295CFGBlock *CFGBuilder::VisitCXXOperatorCallExprForTemporaryDtors(
5296 CXXOperatorCallExpr *E, TempDtorContext &Context) {
5300 CFGBlock *RHSBlock = VisitForTemporaries(E->
getArg(1),
false, Context);
5301 CFGBlock *LHSBlock = VisitForTemporaries(E->
getArg(0),
false, Context);
5302 return LHSBlock ? LHSBlock : RHSBlock;
5304 return VisitChildrenForTemporaries(E,
false, Context);
5307CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5308 CXXBindTemporaryExpr *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5311 CFGBlock *B = VisitForTemporaries(E->
getSubExpr(),
true, Context);
5325 Block = createNoReturnBlock();
5326 }
else if (Context.needsTempDtorBranch()) {
5330 Block = createBlock();
5334 if (Context.needsTempDtorBranch()) {
5335 Context.setDecisionPoint(Succ, E);
5337 appendTemporaryDtor(
Block, E);
5343void CFGBuilder::InsertTempDecisionBlock(
const TempDtorContext &Context,
5344 CFGBlock *FalseSucc) {
5345 if (!Context.TerminatorExpr) {
5349 assert(Context.TerminatorExpr);
5350 CFGBlock *Decision = createBlock(
false);
5351 Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,
5353 addSuccessor(Decision,
Block, !Context.KnownExecuted.isFalse());
5354 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5355 !Context.KnownExecuted.isTrue());
5359CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaries(
5360 AbstractConditionalOperator *E,
bool ExternallyDestructed,
5361 TempDtorContext &Context) {
5362 VisitForTemporaries(E->
getCond(),
false, Context);
5363 CFGBlock *ConditionBlock =
Block;
5364 CFGBlock *ConditionSucc = Succ;
5365 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
5366 TryResult NegatedVal = ConditionVal;
5367 if (NegatedVal.isKnown()) NegatedVal.negate();
5369 TempDtorContext TrueContext(
5371 VisitForTemporaries(E->
getTrueExpr(), ExternallyDestructed, TrueContext);
5372 CFGBlock *TrueBlock =
Block;
5374 Block = ConditionBlock;
5375 Succ = ConditionSucc;
5376 TempDtorContext FalseContext(
5378 VisitForTemporaries(E->
getFalseExpr(), ExternallyDestructed, FalseContext);
5380 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5381 InsertTempDecisionBlock(FalseContext, TrueBlock);
5382 }
else if (TrueContext.TerminatorExpr) {
5384 InsertTempDecisionBlock(TrueContext);
5386 InsertTempDecisionBlock(FalseContext);
5389 Context.CollectedMTEs.append(TrueContext.CollectedMTEs);
5390 Context.CollectedMTEs.append(FalseContext.CollectedMTEs);
5396CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
5397 AddStmtChoice asc) {
5398 if (asc.alwaysAdd(*
this, D)) {
5400 appendStmt(
Block, D);
5404 CFGBlock *B =
Block;
5408 SmallVector<Stmt *, 8>
Used(
5409 OMPExecutableDirective::used_clauses_children(D->clauses()));
5410 for (Stmt *S : llvm::reverse(
Used)) {
5411 assert(S &&
"Expected non-null used-in-clause child.");
5412 if (CFGBlock *R = Visit(S))
5416 if (!D->isStandaloneDirective()) {
5417 Stmt *S = D->getRawStmt();
5419 addLocalScopeAndDtors(S);
5420 if (CFGBlock *R = addStmt(S))
5431 bool first_block =
begin() ==
end();
5435 Blocks.push_back(Mem, BlkBVC);
5439 Entry = Exit = &
back();
5448 llvm::TimeTraceScope TimeProfile(
"BuildCFG");
5449 CFGBuilder Builder(
C, BO);
5450 return Builder.buildCFG(D, Statement);
5465 auto IteratorAndFlag = Visited.insert(B);
5466 if (!IteratorAndFlag.second) {
5472 const CFGBlock *FirstReachableB =
nullptr;
5474 if (!AB.isReachable())
5477 if (FirstReachableB ==
nullptr) {
5478 FirstReachableB = &*AB;
5485 if (!FirstReachableB) {
5491 B = FirstReachableB;
5512 llvm_unreachable(
"getDestructorDecl should only be used with "
5523 if (
const Expr *
Init = var->getInit()) {
5570 llvm_unreachable(
"getKind() returned bogus value");
5578 : ReachableBlock(IsReachable ? B :
nullptr),
5579 UnreachableBlock(!IsReachable ? B :
nullptr,
5580 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5583 : ReachableBlock(B),
5584 UnreachableBlock(B == AlternateBlock ?
nullptr : AlternateBlock,
5585 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5595 Succs.push_back(Succ,
C);
5608 if (S->isAllEnumCasesCovered()) {
5626 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5627 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5631 signed currentBlock = 0;
5632 unsigned currStmt = 0;
5642 for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
5643 BI != BEnd; ++BI, ++j ) {
5644 if (std::optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
5645 const Stmt *stmt= SE->getStmt();
5646 std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
5649 switch (stmt->getStmtClass()) {
5650 case Stmt::DeclStmtClass:
5651 DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
5653 case Stmt::IfStmtClass: {
5654 const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
5659 case Stmt::ForStmtClass: {
5660 const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
5665 case Stmt::WhileStmtClass: {
5666 const VarDecl *var =
5667 cast<WhileStmt>(stmt)->getConditionVariable();
5672 case Stmt::SwitchStmtClass: {
5673 const VarDecl *var =
5674 cast<SwitchStmt>(stmt)->getConditionVariable();
5679 case Stmt::CXXCatchStmtClass: {
5680 const VarDecl *var =
5681 cast<CXXCatchStmt>(stmt)->getExceptionDecl();
5694 ~StmtPrinterHelper()
override =
default;
5696 const LangOptions &getLangOpts()
const {
return LangOpts; }
5697 void setBlockID(
signed i) { currentBlock = i; }
5698 void setStmtID(
unsigned i) { currStmt = i; }
5700 bool handledStmt(Stmt *S, raw_ostream &OS)
override {
5701 StmtMapTy::iterator I = StmtMap.find(S);
5703 if (I == StmtMap.end())
5706 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5707 && I->second.second == currStmt) {
5711 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5715 bool handleDecl(
const Decl *D, raw_ostream &OS) {
5716 DeclMapTy::iterator I = DeclMap.find(D);
5718 if (I == DeclMap.end()) {
5721 if (
auto *PVD = dyn_cast_or_null<ParmVarDecl>(D)) {
5722 OS <<
"[Parm: " << PVD->getNameAsString() <<
"]";
5728 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5729 && I->second.second == currStmt) {
5733 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5738class CFGBlockTerminatorPrint
5739 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5741 StmtPrinterHelper* Helper;
5742 PrintingPolicy Policy;
5745 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5746 const PrintingPolicy &Policy)
5747 :
OS(os), Helper(helper), Policy(Policy) {
5751 void VisitIfStmt(IfStmt *I) {
5754 C->printPretty(OS, Helper, Policy);
5758 void VisitStmt(Stmt *Terminator) {
5762 void VisitDeclStmt(DeclStmt *DS) {
5767 void VisitForStmt(ForStmt *F) {
5773 C->printPretty(OS, Helper, Policy);
5780 void VisitWhileStmt(WhileStmt *W) {
5783 C->printPretty(OS, Helper, Policy);
5786 void VisitDoStmt(DoStmt *D) {
5787 OS <<
"do ... while ";
5789 C->printPretty(OS, Helper, Policy);
5792 void VisitSwitchStmt(SwitchStmt *Terminator) {
5797 void VisitCXXTryStmt(CXXTryStmt *) {
OS <<
"try ..."; }
5799 void VisitObjCAtTryStmt(ObjCAtTryStmt *) {
OS <<
"@try ..."; }
5801 void VisitSEHTryStmt(SEHTryStmt *CS) {
OS <<
"__try ..."; }
5803 void VisitAbstractConditionalOperator(AbstractConditionalOperator*
C) {
5804 if (Stmt *
Cond =
C->getCond())
5806 OS <<
" ? ... : ...";
5809 void VisitChooseExpr(ChooseExpr *
C) {
5810 OS <<
"__builtin_choose_expr( ";
5811 if (Stmt *
Cond =
C->getCond())
5816 void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5822 void VisitBinaryOperator(BinaryOperator* B) {
5839 llvm_unreachable(
"Invalid logical operator.");
5843 void VisitExpr(Expr *E) {
5848 void print(CFGTerminator T) {
5854 OS <<
"(Temp Dtor) ";
5858 OS <<
"(See if most derived ctor has already initialized vbases)";
5880 OS <<
" (Base initializer)";
5882 OS <<
" (Delegating initializer)";
5884 OS <<
" (Member initializer)";
5888 StmtPrinterHelper &Helper,
5903 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5908 Stmts.push_back(SDSCC->getDeclStmt());
5913 Stmts.push_back(CDSCC->getDeclStmt());
5914 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5919 Stmts.push_back(NECC->getCXXNewExpr());
5924 Stmts.push_back(RSCC->getReturnStmt());
5930 Stmts.push_back(RSCC->getReturnStmt());
5931 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5936 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5937 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5942 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5943 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5944 Stmts.push_back(TOCC->getConstructorAfterElision());
5949 Helper.handledStmt(
const_cast<LambdaExpr *
>(LCC->getLambdaExpr()), OS);
5950 OS <<
"+" << LCC->getIndex();
5955 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5957 Helper.handledStmt(
const_cast<Stmt *
>(BTE), OS);
5960 Helper.handledStmt(
const_cast<Expr *
>(ACC->getCallLikeExpr()), OS);
5961 OS <<
"+" << ACC->getIndex();
5968 Helper.handledStmt(
const_cast<Stmt *
>(I), OS);
5972static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5973 const CFGElement &E,
bool TerminateWithNewLine =
true);
5976 bool TerminateWithNewLine)
const {
5978 StmtPrinterHelper Helper(
nullptr, LangOpts);
5979 print_elem(OS, Helper, *
this, TerminateWithNewLine);
5982static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5983 const CFGElement &E,
bool TerminateWithNewLine) {
5990 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5993 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
6001 if (TerminateWithNewLine)
6010 Helper.handledStmt(B->
getRHS(),OS);
6011 if (TerminateWithNewLine)
6016 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
6020 OS <<
" (OperatorCall)";
6021 OS <<
" (CXXRecordTypedCall";
6025 OS <<
" (OperatorCall)";
6027 OS <<
" (BindTemporary)";
6029 OS <<
" (CXXConstructExpr";
6033 OS <<
", " << CCE->getType() <<
")";
6034 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
6036 <<
", " << CE->
getType() <<
")";
6040 if (
isa<Expr>(S) && TerminateWithNewLine)
6053 Helper.handleDecl(VD, OS);
6056 if (T->isReferenceType())
6060 T.getUnqualifiedType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
6061 OS <<
"() (Implicit destructor)";
6066 OS <<
"CleanupFunction ("
6072 OS <<
" (Lifetime ends)";
6077 size_t MTECount = MTEs.size();
6078 OS <<
"(FullExprCleanup collected " << MTECount
6079 << (MTECount > 1 ?
" MTEs: " :
" MTE: ");
6080 bool FirstMTE =
true;
6084 if (!Helper.handledStmt(MTE->
getSubExpr(), OS)) {
6102 OS <<
"CFGScopeBegin(";
6109 OS <<
"CFGScopeEnd(";
6116 OS <<
"CFGNewAllocator(";
6118 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
6130 OS <<
"->~" << RD->getName().str() <<
"()";
6131 OS <<
" (Implicit destructor)";
6138 OS <<
" (Base object destructor)";
6145 OS <<
"this->" << FD->
getName();
6146 OS <<
".~" << T->getAsCXXRecordDecl()->getName() <<
"()";
6147 OS <<
" (Member object destructor)";
6156 OS <<
"() (Temporary object destructor)";
6160 if (TerminateWithNewLine)
6166 StmtPrinterHelper &Helper,
bool print_edges,
6172 OS.changeColor(raw_ostream::YELLOW,
true);
6177 OS <<
" (ENTRY)]\n";
6178 else if (&B == &cfg->
getExit())
6181 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
6183 OS <<
" (NORETURN)]\n";
6199 if (
const Expr *LHS =
C->getLHS())
6201 if (
const Expr *RHS =
C->getRHS()) {
6216 if (
const VarDecl *PD = CS->getCatchParamDecl())
6227 llvm_unreachable(
"Invalid label statement in CFGBlock.");
6236 I != E ; ++I, ++j ) {
6241 OS << llvm::format(
"%3d", j) <<
": ";
6243 Helper.setStmtID(j);
6251 OS.changeColor(raw_ostream::GREEN);
6255 Helper.setBlockID(-1);
6258 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
6269 const raw_ostream::Colors Color = raw_ostream::BLUE;
6271 OS.changeColor(Color);
6279 OS.changeColor(Color);
6287 bool Reachable =
true;
6290 B = I->getPossiblyUnreachableBlock();
6295 OS <<
"(Unreachable)";
6306 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
6308 OS.changeColor(Color);
6316 OS.changeColor(Color);
6325 bool Reachable =
true;
6328 B = I->getPossiblyUnreachableBlock();
6334 OS <<
"(Unreachable)";
6350 print(llvm::errs(), LO, ShowColors);
6355 StmtPrinterHelper Helper(
this, LO);
6361 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
6366 print_block(OS,
this, **I, Helper,
true, ShowColors);
6381 bool ShowColors)
const {
6382 print(llvm::errs(), cfg, LO, ShowColors);
6393 StmtPrinterHelper Helper(cfg, LO);
6394 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
6401 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
6407 bool AddQuotes)
const {
6409 llvm::raw_string_ostream TempOut(Buf);
6432 if (llvm::any_of(*Blk, [](
const CFGElement &Elm) {
6433 if (std::optional<CFGStmt> StmtElm = Elm.
getAs<
CFGStmt>())
6453 DFSWorkList.push_back(StartBlk);
6454 while (!DFSWorkList.empty()) {
6455 const CFGBlock *Blk = DFSWorkList.pop_back_val();
6456 Visited.insert(Blk);
6465 for (
const auto &Succ : Blk->
succs()) {
6466 if (
const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
6470 DFSWorkList.push_back(SuccBlk);
6499 const Stmt *
Cond = StmtElem->getStmt();
6513 const Expr *E =
nullptr;
6519 case Stmt::CXXForRangeStmtClass:
6523 case Stmt::ForStmtClass:
6527 case Stmt::WhileStmtClass:
6531 case Stmt::DoStmtClass:
6535 case Stmt::IfStmtClass:
6539 case Stmt::ChooseExprClass:
6543 case Stmt::IndirectGotoStmtClass:
6547 case Stmt::SwitchStmtClass:
6551 case Stmt::BinaryConditionalOperatorClass:
6555 case Stmt::ConditionalOperatorClass:
6559 case Stmt::BinaryOperatorClass:
6563 case Stmt::ObjCForCollectionStmtClass:
6580 StmtPrinterHelper H(
this, LO);
6582 llvm::ViewGraph(
this,
"CFG");
6594 llvm::raw_string_ostream Out(OutStr);
6597 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
6600 for (
unsigned i = 0; i != OutStr.length(); ++i)
6601 if (OutStr[i] ==
'\n') {
6603 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
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)