23 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/SmallPtrSet.h"
26 #include "llvm/Support/Allocator.h"
27 #include "llvm/Support/Format.h"
28 #include "llvm/Support/GraphWriter.h"
29 #include "llvm/Support/SaveAndRestore.h"
31 using namespace clang;
36 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
37 if (
Expr *Ex = VD->getInit())
38 return Ex->getSourceRange().getEnd();
44 const Expr *tryTransformToIntOrEnumConstant(
const Expr *
E) {
46 if (isa<IntegerLiteral>(E))
49 return isa<EnumConstantDecl>(DR->getDecl()) ? DR :
nullptr;
58 static std::tuple<const DeclRefExpr *, BinaryOperatorKind, const Expr *>
63 const Expr *Constant = tryTransformToIntOrEnumConstant(B->
getRHS());
65 if (Constant ==
nullptr) {
77 Constant = tryTransformToIntOrEnumConstant(B->
getLHS());
81 return std::make_tuple(D, Op, Constant);
90 static bool areExprTypesCompatible(
const Expr *E1,
const Expr *E2) {
93 if (isa<IntegerLiteral>(E1) != isa<IntegerLiteral>(E2))
97 if (isa<IntegerLiteral>(E1))
102 assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
103 auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
104 auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
106 assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
110 assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
129 class AddStmtChoice {
131 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
133 AddStmtChoice(
Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
135 bool alwaysAdd(CFGBuilder &builder,
140 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
141 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
175 class const_iterator {
176 const LocalScope*
Scope;
187 :
Scope(nullptr), VarIter(0) {}
191 const_iterator(
const LocalScope&
S,
unsigned I)
192 :
Scope(&S), VarIter(I) {
195 if (VarIter == 0 &&
Scope)
199 VarDecl *
const* operator->()
const {
200 assert (
Scope &&
"Dereferencing invalid iterator is not allowed");
201 assert (VarIter != 0 &&
"Iterator has invalid value of VarIter member");
202 return &
Scope->Vars[VarIter - 1];
205 return *this->operator->();
208 const_iterator &operator++() {
212 assert (VarIter != 0 &&
"Iterator has invalid value of VarIter member");
218 const_iterator operator++(
int) {
219 const_iterator
P = *
this;
224 bool operator==(
const const_iterator &rhs)
const {
225 return Scope == rhs.Scope && VarIter == rhs.VarIter;
227 bool operator!=(
const const_iterator &rhs)
const {
228 return !(*
this == rhs);
231 explicit operator bool()
const {
232 return *
this != const_iterator();
235 int distance(const_iterator L);
238 friend class const_iterator;
244 AutomaticVarsTy Vars;
252 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
255 const_iterator
begin()
const {
return const_iterator(*
this, Vars.size()); }
258 Vars.push_back(VD, ctx);
265 int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
267 const_iterator F = *
this;
268 while (F.Scope != L.Scope) {
269 assert (F != const_iterator()
270 &&
"L iterator is not reachable from F iterator.");
274 D += F.VarIter - L.VarIter;
281 struct BlockScopePosPair {
282 BlockScopePosPair() : block(nullptr) {}
283 BlockScopePosPair(
CFGBlock *b, LocalScope::const_iterator scopePos)
284 : block(b), scopePosition(scopePos) {}
287 LocalScope::const_iterator scopePosition;
297 TryResult(
bool b) :
X(b ? 1 : 0) {}
298 TryResult() :
X(-1) {}
300 bool isTrue()
const {
return X == 1; }
301 bool isFalse()
const {
return X == 0; }
302 bool isKnown()
const {
return X >= 0; }
309 TryResult bothKnownTrue(TryResult R1, TryResult R2) {
310 if (!R1.isKnown() || !R2.isKnown())
312 return TryResult(R1.isTrue() && R2.isTrue());
315 class reverse_children {
319 reverse_children(
Stmt *S);
327 reverse_children::reverse_children(
Stmt *S) {
328 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
332 switch (S->getStmtClass()) {
334 case Stmt::InitListExprClass: {
345 for (
Stmt *SubStmt : S->children())
346 childrenBuf.push_back(SubStmt);
349 children = childrenBuf;
367 typedef BlockScopePosPair JumpTarget;
368 typedef BlockScopePosPair JumpSource;
371 std::unique_ptr<CFG> cfg;
375 JumpTarget ContinueJumpTarget;
376 JumpTarget BreakJumpTarget;
382 LocalScope::const_iterator ScopePos;
385 typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
390 typedef std::vector<JumpSource> BackpatchBlocksTy;
391 BackpatchBlocksTy BackpatchBlocks;
394 typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
395 LabelSetTy AddressTakenLabels;
401 bool switchExclusivelyCovered;
404 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
405 const Stmt *lastLookup;
409 typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy;
410 CachedBoolEvalsTy CachedBoolEvals;
416 Block(nullptr), Succ(nullptr),
417 SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
418 TryTerminatedBlock(nullptr), badCFG(
false), BuildOpts(buildOpts),
419 switchExclusivelyCovered(
false), switchCond(nullptr),
420 cachedEntry(nullptr), lastLookup(nullptr) {}
423 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
466 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
486 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
519 struct TempDtorContext {
521 : IsConditional(
false), KnownExecuted(
true), Succ(nullptr),
522 TerminatorExpr(nullptr) {}
524 TempDtorContext(TryResult KnownExecuted)
525 : IsConditional(
true), KnownExecuted(KnownExecuted), Succ(nullptr),
526 TerminatorExpr(nullptr) {}
534 bool needsTempDtorBranch()
const {
535 return IsConditional && !TerminatorExpr;
545 const bool IsConditional;
546 const TryResult KnownExecuted;
553 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
558 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
560 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
563 void InsertTempDtorDecisionBlock(
const TempDtorContext &
Context,
572 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
573 CFGBlock *createBlock(
bool add_successor =
true);
577 return Visit(S, AddStmtChoice::AlwaysAdd);
580 void addAutomaticObjDtors(LocalScope::const_iterator B,
581 LocalScope::const_iterator E,
Stmt *S);
585 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
587 void addLocalScopeForStmt(
Stmt *S);
588 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
589 LocalScope*
Scope =
nullptr);
590 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
592 void addLocalScopeAndDtors(
Stmt *S);
596 if (alwaysAdd(S) && cachedEntry)
597 cachedEntry->second = B;
600 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
601 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
626 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
627 LocalScope::const_iterator B, LocalScope::const_iterator E);
631 cfg->getBumpVectorContext());
638 cfg->getBumpVectorContext());
644 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
649 const Expr *BoolExpr = RHSExpr;
650 bool IntFirst =
true;
660 llvm::APInt IntValue = IntLiteral->
getValue();
661 if ((IntValue == 1) || (IntValue == 0))
665 !IntValue.isNegative();
671 return TryResult(IntFirst == IntLarger);
675 return TryResult(IntFirst != IntLarger);
683 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
688 const Expr *BoolExpr = RHSExpr;
712 llvm::APInt L1 = IntLiteral->
getValue();
713 llvm::APInt L2 = IntLiteral2->
getValue();
716 if (BuildOpts.Observer)
717 BuildOpts.Observer->compareBitwiseEquality(B,
721 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
722 llvm::APInt IntValue = IntLiteral->
getValue();
723 if ((IntValue == 1) || (IntValue == 0)) {
733 const llvm::APSInt &Value1,
734 const llvm::APSInt &Value2) {
735 assert(Value1.isSigned() == Value2.isSigned());
740 return TryResult(Value1 == Value2);
742 return TryResult(Value1 != Value2);
744 return TryResult(Value1 < Value2);
746 return TryResult(Value1 <= Value2);
748 return TryResult(Value1 > Value2);
750 return TryResult(Value1 >= Value2);
767 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
773 std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS);
775 if (!Decl1 || !Expr1)
781 std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS);
783 if (!Decl2 || !Expr2)
792 if (!areExprTypesCompatible(Expr1, Expr2))
802 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
807 const llvm::APSInt Values[] = {
809 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
813 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
818 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
827 bool AlwaysTrue =
true, AlwaysFalse =
true;
828 for (llvm::APSInt
Value : Values) {
829 TryResult Res1, Res2;
830 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
831 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
833 if (!Res1.isKnown() || !Res2.isKnown())
837 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
838 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
840 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
841 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
845 if (AlwaysTrue || AlwaysFalse) {
846 if (BuildOpts.Observer)
847 BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
848 return TryResult(AlwaysTrue);
855 if (!BuildOpts.PruneTriviallyFalseEdges)
864 TryResult tryEvaluateBool(
Expr *S) {
865 if (!BuildOpts.PruneTriviallyFalseEdges ||
870 if (Bop->isLogicalOp()) {
873 if (I != CachedBoolEvals.end())
877 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
882 switch (Bop->getOpcode()) {
891 if (Bop->getLHS()->EvaluateAsInt(IntVal, *
Context)) {
892 if (!IntVal.getBoolValue()) {
893 return TryResult(
false);
896 if (Bop->getRHS()->EvaluateAsInt(IntVal, *
Context)) {
897 if (!IntVal.getBoolValue()) {
898 return TryResult(
false);
907 return evaluateAsBooleanConditionNoCache(S);
911 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
913 if (Bop->isLogicalOp()) {
914 TryResult LHS = tryEvaluateBool(Bop->getLHS());
918 if (LHS.isTrue() == (Bop->getOpcode() ==
BO_LOr))
921 TryResult RHS = tryEvaluateBool(Bop->getRHS());
923 if (Bop->getOpcode() ==
BO_LOr)
924 return LHS.isTrue() || RHS.isTrue();
926 return LHS.isTrue() && RHS.isTrue();
929 TryResult RHS = tryEvaluateBool(Bop->getRHS());
933 if (RHS.isTrue() == (Bop->getOpcode() ==
BO_LOr))
936 TryResult BopRes = checkIncorrectLogicOperator(Bop);
937 if (BopRes.isKnown())
938 return BopRes.isTrue();
943 }
else if (Bop->isEqualityOp()) {
944 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
945 if (BopRes.isKnown())
946 return BopRes.isTrue();
947 }
else if (Bop->isRelationalOp()) {
948 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
949 if (BopRes.isKnown())
950 return BopRes.isTrue();
963 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
965 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
968 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
969 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
971 if (!BuildOpts.forcedBlkExprs)
974 if (lastLookup == stmt) {
976 assert(cachedEntry->first == stmt);
989 assert(!cachedEntry);
994 if (itr == fb->end()) {
995 cachedEntry =
nullptr;
1006 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1008 if (vat->getSizeExpr())
1011 t = vt->getElementType().getTypePtr();
1022 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1030 Succ = createBlock();
1031 assert(Succ == &cfg->getExit());
1034 if (BuildOpts.AddImplicitDtors)
1036 addImplicitDtorsForDestructor(DD);
1046 for (
auto *I : llvm::reverse(CD->inits())) {
1047 B = addInitializer(I);
1059 E = BackpatchBlocks.end(); I !=
E; ++
I ) {
1067 if (LI == LabelMap.end())
continue;
1069 JumpTarget JT = LI->second;
1070 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1072 addSuccessor(B, JT.block);
1076 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1078 E = AddressTakenLabels.end(); I !=
E; ++
I ) {
1085 if (LI == LabelMap.end())
continue;
1087 addSuccessor(B, LI->second.block);
1091 cfg->setEntry(createBlock());
1093 return std::move(cfg);
1098 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1100 if (add_successor && Succ)
1101 addSuccessor(B, Succ);
1108 CFGBlock *CFGBuilder::createNoReturnBlock() {
1111 addSuccessor(B, &cfg->getExit(), Succ);
1117 if (!BuildOpts.AddInitializers)
1120 bool HasTemporaries =
false;
1126 HasTemporaries = isa<ExprWithCleanups>(Init);
1128 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1131 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1137 appendInitializer(Block, I);
1140 if (HasTemporaries) {
1143 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1145 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1151 appendStmt(Block, Default);
1152 if (
Stmt *Child = Default->getExpr())
1174 Init = EWC->getSubExpr();
1180 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1181 Init = MTE->GetTemporaryExpr();
1186 if (
const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
1189 CE->getCastKind() ==
CK_NoOp) &&
1191 Init = CE->getSubExpr();
1197 if (
const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
1198 if (!ME->isArrow() && ME->getBase()->isRValue()) {
1199 Init = ME->getBase();
1213 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1214 LocalScope::const_iterator E,
Stmt *S) {
1215 if (!BuildOpts.AddImplicitDtors)
1226 Decls.reserve(B.distance(E));
1227 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1228 Decls.push_back(*I);
1238 Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit());
1243 Block = createNoReturnBlock();
1247 appendAutomaticObjDtor(Block, *I, S);
1254 assert (BuildOpts.AddImplicitDtors
1255 &&
"Can be called only when dtors should be added");
1259 for (
const auto &VI : RD->
vbases()) {
1260 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1263 appendBaseDtor(Block, &VI);
1268 for (
const auto &BI : RD->
bases()) {
1269 if (!BI.isVirtual()) {
1270 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1273 appendBaseDtor(Block, &BI);
1279 for (
auto *FI : RD->
fields()) {
1283 if (AT->getSize() == 0)
1285 QT = AT->getElementType();
1291 appendMemberDtor(Block, FI);
1298 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1301 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1302 return new (alloc.Allocate<LocalScope>())
1308 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1309 if (!BuildOpts.AddImplicitDtors)
1312 LocalScope *Scope =
nullptr;
1316 for (
auto *BI : CS->body()) {
1317 Stmt *SI = BI->stripLabelLikeStatements();
1318 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1319 Scope = addLocalScopeForDeclStmt(DS, Scope);
1326 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
1327 addLocalScopeForDeclStmt(DS);
1332 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1333 LocalScope* Scope) {
1334 if (!BuildOpts.AddImplicitDtors)
1337 for (
auto *DI : DS->
decls())
1338 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1339 Scope = addLocalScopeForVarDecl(VD, Scope);
1346 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1347 LocalScope* Scope) {
1348 if (!BuildOpts.AddImplicitDtors)
1357 default:
return Scope;
1374 Init = EWC->getSubExpr();
1375 if (!isa<MaterializeTemporaryExpr>(Init))
1379 QT = getReferenceInitTemporaryType(*Context, Init);
1384 if (AT->getSize() == 0)
1386 QT = AT->getElementType();
1393 Scope = createOrReuseLocalScope(Scope);
1395 ScopePos = Scope->begin();
1402 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1403 if (!BuildOpts.AddImplicitDtors)
1406 LocalScope::const_iterator scopeBeginPos = ScopePos;
1407 addLocalScopeForStmt(S);
1408 addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
1418 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1419 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1423 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1431 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1437 if (
Expr *E = dyn_cast<Expr>(S))
1438 S = E->IgnoreParens();
1440 switch (S->getStmtClass()) {
1442 return VisitStmt(S, asc);
1444 case Stmt::AddrLabelExprClass:
1445 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
1447 case Stmt::BinaryConditionalOperatorClass:
1448 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
1450 case Stmt::BinaryOperatorClass:
1451 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
1453 case Stmt::BlockExprClass:
1454 return VisitBlockExpr(cast<BlockExpr>(S), asc);
1456 case Stmt::BreakStmtClass:
1457 return VisitBreakStmt(cast<BreakStmt>(S));
1459 case Stmt::CallExprClass:
1460 case Stmt::CXXOperatorCallExprClass:
1461 case Stmt::CXXMemberCallExprClass:
1462 case Stmt::UserDefinedLiteralClass:
1463 return VisitCallExpr(cast<CallExpr>(S), asc);
1465 case Stmt::CaseStmtClass:
1466 return VisitCaseStmt(cast<CaseStmt>(S));
1468 case Stmt::ChooseExprClass:
1469 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
1471 case Stmt::CompoundStmtClass:
1472 return VisitCompoundStmt(cast<CompoundStmt>(S));
1474 case Stmt::ConditionalOperatorClass:
1475 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
1477 case Stmt::ContinueStmtClass:
1478 return VisitContinueStmt(cast<ContinueStmt>(S));
1480 case Stmt::CXXCatchStmtClass:
1481 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
1483 case Stmt::ExprWithCleanupsClass:
1484 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
1486 case Stmt::CXXDefaultArgExprClass:
1487 case Stmt::CXXDefaultInitExprClass:
1497 return VisitStmt(S, asc);
1499 case Stmt::CXXBindTemporaryExprClass:
1500 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
1502 case Stmt::CXXConstructExprClass:
1503 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
1505 case Stmt::CXXNewExprClass:
1506 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
1508 case Stmt::CXXDeleteExprClass:
1509 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
1511 case Stmt::CXXFunctionalCastExprClass:
1512 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
1514 case Stmt::CXXTemporaryObjectExprClass:
1515 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
1517 case Stmt::CXXThrowExprClass:
1518 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
1520 case Stmt::CXXTryStmtClass:
1521 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
1523 case Stmt::CXXForRangeStmtClass:
1524 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
1526 case Stmt::DeclStmtClass:
1527 return VisitDeclStmt(cast<DeclStmt>(S));
1529 case Stmt::DefaultStmtClass:
1530 return VisitDefaultStmt(cast<DefaultStmt>(S));
1532 case Stmt::DoStmtClass:
1533 return VisitDoStmt(cast<DoStmt>(S));
1535 case Stmt::ForStmtClass:
1536 return VisitForStmt(cast<ForStmt>(S));
1538 case Stmt::GotoStmtClass:
1539 return VisitGotoStmt(cast<GotoStmt>(S));
1541 case Stmt::IfStmtClass:
1542 return VisitIfStmt(cast<IfStmt>(S));
1544 case Stmt::ImplicitCastExprClass:
1545 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
1547 case Stmt::IndirectGotoStmtClass:
1548 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
1550 case Stmt::LabelStmtClass:
1551 return VisitLabelStmt(cast<LabelStmt>(S));
1553 case Stmt::LambdaExprClass:
1554 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
1556 case Stmt::MemberExprClass:
1557 return VisitMemberExpr(cast<MemberExpr>(S), asc);
1559 case Stmt::NullStmtClass:
1562 case Stmt::ObjCAtCatchStmtClass:
1563 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
1565 case Stmt::ObjCAutoreleasePoolStmtClass:
1566 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
1568 case Stmt::ObjCAtSynchronizedStmtClass:
1569 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
1571 case Stmt::ObjCAtThrowStmtClass:
1572 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
1574 case Stmt::ObjCAtTryStmtClass:
1575 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
1577 case Stmt::ObjCForCollectionStmtClass:
1578 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
1580 case Stmt::OpaqueValueExprClass:
1583 case Stmt::PseudoObjectExprClass:
1584 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
1586 case Stmt::ReturnStmtClass:
1587 return VisitReturnStmt(cast<ReturnStmt>(S));
1589 case Stmt::UnaryExprOrTypeTraitExprClass:
1590 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1593 case Stmt::StmtExprClass:
1594 return VisitStmtExpr(cast<StmtExpr>(S), asc);
1596 case Stmt::SwitchStmtClass:
1597 return VisitSwitchStmt(cast<SwitchStmt>(S));
1599 case Stmt::UnaryOperatorClass:
1600 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
1602 case Stmt::WhileStmtClass:
1603 return VisitWhileStmt(cast<WhileStmt>(S));
1607 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
1608 if (asc.alwaysAdd(*
this, S)) {
1610 appendStmt(Block, S);
1613 return VisitChildren(S);
1622 reverse_children RChildren(S);
1623 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
1625 if (
Stmt *Child = *I)
1633 AddStmtChoice asc) {
1634 AddressTakenLabels.insert(A->
getLabel());
1636 if (asc.alwaysAdd(*
this, A)) {
1638 appendStmt(Block, A);
1645 AddStmtChoice asc) {
1646 if (asc.alwaysAdd(*
this, U)) {
1648 appendStmt(Block, U);
1651 return Visit(U->
getSubExpr(), AddStmtChoice());
1655 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1656 appendStmt(ConfluenceBlock, B);
1661 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
1662 ConfluenceBlock).first;
1665 std::pair<CFGBlock*, CFGBlock*>
1679 if (B_RHS->isLogicalOp()) {
1680 std::tie(RHSBlock, ExitBlock) =
1681 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
1689 ExitBlock = RHSBlock = createBlock(
false);
1692 assert(TrueBlock == FalseBlock);
1693 addSuccessor(RHSBlock, TrueBlock);
1697 TryResult KnownVal = tryEvaluateBool(RHS);
1698 if (!KnownVal.isKnown())
1699 KnownVal = tryEvaluateBool(B);
1700 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
1701 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
1705 RHSBlock = addStmt(RHS);
1710 return std::make_pair(
nullptr,
nullptr);
1716 if (B_LHS->isLogicalOp()) {
1718 FalseBlock = RHSBlock;
1720 TrueBlock = RHSBlock;
1725 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
1730 CFGBlock *LHSBlock = createBlock(
false);
1734 CFGBlock *EntryLHSBlock = addStmt(LHS);
1737 return std::make_pair(
nullptr,
nullptr);
1740 TryResult KnownVal = tryEvaluateBool(LHS);
1744 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
1745 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
1748 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
1749 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
1752 return std::make_pair(EntryLHSBlock, ExitBlock);
1757 AddStmtChoice asc) {
1760 return VisitLogicalOperator(B);
1764 appendStmt(Block, B);
1766 return addStmt(B->
getLHS());
1770 if (asc.alwaysAdd(*
this, B)) {
1772 appendStmt(Block, B);
1775 return Visit(B->
getRHS());
1778 if (asc.alwaysAdd(*
this, B)) {
1780 appendStmt(Block, B);
1788 return (LBlock ? LBlock : RBlock);
1791 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
1792 if (asc.alwaysAdd(*
this, E)) {
1794 appendStmt(Block, E);
1806 Block = createBlock(
false);
1807 Block->setTerminator(B);
1811 if (BreakJumpTarget.block) {
1812 addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B);
1813 addSuccessor(Block, BreakJumpTarget.block);
1832 Proto->isNothrow(Ctx))
1846 if (!boundType.
isNull()) calleeType = boundType;
1852 bool AddEHEdge =
false;
1856 if (BuildOpts.AddEHEdges)
1862 bool OmitArguments =
false;
1865 if (FD->isNoReturn())
1867 if (FD->
hasAttr<NoThrowAttr>())
1869 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
1870 OmitArguments =
true;
1876 if (OmitArguments) {
1877 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
1878 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
1880 appendStmt(Block, C);
1884 if (!NoReturn && !AddEHEdge) {
1885 return VisitStmt(C, asc.withAlwaysAdd(
true));
1895 Block = createNoReturnBlock();
1897 Block = createBlock();
1899 appendStmt(Block, C);
1903 if (TryTerminatedBlock)
1904 addSuccessor(Block, TryTerminatedBlock);
1906 addSuccessor(Block, &cfg->getExit());
1909 return VisitChildren(C);
1913 AddStmtChoice asc) {
1914 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1915 appendStmt(ConfluenceBlock, C);
1919 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
1920 Succ = ConfluenceBlock;
1926 Succ = ConfluenceBlock;
1932 Block = createBlock(
false);
1934 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
1935 addSuccessor(Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
1936 addSuccessor(Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
1937 Block->setTerminator(C);
1943 LocalScope::const_iterator scopeBeginPos = ScopePos;
1944 if (BuildOpts.AddImplicitDtors) {
1945 addLocalScopeForStmt(C);
1949 addAutomaticObjDtors(ScopePos, scopeBeginPos, C);
1958 if (
CFGBlock *newBlock = addStmt(*I))
1959 LastBlock = newBlock;
1969 AddStmtChoice asc) {
1975 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1976 appendStmt(ConfluenceBlock, C);
1980 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
1986 Succ = ConfluenceBlock;
1990 if (trueExpr != opaqueValue) {
1997 LHSBlock = ConfluenceBlock;
2000 Succ = ConfluenceBlock;
2008 if (Cond->isLogicalOp())
2009 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2012 Block = createBlock(
false);
2015 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2016 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2017 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2018 Block->setTerminator(C);
2024 if (condExpr != opaqueValue)
2032 return addStmt(condExpr);
2043 return VisitDeclSubExpr(DS);
2052 unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
2053 ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
2059 void *Mem = cfg->getAllocator().Allocate(
sizeof(
DeclStmt), A);
2061 cfg->addSyntheticDeclStmt(DSNew, DS);
2064 B = VisitDeclSubExpr(DSNew);
2073 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2082 bool HasTemporaries =
false;
2085 CFGBlock *blockAfterStaticInit =
nullptr;
2087 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2096 blockAfterStaticInit = Succ;
2101 Expr *Init = VD->getInit();
2103 HasTemporaries = isa<ExprWithCleanups>(Init);
2105 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2108 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2114 appendStmt(Block, DS);
2122 if (HasTemporaries) {
2127 LastBlock = newBlock;
2130 if (
CFGBlock *newBlock = Visit(Init))
2131 LastBlock = newBlock;
2137 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2138 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2139 LastBlock = newBlock;
2143 if (ScopePos && VD == *ScopePos)
2147 if (blockAfterStaticInit) {
2149 Block = createBlock(
false);
2150 Block->setTerminator(DS);
2151 addSuccessor(Block, blockAfterStaticInit);
2152 addSuccessor(Block, B);
2174 LocalScope::const_iterator BeginScopePos = ScopePos;
2175 addLocalScopeForVarDecl(VD);
2176 addAutomaticObjDtors(ScopePos, BeginScopePos, I);
2199 if (!isa<CompoundStmt>(Else))
2200 addLocalScopeAndDtors(Else);
2202 ElseBlock = addStmt(Else);
2205 ElseBlock = sv.get();
2222 if (!isa<CompoundStmt>(Then))
2223 addLocalScopeAndDtors(Then);
2225 ThenBlock = addStmt(Then);
2231 ThenBlock = createBlock(
false);
2232 addSuccessor(ThenBlock, sv.get());
2249 if (Cond->isLogicalOp())
2250 return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2253 Block = createBlock(
false);
2256 Block->setTerminator(I);
2259 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2263 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2264 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2275 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2291 Block = createBlock(
false);
2293 addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
2297 if (!Block->hasNoReturnElement())
2298 addSuccessor(Block, &cfg->getExit());
2302 return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2311 LabelBlock = createBlock();
2313 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
2314 "label already in map");
2315 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
2321 LabelBlock->setLabel(L);
2335 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2337 if (
Expr *CopyExpr = CI.getCopyExpr()) {
2347 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2350 if (
Expr *Init = *it) {
2363 Block = createBlock(
false);
2364 Block->setTerminator(G);
2369 if (I == LabelMap.end())
2371 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
2373 JumpTarget JT = I->second;
2374 addAutomaticObjDtors(ScopePos, JT.scopePosition, G);
2375 addSuccessor(Block, JT.block);
2392 addLocalScopeForStmt(Init);
2393 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2396 addLocalScopeForVarDecl(VD);
2397 LocalScope::const_iterator ContinueScopePos = ScopePos;
2399 addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F);
2406 LoopSuccessor = Block;
2408 LoopSuccessor = Succ;
2413 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2415 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2428 Block = Succ = TransitionBlock = createBlock(
false);
2429 TransitionBlock->setLoopTarget(F);
2439 assert(Block == Succ);
2447 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
2448 ContinueJumpTarget.block->setLoopTarget(F);
2451 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
2455 if (!isa<CompoundStmt>(F->
getBody()))
2456 addLocalScopeAndDtors(F->
getBody());
2460 BodyBlock = addStmt(F->
getBody());
2465 BodyBlock = ContinueJumpTarget.block;
2474 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2482 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
2483 if (Cond->isLogicalOp()) {
2484 std::tie(EntryConditionBlock, ExitConditionBlock) =
2485 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
2490 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
2491 ExitConditionBlock->setTerminator(F);
2494 TryResult KnownVal(
true);
2500 Block = ExitConditionBlock;
2501 EntryConditionBlock = addStmt(C);
2506 if (
Expr *Init = VD->getInit()) {
2509 EntryConditionBlock = addStmt(Init);
2510 assert(Block == EntryConditionBlock);
2514 if (Block && badCFG)
2517 KnownVal = tryEvaluateBool(C);
2521 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2524 addSuccessor(ExitConditionBlock,
2525 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2530 addSuccessor(TransitionBlock, EntryConditionBlock);
2533 Succ = EntryConditionBlock;
2538 Block = createBlock();
2545 Succ = EntryConditionBlock;
2546 return EntryConditionBlock;
2550 if (asc.alwaysAdd(*
this, M)) {
2552 appendStmt(Block, M);
2595 LoopSuccessor = Block;
2598 LoopSuccessor = Succ;
2601 CFGBlock *ExitConditionBlock = createBlock(
false);
2609 appendStmt(ExitConditionBlock, S);
2610 Block = ExitConditionBlock;
2616 AddStmtChoice::NotAlwaysAdd);
2625 Succ = EntryConditionBlock;
2632 save_break(BreakJumpTarget);
2638 Succ = LoopBackBlock = createBlock();
2641 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2642 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
2647 BodyBlock = ContinueJumpTarget.block;
2654 addSuccessor(ExitConditionBlock, BodyBlock);
2659 addSuccessor(ExitConditionBlock, LoopSuccessor);
2662 Block = createBlock();
2690 appendStmt(Block, S);
2705 appendStmt(Block, E);
2717 Semantic = OVE->getSourceExpr();
2735 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2737 addLocalScopeForVarDecl(VD);
2738 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2746 LoopSuccessor = Block;
2749 LoopSuccessor = Succ;
2752 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2761 save_break(BreakJumpTarget);
2765 Succ = TransitionBlock = createBlock(
false);
2766 TransitionBlock->setLoopTarget(W);
2767 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
2770 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2773 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2777 if (!isa<CompoundStmt>(W->
getBody()))
2778 addLocalScopeAndDtors(W->
getBody());
2781 BodyBlock = addStmt(W->
getBody());
2784 BodyBlock = ContinueJumpTarget.block;
2785 else if (Block && badCFG)
2792 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2800 if (Cond->isLogicalOp()) {
2801 std::tie(EntryConditionBlock, ExitConditionBlock) =
2802 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
2807 ExitConditionBlock = createBlock(
false);
2813 Block = ExitConditionBlock;
2814 Block = EntryConditionBlock = addStmt(C);
2819 if (
Expr *Init = VD->getInit()) {
2822 EntryConditionBlock = addStmt(Init);
2823 assert(Block == EntryConditionBlock);
2827 if (Block && badCFG)
2831 const TryResult& KnownVal = tryEvaluateBool(C);
2834 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2837 addSuccessor(ExitConditionBlock,
2838 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2843 addSuccessor(TransitionBlock, EntryConditionBlock);
2850 Succ = EntryConditionBlock;
2851 return EntryConditionBlock;
2870 Block = createBlock(
false);
2873 addSuccessor(Block, &cfg->getExit());
2877 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
2886 Block = createBlock(
false);
2888 if (TryTerminatedBlock)
2890 addSuccessor(Block, TryTerminatedBlock);
2893 addSuccessor(Block, &cfg->getExit());
2897 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
2908 LoopSuccessor = Block;
2910 LoopSuccessor = Succ;
2915 CFGBlock *ExitConditionBlock = createBlock(
false);
2916 CFGBlock *EntryConditionBlock = ExitConditionBlock;
2924 Block = ExitConditionBlock;
2925 EntryConditionBlock = addStmt(C);
2933 Succ = EntryConditionBlock;
2936 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
2946 save_break(BreakJumpTarget);
2949 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
2952 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2959 if (!isa<CompoundStmt>(D->
getBody()))
2960 addLocalScopeAndDtors(D->
getBody());
2963 BodyBlock = addStmt(D->
getBody());
2966 BodyBlock = EntryConditionBlock;
2972 if (!KnownVal.isFalse()) {
2980 CFGBlock *LoopBackBlock = createBlock();
2984 addSuccessor(ExitConditionBlock, LoopBackBlock);
2987 addSuccessor(ExitConditionBlock,
nullptr);
2992 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3010 Block = createBlock(
false);
3011 Block->setTerminator(C);
3015 if (ContinueJumpTarget.block) {
3016 addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C);
3017 addSuccessor(Block, ContinueJumpTarget.block);
3025 AddStmtChoice asc) {
3027 if (asc.alwaysAdd(*
this, E)) {
3029 appendStmt(Block, E);
3037 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3038 lastBlock = addStmt(VA->getSizeExpr());
3046 if (asc.alwaysAdd(*
this, SE)) {
3048 appendStmt(Block, SE);
3056 CFGBlock *SwitchSuccessor =
nullptr;
3065 LocalScope::const_iterator SwitchBeginScopePos = ScopePos;
3066 addLocalScopeForVarDecl(VD);
3067 addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator);
3073 SwitchSuccessor = Block;
3074 }
else SwitchSuccessor = Succ;
3078 save_default(DefaultCaseBlock);
3084 DefaultCaseBlock = SwitchSuccessor;
3087 SwitchTerminatedBlock = createBlock(
false);
3091 Succ = SwitchSuccessor;
3092 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3097 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3106 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3108 bool b = tryEvaluate(Terminator->
getCond(), result);
3110 b ? &result :
nullptr);
3114 if (!isa<CompoundStmt>(Terminator->
getBody()))
3115 addLocalScopeAndDtors(Terminator->
getBody());
3117 addStmt(Terminator->
getBody());
3129 bool SwitchAlwaysHasSuccessor =
false;
3130 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3133 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3134 !SwitchAlwaysHasSuccessor);
3137 SwitchTerminatedBlock->setTerminator(Terminator);
3138 Block = SwitchTerminatedBlock;
3144 if (
Expr *Init = VD->getInit()) {
3147 LastBlock = addStmt(Init);
3154 static bool shouldAddCase(
bool &switchExclusivelyCovered,
3161 bool addCase =
false;
3163 if (!switchExclusivelyCovered) {
3167 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3169 if (condInt == lhsInt) {
3171 switchExclusivelyCovered =
true;
3173 else if (condInt > lhsInt) {
3177 if (V2 >= condInt) {
3179 switchExclusivelyCovered =
true;
3193 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3199 while (isa<CaseStmt>(Sub)) {
3200 CFGBlock *currentBlock = createBlock(
false);
3204 addSuccessor(LastBlock, currentBlock);
3206 TopBlock = currentBlock;
3208 addSuccessor(SwitchTerminatedBlock,
3209 shouldAddCase(switchExclusivelyCovered, switchCond,
3211 ? currentBlock :
nullptr);
3213 LastBlock = currentBlock;
3214 CS = cast<CaseStmt>(Sub);
3223 CaseBlock = createBlock();
3234 assert(SwitchTerminatedBlock);
3235 addSuccessor(SwitchTerminatedBlock, CaseBlock,
3236 shouldAddCase(switchExclusivelyCovered, switchCond,
3243 addSuccessor(LastBlock, CaseBlock);
3257 DefaultCaseBlock = Block;
3259 if (!DefaultCaseBlock)
3260 DefaultCaseBlock = createBlock();
3264 DefaultCaseBlock->setLabel(Terminator);
3279 Succ = DefaultCaseBlock;
3281 return DefaultCaseBlock;
3292 TrySuccessor = Block;
3293 }
else TrySuccessor = Succ;
3295 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
3298 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3302 bool HasCatchAll =
false;
3305 Succ = TrySuccessor;
3311 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
3316 addSuccessor(NewTryTerminatedBlock, CatchBlock);
3319 if (PrevTryTerminatedBlock)
3320 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
3322 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3326 Succ = TrySuccessor;
3330 cfg->addTryDispatchBlock(TryTerminatedBlock);
3332 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
3348 LocalScope::const_iterator BeginScopePos = ScopePos;
3349 addLocalScopeForVarDecl(VD);
3350 addAutomaticObjDtors(ScopePos, BeginScopePos, CS);
3358 CatchBlock = createBlock();
3364 appendStmt(CatchBlock, CS);
3399 addLocalScopeForStmt(Range);
3401 addLocalScopeForStmt(BeginEnd);
3402 addAutomaticObjDtors(ScopePos, save_scope_pos.get(),
S);
3404 LocalScope::const_iterator ContinueScopePos = ScopePos;
3412 LoopSuccessor = Block;
3414 LoopSuccessor = Succ;
3419 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3422 CFGBlock *ConditionBlock = createBlock(
false);
3427 Block = ConditionBlock;
3428 CFGBlock *BeginConditionBlock = addStmt(C);
3431 assert(BeginConditionBlock == ConditionBlock &&
3432 "condition block in for-range was unexpectedly complex");
3433 (void)BeginConditionBlock;
3438 Succ = ConditionBlock;
3441 TryResult KnownVal(
true);
3444 KnownVal = tryEvaluateBool(S->
getCond());
3457 Succ = addStmt(S->
getInc());
3458 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3462 ContinueJumpTarget.block->setLoopTarget(S);
3482 addSuccessor(ConditionBlock,
3483 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
3488 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3491 Block = createBlock();
3497 AddStmtChoice asc) {
3498 if (BuildOpts.AddTemporaryDtors) {
3506 asc = asc.withAlwaysAdd(
true);
3512 AddStmtChoice asc) {
3513 if (asc.alwaysAdd(*
this, E)) {
3515 appendStmt(Block, E);
3518 asc = asc.withAlwaysAdd(
false);
3524 AddStmtChoice asc) {
3526 appendStmt(Block, C);
3528 return VisitChildren(C);
3532 AddStmtChoice asc) {
3535 appendStmt(Block, NE);
3539 if (BuildOpts.AddCXXNewAllocator)
3540 appendNewAllocator(Block, NE);
3550 AddStmtChoice asc) {
3552 appendStmt(Block, DE);
3555 CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
3558 appendDeleteDtor(Block, RD, DE);
3561 return VisitChildren(DE);
3565 AddStmtChoice asc) {
3566 if (asc.alwaysAdd(*
this, E)) {
3568 appendStmt(Block, E);
3570 asc = asc.withAlwaysAdd(
false);
3576 AddStmtChoice asc) {
3578 appendStmt(Block, C);
3579 return VisitChildren(C);
3583 AddStmtChoice asc) {
3584 if (asc.alwaysAdd(*
this, E)) {
3586 appendStmt(Block, E);
3588 return Visit(E->
getSubExpr(), AddStmtChoice());
3593 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
3596 IBlock = createBlock(
false);
3597 cfg->setIndirectGotoBlock(IBlock);
3605 Block = createBlock(
false);
3606 Block->setTerminator(I);
3607 addSuccessor(Block, IBlock);
3611 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
3612 TempDtorContext &Context) {
3613 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
3620 switch (E->getStmtClass()) {
3622 return VisitChildrenForTemporaryDtors(E, Context);
3624 case Stmt::BinaryOperatorClass:
3625 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
3628 case Stmt::CXXBindTemporaryExprClass:
3629 return VisitCXXBindTemporaryExprForTemporaryDtors(
3630 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
3632 case Stmt::BinaryConditionalOperatorClass:
3633 case Stmt::ConditionalOperatorClass:
3634 return VisitConditionalOperatorForTemporaryDtors(
3635 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
3637 case Stmt::ImplicitCastExprClass:
3639 E = cast<CastExpr>(
E)->getSubExpr();
3642 case Stmt::CXXFunctionalCastExprClass:
3644 E = cast<CXXFunctionalCastExpr>(
E)->getSubExpr();
3647 case Stmt::ParenExprClass:
3648 E = cast<ParenExpr>(
E)->getSubExpr();
3651 case Stmt::MaterializeTemporaryExprClass: {
3657 E =
const_cast<Expr *
>(
3658 cast<MaterializeTemporaryExpr>(
E)
3659 ->GetTemporaryExpr()
3660 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
3662 for (
const Expr *CommaLHS : CommaLHSs) {
3663 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
3669 case Stmt::BlockExprClass:
3674 case Stmt::LambdaExprClass: {
3677 auto *LE = cast<LambdaExpr>(
E);
3679 for (
Expr *Init : LE->capture_inits()) {
3680 if (
CFGBlock *R = VisitForTemporaryDtors(
3681 Init,
false, Context))
3687 case Stmt::CXXDefaultArgExprClass:
3688 E = cast<CXXDefaultArgExpr>(
E)->getExpr();
3691 case Stmt::CXXDefaultInitExprClass:
3692 E = cast<CXXDefaultInitExpr>(
E)->getExpr();
3697 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
3698 TempDtorContext &Context) {
3699 if (isa<LambdaExpr>(E)) {
3709 for (
Stmt *Child : E->children())
3711 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
3717 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
3721 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
3723 RHSExecuted.negate();
3728 TempDtorContext RHSContext(
3729 bothKnownTrue(Context.KnownExecuted, RHSExecuted));
3730 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
3731 InsertTempDtorDecisionBlock(RHSContext);
3741 return LHSBlock ? LHSBlock : RHSBlock;
3749 return RHSBlock ? RHSBlock : LHSBlock;
3752 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
3756 if (!BindToTemporary) {
3768 Block = createNoReturnBlock();
3769 }
else if (Context.needsTempDtorBranch()) {
3773 Block = createBlock();
3777 if (Context.needsTempDtorBranch()) {
3778 Context.setDecisionPoint(Succ, E);
3780 appendTemporaryDtor(Block, E);
3787 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
3789 if (!Context.TerminatorExpr) {
3793 assert(Context.TerminatorExpr);
3794 CFGBlock *Decision = createBlock(
false);
3796 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
3797 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
3798 !Context.KnownExecuted.isTrue());
3802 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
3804 TempDtorContext &Context) {
3808 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
3809 TryResult NegatedVal = ConditionVal;
3810 if (NegatedVal.isKnown()) NegatedVal.negate();
3812 TempDtorContext TrueContext(
3813 bothKnownTrue(Context.KnownExecuted, ConditionVal));
3814 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
3817 Block = ConditionBlock;
3818 Succ = ConditionSucc;
3819 TempDtorContext FalseContext(
3820 bothKnownTrue(Context.KnownExecuted, NegatedVal));
3821 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
3823 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
3824 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
3825 }
else if (TrueContext.TerminatorExpr) {
3827 InsertTempDtorDecisionBlock(TrueContext);
3829 InsertTempDtorDecisionBlock(FalseContext);
3840 bool first_block =
begin() ==
end();
3844 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
3849 Entry = Exit = &
back();
3859 return Builder.buildCFG(D, Statement);
3868 llvm_unreachable(
"getDestructorDecl should only be used with "
3871 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
3875 ty = arrayType->getElementType();
3879 cast<CXXRecordDecl>(recordType->
getDecl());
3883 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
3892 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
3902 llvm_unreachable(
"getKind() returned bogus value");
3916 : ReachableBlock(IsReachable ? B : nullptr),
3917 UnreachableBlock(!IsReachable ? B : nullptr,
3918 B && IsReachable ? AB_Normal : AB_Unreachable) {}
3921 : ReachableBlock(B),
3922 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
3923 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
3931 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
3947 if (S->isAllEnumCasesCovered()) {
3949 if (!L || !isa<CaseStmt>(L))
3965 typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
3966 typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
3969 signed currentBlock;
3975 : currentBlock(0), currStmt(0), LangOpts(LO)
3980 BI != BEnd; ++BI, ++j ) {
3982 const Stmt *stmt= SE->getStmt();
3983 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
3986 switch (stmt->getStmtClass()) {
3987 case Stmt::DeclStmtClass:
3988 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
3990 case Stmt::IfStmtClass: {
3991 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
3996 case Stmt::ForStmtClass: {
3997 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4002 case Stmt::WhileStmtClass: {
4004 cast<WhileStmt>(
stmt)->getConditionVariable();
4009 case Stmt::SwitchStmtClass: {
4011 cast<SwitchStmt>(
stmt)->getConditionVariable();
4016 case Stmt::CXXCatchStmtClass: {
4018 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
4031 ~StmtPrinterHelper()
override {}
4033 const LangOptions &getLangOpts()
const {
return LangOpts; }
4034 void setBlockID(
signed i) { currentBlock = i; }
4035 void setStmtID(
unsigned i) { currStmt = i; }
4037 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
4040 if (I == StmtMap.end())
4043 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4044 && I->second.second == currStmt) {
4048 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4052 bool handleDecl(
const Decl *D, raw_ostream &OS) {
4055 if (I == DeclMap.end())
4058 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4059 && I->second.second == currStmt) {
4063 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4071 class CFGBlockTerminatorPrint
4072 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4075 StmtPrinterHelper* Helper;
4078 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4080 : OS(os), Helper(helper), Policy(Policy) {
4084 void VisitIfStmt(
IfStmt *I) {
4087 C->printPretty(OS, Helper, Policy);
4091 void VisitStmt(
Stmt *Terminator) {
4092 Terminator->printPretty(OS, Helper, Policy);
4097 OS <<
"static init " << VD->
getName();
4100 void VisitForStmt(
ForStmt *F) {
4106 C->printPretty(OS, Helper, Policy);
4116 C->printPretty(OS, Helper, Policy);
4119 void VisitDoStmt(
DoStmt *D) {
4120 OS <<
"do ... while ";
4122 C->printPretty(OS, Helper, Policy);
4125 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4127 Terminator->
getCond()->printPretty(OS, Helper, Policy);
4136 Cond->printPretty(OS, Helper, Policy);
4137 OS <<
" ? ... : ...";
4141 OS <<
"__builtin_choose_expr( ";
4143 Cond->printPretty(OS, Helper, Policy);
4150 T->printPretty(OS, Helper, Policy);
4160 B->
getLHS()->printPretty(OS, Helper, Policy);
4170 llvm_unreachable(
"Invalid logical operator.");
4174 void VisitExpr(
Expr *E) {
4175 E->printPretty(OS, Helper, Policy);
4181 OS <<
"(Temp Dtor) ";
4187 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
4190 const Stmt *S = CS->getStmt();
4191 assert(S !=
nullptr &&
"Expecting non-null Stmt");
4194 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
4198 if (Children.begin() != Children.end()) {
4209 Helper.handledStmt(B->
getRHS(),OS);
4214 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4216 if (isa<CXXOperatorCallExpr>(S)) {
4217 OS <<
" (OperatorCall)";
4219 else if (isa<CXXBindTemporaryExpr>(S)) {
4220 OS <<
" (BindTemporary)";
4223 OS <<
" (CXXConstructExpr, " << CCE->getType().getAsString() <<
")";
4225 else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
4226 OS <<
" (" << CE->getStmtClassName() <<
", "
4227 << CE->getCastKindName()
4228 <<
", " << CE->getType().getAsString()
4246 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4250 OS <<
" (Base initializer)\n";
4252 OS <<
" (Delegating initializer)\n";
4253 else OS <<
" (Member initializer)\n";
4257 const VarDecl *VD = DE->getVarDecl();
4258 Helper.handleDecl(VD, OS);
4266 OS <<
" (Implicit destructor)\n";
4269 OS <<
"CFGNewAllocator(";
4270 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
4271 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
4279 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
4280 OS <<
"->~" << RD->
getName().str() <<
"()";
4281 OS <<
" (Implicit destructor)\n";
4285 OS <<
" (Base object destructor)\n";
4288 const FieldDecl *FD = ME->getFieldDecl();
4290 OS <<
"this->" << FD->
getName();
4292 OS <<
" (Member object destructor)\n";
4298 OS <<
"() (Temporary object destructor)\n";
4304 StmtPrinterHelper &Helper,
bool print_edges,
4311 OS.changeColor(raw_ostream::YELLOW,
true);
4316 OS <<
" (ENTRY)]\n";
4317 else if (&B == &cfg->
getExit())
4320 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
4322 OS <<
" (NORETURN)]\n";
4335 if (
LabelStmt *L = dyn_cast<LabelStmt>(Label))
4337 else if (
CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
4340 C->
getLHS()->printPretty(OS, &Helper,
4344 C->
getRHS()->printPretty(OS, &Helper,
4347 }
else if (isa<DefaultStmt>(Label))
4349 else if (
CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
4359 llvm_unreachable(
"Invalid label statement in CFGBlock.");
4368 I !=
E ; ++
I, ++j ) {
4374 OS << llvm::format(
"%3d", j) <<
": ";
4376 Helper.setStmtID(j);
4384 OS.changeColor(raw_ostream::GREEN);
4388 Helper.setBlockID(-1);
4391 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
4402 const raw_ostream::Colors Color = raw_ostream::BLUE;
4404 OS.changeColor(Color);
4412 OS.changeColor(Color);
4421 bool Reachable =
true;
4424 B = I->getPossiblyUnreachableBlock();
4429 OS <<
"(Unreachable)";
4440 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
4442 OS.changeColor(Color);
4450 OS.changeColor(Color);
4460 bool Reachable =
true;
4463 B = I->getPossiblyUnreachableBlock();
4469 OS <<
"(Unreachable)";
4486 print(llvm::errs(), LO, ShowColors);
4491 StmtPrinterHelper Helper(
this, LO);
4494 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
4499 if (&(**I) == &getEntry() || &(**I) == &getExit())
4502 print_block(OS,
this, **I, Helper,
true, ShowColors);
4506 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
4513 bool ShowColors)
const {
4514 print(llvm::errs(), cfg, LO, ShowColors);
4525 StmtPrinterHelper Helper(cfg, LO);
4526 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
4533 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
4538 Stmt *Terminator = this->Terminator;
4544 switch (Terminator->getStmtClass()) {
4548 case Stmt::CXXForRangeStmtClass:
4549 E = cast<CXXForRangeStmt>(Terminator)->getCond();
4552 case Stmt::ForStmtClass:
4553 E = cast<ForStmt>(Terminator)->getCond();
4556 case Stmt::WhileStmtClass:
4557 E = cast<WhileStmt>(Terminator)->getCond();
4560 case Stmt::DoStmtClass:
4561 E = cast<DoStmt>(Terminator)->getCond();
4564 case Stmt::IfStmtClass:
4565 E = cast<IfStmt>(Terminator)->getCond();
4568 case Stmt::ChooseExprClass:
4569 E = cast<ChooseExpr>(Terminator)->getCond();
4572 case Stmt::IndirectGotoStmtClass:
4573 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
4576 case Stmt::SwitchStmtClass:
4577 E = cast<SwitchStmt>(Terminator)->getCond();
4580 case Stmt::BinaryConditionalOperatorClass:
4581 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
4584 case Stmt::ConditionalOperatorClass:
4585 E = cast<ConditionalOperator>(Terminator)->getCond();
4588 case Stmt::BinaryOperatorClass:
4589 E = cast<BinaryOperator>(Terminator)->getLHS();
4592 case Stmt::ObjCForCollectionStmtClass:
4613 StmtPrinterHelper H(
this, LO);
4615 llvm::ViewGraph(
this,
"CFG");
4616 GraphHelper =
nullptr;
4629 std::string OutSStr;
4630 llvm::raw_string_ostream Out(OutSStr);
4631 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
4632 std::string& OutStr = Out.str();
4634 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
4637 for (
unsigned i = 0; i != OutStr.length(); ++i)
4638 if (OutStr[i] ==
'\n') {
4640 OutStr.insert(OutStr.begin()+i+1,
'l');
Defines the clang::ASTContext interface.
unsigned getNumInits() const
CFGNewAllocator - Represents C++ allocator call.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
static const VariableArrayType * FindVA(QualType Ty)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
A class which contains all the information about a particular captured value.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
QualType getType() const
Retrieves the type of the base class.
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
std::reverse_iterator< body_iterator > reverse_body_iterator
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
bool isArgumentType() const
IfStmt - This represents an if/then/else.
bool isRecordType() const
Decl - This represents one declaration (or definition), e.g.
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
llvm::BumpPtrAllocator & getAllocator()
The base class of the type hierarchy.
Represents Objective-C's @throw statement.
CFGDeleteDtor - Represents C++ object destructor generated from a call to delete. ...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
const Expr * getInit() const
Represents a call to a C++ constructor.
const Stmt * getElse() const
bool isBlockPointerType() const
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
unsigned IgnoreDefaultsWithCoveredEnums
Represents a C++ constructor within a class.
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFG that outputs to an ostream.
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Expr * getInit() const
Get the initializer.
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
const Expr * getCallee() const
unsigned succ_size() const
Describes how types, statements, expressions, and declarations should be printed. ...
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E)
A C++ throw-expression (C++ [except.throw]).
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
static bool isAssignmentOp(Opcode Opc)
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
LabelStmt - Represents a label, which has a substatement.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void setLoopTarget(const Stmt *loopTarget)
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)
unsigned getNumSemanticExprs() const
bool isReferenceType() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated for automatic object or t...
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
void setTerminator(CFGTerminator Term)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isAnyDestructorNoReturn() const
Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn...
StorageClass getStorageClass() const
Returns the storage class as written in the source.
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
Represents Objective-C's @catch statement.
const CompoundStmt * getSynchBody() const
IndirectGotoStmt - This represents an indirect goto.
Describes an C or C++ initializer list.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
const LangOptions & getLangOpts() const
Expr * getTrueExpr() const
APValue Val
Val - This is the value the expression can be folded to.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Stmt * getHandlerBlock() const
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Expr * getInitializer()
The initializer of this new-expression.
field_range fields() const
unsigned pred_size() const
ElementList::const_iterator const_iterator
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
A builtin binary operation expression such as "x + y" or "x <= y".
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
RecordDecl * getDecl() const
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const DeclStmt * getConditionVariableDeclStmt() const
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
Scope - A scope is a transient data structure that is used while parsing the program.
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
detail::InMemoryDirectory::const_iterator I
arg_iterator placement_arg_end()
llvm::APInt getValue() const
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents a prototype with parameter type info, e.g.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
CFGBlock - Represents a single basic block in a source-level CFG.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
bool isFunctionPointerType() const
LabelDecl * getDecl() const
bool isKnownToHaveBooleanValue() const
isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...
QualType getPointeeType() const
Expr - This represents one expression.
Stmt * getTerminatorCondition(bool StripParens=true)
bool isNoReturn(ASTContext &astContext) const
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "while" statement, if any.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Represents a C++ functional cast expression that builds a temporary object.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
Represents Objective-C's @synchronized statement.
CXXTryStmt - A C++ try block, including all handlers.
const SwitchCase * getSwitchCaseList() const
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine()) const
AdjacentBlocks::const_iterator const_pred_iterator
Expr * getSubExpr() const
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
unsigned getBlockID() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
const DeclStmt * getConditionVariableDeclStmt() const
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
const DeclStmt * getConditionVariableDeclStmt() const
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
CFGBaseDtor - Represents C++ object destructor implicitly generated for base object in destructor...
The result type of a method or function.
void viewCFG(const LangOptions &LO) const
ElementList::iterator iterator
DoStmt - This represents a 'do/while' stmt.
LabelDecl * getLabel() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
bool hasNoReturnElement() const
CFGTerminator getTerminator()
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const
EvaluateAsBooleanCondition - Return true if this is a constant which we we can fold and convert to a ...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Encodes a location in the source.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
const TemplateArgument * iterator
Represents a C++ temporary.
FieldDecl * getAnyMember() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
void setLabel(Stmt *Statement)
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
buildCFG - Builds a CFG from an AST.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
const Expr * getCond() const
bool isTemporaryDtorsBranch() const
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
reverse_body_iterator body_rend()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
CK_DerivedToBase - A conversion from a C++ class pointer to a base class pointer. ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)
decl_iterator decl_begin()
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
reverse_decl_iterator decl_rbegin()
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "switch" statement, if any.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
static QualType findBoundMemberType(const Expr *expr)
Given an expression of bound-member type, find the type of the member.
Expr ** getInits()
Retrieve the set of initializers.
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
static bool isLogicalOp(Opcode Opc)
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
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.
const BlockDecl * getBlockDecl() const
QualType getType() const
Return the type wrapped by this type source info.
AdjacentBlocks::const_iterator const_succ_iterator
const Decl * getSingleDecl() const
QualType getPointeeType() const
AddrLabelExpr - The GNU address of label extension, representing &&label.
ast_type_traits::DynTypedNode Node
void push_back(const_reference Elt, BumpVectorContext &C)
Represents a template argument.
pred_iterator pred_begin()
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "if" statement, if any.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
EvalResult is a struct with detailed info about an evaluated expression.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
const Stmt * getBody() const
ExprIterator arg_iterator
static StmtPrinterHelper * GraphHelper
const Expr * getSynchExpr() const
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
unsigned getNumHandlers() const
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
detail::InMemoryDirectory::const_iterator E
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
This class represents a potential adjacent block in the CFG.
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
const Stmt * getThen() const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
SwitchStmt - This represents a 'switch' stmt.
CFGBlock * getIndirectGotoBlock()
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
const T * getAs() const
Member-template getAs<specific type>'.
Expr * getFalseExpr() const
DeclStmt * getBeginEndStmt()
const Stmt * getSubStmt() const
Represents Objective-C's collection statement.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Represents a C++ base or member initializer.
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
reverse_decl_iterator decl_rend()
Base for LValueReferenceType and RValueReferenceType.
CanQualType BoundMemberTy
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
LabelDecl * getLabel() const
const DeclStmt * getConditionVariableDeclStmt() const
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
Represents a base class of a C++ class.
CK_UncheckedDerivedToBase - A conversion from a C++ class pointer/reference to a base class that can ...
arg_iterator placement_arg_begin()
DeclStmt * getRangeStmt()
GotoStmt - This represents a direct goto.
A use of a default initializer in a constructor or in aggregate initialization.
unsigned IgnoreNullPredecessors
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
void setHasNoReturnElement()
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Represents a C++ struct/union/class.
BoundNodesTreeBuilder *const Builder
ContinueStmt - This represents a continue.
reverse_body_iterator body_rbegin()
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
CXXCatchStmt - This represents a C++ catch block.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr.type.conv]).
bool operator!=(CanQual< T > x, CanQual< U > y)
WhileStmt - This represents a 'while' stmt.
const Expr * getCond() const
CFGElement - Represents a top-level expression in a basic block.
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
CFGTerminator - Represents CFGBlock terminator statement.
CompoundStmt * getTryBlock()
CFGMemberDtor - Represents C++ object destructor implicitly generated for member object in destructor...
Represents Objective-C's @try ... @catch ... @finally statement.
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Full-expression storage duration (for temporaries).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
CK_NoOp - A conversion which does not affect the type other than (possibly) adding qualifiers...
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument for this lambda expression...
VarDecl * getExceptionDecl() const
A reference to a declared variable, function, enum, etc.
std::reverse_iterator< decl_iterator > reverse_decl_iterator
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
BreakStmt - This represents a break.
CFGInitializer - Represents C++ base or member initializer from constructor's initialization list...
Expr * getSemanticExpr(unsigned index)
const Expr * getSubExpr() const
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
SourceLocation getLocation() const
Represents a C array with a specified size that is not an integer-constant-expression.
CFGBlock * createBlock()
createBlock - Create a new block in the CFG.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const char * getName() const
Represents Objective-C's @autoreleasepool Statement.
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
const CXXDestructorDecl * getDestructor() const
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
CFGTemporaryDtor - Represents C++ object destructor implicitly generated at the end of full expressio...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Defines enum values for all the target-independent builtin functions.
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
QualType getArgumentType() const