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();
236 const_iterator shared_parent(const_iterator L);
239 friend class const_iterator;
245 AutomaticVarsTy Vars;
253 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
256 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
259 Vars.push_back(VD, ctx);
268 const_iterator F = *
this;
269 while (F.Scope != L.Scope) {
270 assert (F != const_iterator()
271 &&
"L iterator is not reachable from F iterator.");
275 D += F.VarIter - L.VarIter;
283 LocalScope::const_iterator
284 LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
285 llvm::SmallPtrSet<const LocalScope *, 4> ScopesOfL;
287 ScopesOfL.insert(L.Scope);
288 if (L == const_iterator())
293 const_iterator F = *
this;
295 if (ScopesOfL.count(F.Scope))
297 assert(F != const_iterator() &&
298 "L iterator is not reachable from F iterator.");
306 struct BlockScopePosPair {
307 BlockScopePosPair() : block(nullptr) {}
308 BlockScopePosPair(
CFGBlock *b, LocalScope::const_iterator scopePos)
309 : block(b), scopePosition(scopePos) {}
312 LocalScope::const_iterator scopePosition;
322 TryResult(
bool b) :
X(b ? 1 : 0) {}
323 TryResult() :
X(-1) {}
325 bool isTrue()
const {
return X == 1; }
326 bool isFalse()
const {
return X == 0; }
327 bool isKnown()
const {
return X >= 0; }
334 TryResult bothKnownTrue(TryResult R1, TryResult R2) {
335 if (!R1.isKnown() || !R2.isKnown())
337 return TryResult(R1.isTrue() && R2.isTrue());
340 class reverse_children {
344 reverse_children(
Stmt *S);
347 iterator begin()
const {
return children.rbegin(); }
348 iterator end()
const {
return children.rend(); }
352 reverse_children::reverse_children(
Stmt *S) {
353 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
359 case Stmt::InitListExprClass: {
371 childrenBuf.push_back(SubStmt);
374 children = childrenBuf;
392 typedef BlockScopePosPair JumpTarget;
393 typedef BlockScopePosPair JumpSource;
396 std::unique_ptr<CFG> cfg;
400 JumpTarget ContinueJumpTarget;
401 JumpTarget BreakJumpTarget;
407 LocalScope::const_iterator ScopePos;
410 typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
415 typedef std::vector<JumpSource> BackpatchBlocksTy;
416 BackpatchBlocksTy BackpatchBlocks;
419 typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
420 LabelSetTy AddressTakenLabels;
426 bool switchExclusivelyCovered;
429 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
430 const Stmt *lastLookup;
434 typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy;
435 CachedBoolEvalsTy CachedBoolEvals;
441 Block(nullptr), Succ(nullptr),
442 SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
443 TryTerminatedBlock(nullptr), badCFG(
false), BuildOpts(buildOpts),
444 switchExclusivelyCovered(
false), switchCond(nullptr),
445 cachedEntry(nullptr), lastLookup(nullptr) {}
448 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
491 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
511 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
544 struct TempDtorContext {
546 : IsConditional(
false), KnownExecuted(
true), Succ(nullptr),
547 TerminatorExpr(nullptr) {}
549 TempDtorContext(TryResult KnownExecuted)
550 : IsConditional(
true), KnownExecuted(KnownExecuted), Succ(nullptr),
551 TerminatorExpr(nullptr) {}
559 bool needsTempDtorBranch()
const {
560 return IsConditional && !TerminatorExpr;
570 const bool IsConditional;
571 const TryResult KnownExecuted;
578 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
583 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
585 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
588 void InsertTempDtorDecisionBlock(
const TempDtorContext &
Context,
597 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
598 CFGBlock *createBlock(
bool add_successor =
true);
602 return Visit(S, AddStmtChoice::AlwaysAdd);
605 void addAutomaticObjDtors(LocalScope::const_iterator B,
606 LocalScope::const_iterator E,
Stmt *S);
607 void addLifetimeEnds(LocalScope::const_iterator B,
608 LocalScope::const_iterator E,
Stmt *S);
609 void addAutomaticObjHandling(LocalScope::const_iterator B,
610 LocalScope::const_iterator E,
Stmt *S);
614 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
616 void addLocalScopeForStmt(
Stmt *S);
617 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
618 LocalScope*
Scope =
nullptr);
619 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
621 void addLocalScopeAndDtors(
Stmt *S);
625 if (alwaysAdd(S) && cachedEntry)
626 cachedEntry->second = B;
629 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
630 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
659 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
660 LocalScope::const_iterator B, LocalScope::const_iterator E);
662 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
663 LocalScope::const_iterator B,
664 LocalScope::const_iterator E);
668 cfg->getBumpVectorContext());
675 cfg->getBumpVectorContext());
681 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
686 const Expr *BoolExpr = RHSExpr;
687 bool IntFirst =
true;
697 llvm::APInt IntValue = IntLiteral->
getValue();
698 if ((IntValue == 1) || (IntValue == 0))
702 !IntValue.isNegative();
705 if (Bok == BO_GT || Bok == BO_GE) {
708 return TryResult(IntFirst == IntLarger);
712 return TryResult(IntFirst != IntLarger);
720 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
725 const Expr *BoolExpr = RHSExpr;
736 if (BitOp && (BitOp->
getOpcode() == BO_And ||
749 llvm::APInt L1 = IntLiteral->
getValue();
750 llvm::APInt L2 = IntLiteral2->
getValue();
751 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
752 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
753 if (BuildOpts.Observer)
754 BuildOpts.Observer->compareBitwiseEquality(B,
758 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
759 llvm::APInt IntValue = IntLiteral->
getValue();
760 if ((IntValue == 1) || (IntValue == 0)) {
763 return TryResult(B->
getOpcode() != BO_EQ);
770 const llvm::APSInt &Value1,
771 const llvm::APSInt &Value2) {
772 assert(Value1.isSigned() == Value2.isSigned());
777 return TryResult(Value1 == Value2);
779 return TryResult(Value1 != Value2);
781 return TryResult(Value1 < Value2);
783 return TryResult(Value1 <= Value2);
785 return TryResult(Value1 > Value2);
787 return TryResult(Value1 >= Value2);
804 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
810 std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS);
812 if (!Decl1 || !Expr1)
818 std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS);
820 if (!Decl2 || !Expr2)
829 if (!areExprTypesCompatible(Expr1, Expr2))
839 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
844 const llvm::APSInt Values[] = {
846 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
850 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
855 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
864 bool AlwaysTrue =
true, AlwaysFalse =
true;
865 for (
const llvm::APSInt &
Value : Values) {
866 TryResult Res1, Res2;
867 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
868 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
870 if (!Res1.isKnown() || !Res2.isKnown())
874 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
875 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
877 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
878 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
882 if (AlwaysTrue || AlwaysFalse) {
883 if (BuildOpts.Observer)
884 BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
885 return TryResult(AlwaysTrue);
892 if (!BuildOpts.PruneTriviallyFalseEdges)
901 TryResult tryEvaluateBool(
Expr *S) {
902 if (!BuildOpts.PruneTriviallyFalseEdges ||
907 if (Bop->isLogicalOp()) {
909 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
910 if (I != CachedBoolEvals.end())
914 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
919 switch (Bop->getOpcode()) {
928 if (Bop->getLHS()->EvaluateAsInt(IntVal, *
Context)) {
929 if (!IntVal.getBoolValue()) {
930 return TryResult(
false);
933 if (Bop->getRHS()->EvaluateAsInt(IntVal, *
Context)) {
934 if (!IntVal.getBoolValue()) {
935 return TryResult(
false);
944 return evaluateAsBooleanConditionNoCache(S);
948 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
950 if (Bop->isLogicalOp()) {
951 TryResult LHS = tryEvaluateBool(Bop->getLHS());
955 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
958 TryResult RHS = tryEvaluateBool(Bop->getRHS());
960 if (Bop->getOpcode() == BO_LOr)
961 return LHS.isTrue() || RHS.isTrue();
963 return LHS.isTrue() && RHS.isTrue();
966 TryResult RHS = tryEvaluateBool(Bop->getRHS());
970 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
973 TryResult BopRes = checkIncorrectLogicOperator(Bop);
974 if (BopRes.isKnown())
975 return BopRes.isTrue();
980 }
else if (Bop->isEqualityOp()) {
981 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
982 if (BopRes.isKnown())
983 return BopRes.isTrue();
984 }
else if (Bop->isRelationalOp()) {
985 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
986 if (BopRes.isKnown())
987 return BopRes.isTrue();
998 bool hasTrivialDestructor(
VarDecl *VD);
1001 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1003 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
1006 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
1007 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1009 if (!BuildOpts.forcedBlkExprs)
1012 if (lastLookup == stmt) {
1014 assert(cachedEntry->first == stmt);
1027 assert(!cachedEntry);
1031 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1032 if (itr == fb->end()) {
1033 cachedEntry =
nullptr;
1037 cachedEntry = &*itr;
1044 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1046 if (vat->getSizeExpr())
1049 t = vt->getElementType().getTypePtr();
1060 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1068 Succ = createBlock();
1069 assert(Succ == &cfg->getExit());
1072 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1073 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1075 if (BuildOpts.AddImplicitDtors)
1077 addImplicitDtorsForDestructor(DD);
1087 for (
auto *I : llvm::reverse(CD->inits())) {
1088 B = addInitializer(I);
1099 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1100 E = BackpatchBlocks.end(); I !=
E; ++
I ) {
1104 LabelMapTy::iterator LI = LabelMap.find(G->
getLabel());
1108 if (LI == LabelMap.end())
continue;
1110 JumpTarget JT = LI->second;
1111 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1113 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1115 addSuccessor(B, JT.block);
1119 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1120 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1121 E = AddressTakenLabels.end(); I !=
E; ++
I ) {
1124 LabelMapTy::iterator LI = LabelMap.find(*I);
1128 if (LI == LabelMap.end())
continue;
1130 addSuccessor(B, LI->second.block);
1134 cfg->setEntry(createBlock());
1136 return std::move(cfg);
1141 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1143 if (add_successor && Succ)
1144 addSuccessor(B, Succ);
1151 CFGBlock *CFGBuilder::createNoReturnBlock() {
1154 addSuccessor(B, &cfg->getExit(), Succ);
1160 if (!BuildOpts.AddInitializers)
1163 bool HasTemporaries =
false;
1169 HasTemporaries = isa<ExprWithCleanups>(Init);
1171 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1174 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1180 appendInitializer(Block, I);
1183 if (HasTemporaries) {
1186 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1188 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1211 bool *FoundMTE =
nullptr) {
1218 Init = EWC->getSubExpr();
1224 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1225 Init = MTE->GetTemporaryExpr();
1232 if (
const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
1233 if ((CE->getCastKind() == CK_DerivedToBase ||
1234 CE->getCastKind() == CK_UncheckedDerivedToBase ||
1235 CE->getCastKind() == CK_NoOp) &&
1237 Init = CE->getSubExpr();
1243 if (
const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
1244 if (!ME->isArrow() && ME->getBase()->isRValue()) {
1245 Init = ME->getBase();
1256 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1257 LocalScope::const_iterator E,
1259 if (BuildOpts.AddImplicitDtors)
1260 addAutomaticObjDtors(B, E, S);
1261 if (BuildOpts.AddLifetime)
1262 addLifetimeEnds(B, E, S);
1266 void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1267 LocalScope::const_iterator E,
Stmt *S) {
1268 if (!BuildOpts.AddLifetime)
1278 LocalScope::const_iterator
P = B.shared_parent(E);
1279 int dist = B.distance(P);
1286 DeclsTrivial.reserve(dist);
1287 DeclsNonTrivial.reserve(dist);
1289 for (LocalScope::const_iterator I = B; I !=
P; ++
I)
1290 if (hasTrivialDestructor(*I))
1291 DeclsTrivial.push_back(*I);
1293 DeclsNonTrivial.push_back(*I);
1299 E = DeclsTrivial.rend();
1301 appendLifetimeEnds(Block, *I, S);
1304 I = DeclsNonTrivial.rbegin(),
1305 E = DeclsNonTrivial.rend();
1307 appendLifetimeEnds(Block, *I, S);
1313 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1314 LocalScope::const_iterator E,
Stmt *S) {
1315 if (!BuildOpts.AddImplicitDtors)
1326 Decls.reserve(B.distance(E));
1327 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1328 Decls.push_back(*I);
1338 Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit());
1343 Block = createNoReturnBlock();
1347 appendAutomaticObjDtor(Block, *I, S);
1354 assert (BuildOpts.AddImplicitDtors
1355 &&
"Can be called only when dtors should be added");
1359 for (
const auto &VI : RD->
vbases()) {
1360 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1363 appendBaseDtor(Block, &VI);
1368 for (
const auto &BI : RD->
bases()) {
1369 if (!BI.isVirtual()) {
1370 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1373 appendBaseDtor(Block, &BI);
1379 for (
auto *FI : RD->
fields()) {
1383 if (AT->getSize() == 0)
1385 QT = AT->getElementType();
1391 appendMemberDtor(Block, FI);
1398 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1401 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1402 return new (alloc.Allocate<LocalScope>())
1408 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1409 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
1412 LocalScope *Scope =
nullptr;
1416 for (
auto *BI : CS->body()) {
1418 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1419 Scope = addLocalScopeForDeclStmt(DS, Scope);
1427 addLocalScopeForDeclStmt(DS);
1432 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1433 LocalScope* Scope) {
1434 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
1437 for (
auto *DI : DS->
decls())
1438 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1439 Scope = addLocalScopeForVarDecl(VD, Scope);
1443 bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
1460 bool FoundMTE =
false;
1461 QT = getReferenceInitTemporaryType(*Context, Init, &FoundMTE);
1468 if (AT->getSize() == 0)
1470 QT = AT->getElementType();
1482 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1483 LocalScope* Scope) {
1484 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1485 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1486 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
1495 default:
return Scope;
1498 if (BuildOpts.AddImplicitDtors) {
1499 if (!hasTrivialDestructor(VD)) {
1501 Scope = createOrReuseLocalScope(Scope);
1503 ScopePos = Scope->begin();
1508 assert(BuildOpts.AddLifetime);
1510 Scope = createOrReuseLocalScope(Scope);
1512 ScopePos = Scope->begin();
1518 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1519 LocalScope::const_iterator scopeBeginPos = ScopePos;
1520 addLocalScopeForStmt(S);
1521 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
1531 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1532 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1533 if (!BuildOpts.AddImplicitDtors)
1538 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1548 void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
1549 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
1550 if (!BuildOpts.AddLifetime)
1555 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1561 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1567 if (
Expr *E = dyn_cast<Expr>(S))
1568 S = E->IgnoreParens();
1572 return VisitStmt(S, asc);
1574 case Stmt::AddrLabelExprClass:
1575 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
1577 case Stmt::BinaryConditionalOperatorClass:
1578 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
1580 case Stmt::BinaryOperatorClass:
1581 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
1583 case Stmt::BlockExprClass:
1584 return VisitBlockExpr(cast<BlockExpr>(S), asc);
1586 case Stmt::BreakStmtClass:
1587 return VisitBreakStmt(cast<BreakStmt>(S));
1589 case Stmt::CallExprClass:
1590 case Stmt::CXXOperatorCallExprClass:
1591 case Stmt::CXXMemberCallExprClass:
1592 case Stmt::UserDefinedLiteralClass:
1593 return VisitCallExpr(cast<CallExpr>(S), asc);
1595 case Stmt::CaseStmtClass:
1596 return VisitCaseStmt(cast<CaseStmt>(S));
1598 case Stmt::ChooseExprClass:
1599 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
1601 case Stmt::CompoundStmtClass:
1602 return VisitCompoundStmt(cast<CompoundStmt>(S));
1604 case Stmt::ConditionalOperatorClass:
1605 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
1607 case Stmt::ContinueStmtClass:
1608 return VisitContinueStmt(cast<ContinueStmt>(S));
1610 case Stmt::CXXCatchStmtClass:
1611 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
1613 case Stmt::ExprWithCleanupsClass:
1614 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
1616 case Stmt::CXXDefaultArgExprClass:
1617 case Stmt::CXXDefaultInitExprClass:
1627 return VisitStmt(S, asc);
1629 case Stmt::CXXBindTemporaryExprClass:
1630 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
1632 case Stmt::CXXConstructExprClass:
1633 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
1635 case Stmt::CXXNewExprClass:
1636 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
1638 case Stmt::CXXDeleteExprClass:
1639 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
1641 case Stmt::CXXFunctionalCastExprClass:
1642 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
1644 case Stmt::CXXTemporaryObjectExprClass:
1645 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
1647 case Stmt::CXXThrowExprClass:
1648 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
1650 case Stmt::CXXTryStmtClass:
1651 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
1653 case Stmt::CXXForRangeStmtClass:
1654 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
1656 case Stmt::DeclStmtClass:
1657 return VisitDeclStmt(cast<DeclStmt>(S));
1659 case Stmt::DefaultStmtClass:
1660 return VisitDefaultStmt(cast<DefaultStmt>(S));
1662 case Stmt::DoStmtClass:
1663 return VisitDoStmt(cast<DoStmt>(S));
1665 case Stmt::ForStmtClass:
1666 return VisitForStmt(cast<ForStmt>(S));
1668 case Stmt::GotoStmtClass:
1669 return VisitGotoStmt(cast<GotoStmt>(S));
1671 case Stmt::IfStmtClass:
1672 return VisitIfStmt(cast<IfStmt>(S));
1674 case Stmt::ImplicitCastExprClass:
1675 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
1677 case Stmt::IndirectGotoStmtClass:
1678 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
1680 case Stmt::LabelStmtClass:
1681 return VisitLabelStmt(cast<LabelStmt>(S));
1683 case Stmt::LambdaExprClass:
1684 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
1686 case Stmt::MemberExprClass:
1687 return VisitMemberExpr(cast<MemberExpr>(S), asc);
1689 case Stmt::NullStmtClass:
1692 case Stmt::ObjCAtCatchStmtClass:
1693 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
1695 case Stmt::ObjCAutoreleasePoolStmtClass:
1696 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
1698 case Stmt::ObjCAtSynchronizedStmtClass:
1699 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
1701 case Stmt::ObjCAtThrowStmtClass:
1702 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
1704 case Stmt::ObjCAtTryStmtClass:
1705 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
1707 case Stmt::ObjCForCollectionStmtClass:
1708 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
1710 case Stmt::OpaqueValueExprClass:
1713 case Stmt::PseudoObjectExprClass:
1714 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
1716 case Stmt::ReturnStmtClass:
1717 return VisitReturnStmt(cast<ReturnStmt>(S));
1719 case Stmt::UnaryExprOrTypeTraitExprClass:
1720 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1723 case Stmt::StmtExprClass:
1724 return VisitStmtExpr(cast<StmtExpr>(S), asc);
1726 case Stmt::SwitchStmtClass:
1727 return VisitSwitchStmt(cast<SwitchStmt>(S));
1729 case Stmt::UnaryOperatorClass:
1730 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
1732 case Stmt::WhileStmtClass:
1733 return VisitWhileStmt(cast<WhileStmt>(S));
1737 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
1738 if (asc.alwaysAdd(*
this, S)) {
1740 appendStmt(Block, S);
1743 return VisitChildren(S);
1752 reverse_children RChildren(S);
1753 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
1755 if (
Stmt *Child = *I)
1763 AddStmtChoice asc) {
1764 AddressTakenLabels.insert(A->
getLabel());
1766 if (asc.alwaysAdd(*
this, A)) {
1768 appendStmt(Block, A);
1775 AddStmtChoice asc) {
1776 if (asc.alwaysAdd(*
this, U)) {
1778 appendStmt(Block, U);
1781 return Visit(U->
getSubExpr(), AddStmtChoice());
1785 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1786 appendStmt(ConfluenceBlock, B);
1791 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
1792 ConfluenceBlock).first;
1795 std::pair<CFGBlock*, CFGBlock*>
1809 if (B_RHS->isLogicalOp()) {
1810 std::tie(RHSBlock, ExitBlock) =
1811 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
1819 ExitBlock = RHSBlock = createBlock(
false);
1824 TryResult KnownVal = tryEvaluateBool(RHS);
1825 if (!KnownVal.isKnown())
1826 KnownVal = tryEvaluateBool(B);
1829 assert(TrueBlock == FalseBlock);
1830 addSuccessor(RHSBlock, TrueBlock);
1834 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
1835 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
1839 RHSBlock = addStmt(RHS);
1844 return std::make_pair(
nullptr,
nullptr);
1850 if (B_LHS->isLogicalOp()) {
1852 FalseBlock = RHSBlock;
1854 TrueBlock = RHSBlock;
1859 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
1864 CFGBlock *LHSBlock = createBlock(
false);
1868 CFGBlock *EntryLHSBlock = addStmt(LHS);
1871 return std::make_pair(
nullptr,
nullptr);
1874 TryResult KnownVal = tryEvaluateBool(LHS);
1878 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
1879 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
1882 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
1883 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
1886 return std::make_pair(EntryLHSBlock, ExitBlock);
1891 AddStmtChoice asc) {
1894 return VisitLogicalOperator(B);
1898 appendStmt(Block, B);
1900 return addStmt(B->
getLHS());
1904 if (asc.alwaysAdd(*
this, B)) {
1906 appendStmt(Block, B);
1909 return Visit(B->
getRHS());
1912 if (asc.alwaysAdd(*
this, B)) {
1914 appendStmt(Block, B);
1922 return (LBlock ? LBlock : RBlock);
1925 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
1926 if (asc.alwaysAdd(*
this, E)) {
1928 appendStmt(Block, E);
1940 Block = createBlock(
false);
1941 Block->setTerminator(B);
1945 if (BreakJumpTarget.block) {
1946 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
1947 addSuccessor(Block, BreakJumpTarget.block);
1966 Proto->isNothrow(Ctx))
1980 if (!boundType.
isNull()) calleeType = boundType;
1986 bool AddEHEdge =
false;
1990 if (BuildOpts.AddEHEdges)
1996 bool OmitArguments =
false;
1999 if (FD->isNoReturn())
2001 if (FD->
hasAttr<NoThrowAttr>())
2003 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
2004 OmitArguments =
true;
2010 if (OmitArguments) {
2011 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2012 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2014 appendStmt(Block, C);
2018 if (!NoReturn && !AddEHEdge) {
2019 return VisitStmt(C, asc.withAlwaysAdd(
true));
2029 Block = createNoReturnBlock();
2031 Block = createBlock();
2033 appendStmt(Block, C);
2037 if (TryTerminatedBlock)
2038 addSuccessor(Block, TryTerminatedBlock);
2040 addSuccessor(Block, &cfg->getExit());
2043 return VisitChildren(C);
2047 AddStmtChoice asc) {
2048 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2049 appendStmt(ConfluenceBlock, C);
2053 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2054 Succ = ConfluenceBlock;
2060 Succ = ConfluenceBlock;
2066 Block = createBlock(
false);
2068 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2069 addSuccessor(Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2070 addSuccessor(Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2071 Block->setTerminator(C);
2077 LocalScope::const_iterator scopeBeginPos = ScopePos;
2078 addLocalScopeForStmt(C);
2083 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2092 if (
CFGBlock *newBlock = addStmt(*I))
2093 LastBlock = newBlock;
2103 AddStmtChoice asc) {
2109 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2110 appendStmt(ConfluenceBlock, C);
2114 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2120 Succ = ConfluenceBlock;
2124 if (trueExpr != opaqueValue) {
2131 LHSBlock = ConfluenceBlock;
2134 Succ = ConfluenceBlock;
2142 if (Cond->isLogicalOp())
2143 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2146 Block = createBlock(
false);
2149 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2150 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2151 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2152 Block->setTerminator(C);
2158 if (condExpr != opaqueValue)
2166 return addStmt(condExpr);
2177 return VisitDeclSubExpr(DS);
2192 void *Mem = cfg->getAllocator().Allocate(
sizeof(
DeclStmt), A);
2194 cfg->addSyntheticDeclStmt(DSNew, DS);
2197 B = VisitDeclSubExpr(DSNew);
2206 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2215 bool HasTemporaries =
false;
2218 CFGBlock *blockAfterStaticInit =
nullptr;
2220 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2229 blockAfterStaticInit = Succ;
2234 Expr *Init = VD->getInit();
2236 HasTemporaries = isa<ExprWithCleanups>(Init);
2238 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2241 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2247 appendStmt(Block, DS);
2255 if (HasTemporaries) {
2260 LastBlock = newBlock;
2263 if (
CFGBlock *newBlock = Visit(Init))
2264 LastBlock = newBlock;
2270 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2271 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2272 LastBlock = newBlock;
2276 if (ScopePos && VD == *ScopePos)
2280 if (blockAfterStaticInit) {
2282 Block = createBlock(
false);
2283 Block->setTerminator(DS);
2284 addSuccessor(Block, blockAfterStaticInit);
2285 addSuccessor(Block, B);
2306 addLocalScopeForStmt(Init);
2311 addLocalScopeForVarDecl(VD);
2313 addAutomaticObjHandling(ScopePos, save_scope_pos.get(),
I);
2335 if (!isa<CompoundStmt>(Else))
2336 addLocalScopeAndDtors(Else);
2338 ElseBlock = addStmt(Else);
2341 ElseBlock = sv.get();
2358 if (!isa<CompoundStmt>(Then))
2359 addLocalScopeAndDtors(Then);
2361 ThenBlock = addStmt(Then);
2367 ThenBlock = createBlock(
false);
2368 addSuccessor(ThenBlock, sv.get());
2388 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2391 Block = createBlock(
false);
2394 Block->setTerminator(I);
2397 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2401 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2402 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2407 LastBlock = addStmt(I->
getCond());
2413 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2420 LastBlock = addStmt(Init);
2436 Block = createBlock(
false);
2438 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), R);
2442 if (!Block->hasNoReturnElement())
2443 addSuccessor(Block, &cfg->getExit());
2447 return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2456 LabelBlock = createBlock();
2458 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
2459 "label already in map");
2460 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
2466 LabelBlock->setLabel(L);
2480 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2482 if (
Expr *CopyExpr = CI.getCopyExpr()) {
2492 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2495 if (
Expr *Init = *it) {
2508 Block = createBlock(
false);
2509 Block->setTerminator(G);
2512 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
2514 if (I == LabelMap.end())
2516 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
2518 JumpTarget JT = I->second;
2519 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
2520 addSuccessor(Block, JT.block);
2537 addLocalScopeForStmt(Init);
2538 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2541 addLocalScopeForVarDecl(VD);
2542 LocalScope::const_iterator ContinueScopePos = ScopePos;
2544 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
2551 LoopSuccessor = Block;
2553 LoopSuccessor = Succ;
2558 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2560 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2573 Block = Succ = TransitionBlock = createBlock(
false);
2574 TransitionBlock->setLoopTarget(F);
2584 assert(Block == Succ);
2592 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
2593 ContinueJumpTarget.block->setLoopTarget(F);
2596 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
2600 if (!isa<CompoundStmt>(F->
getBody()))
2601 addLocalScopeAndDtors(F->
getBody());
2605 BodyBlock = addStmt(F->
getBody());
2610 BodyBlock = ContinueJumpTarget.block;
2619 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2627 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
2629 std::tie(EntryConditionBlock, ExitConditionBlock) =
2630 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
2635 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
2636 ExitConditionBlock->setTerminator(F);
2639 TryResult KnownVal(
true);
2645 Block = ExitConditionBlock;
2646 EntryConditionBlock = addStmt(C);
2651 if (
Expr *Init = VD->getInit()) {
2654 EntryConditionBlock = addStmt(Init);
2655 assert(Block == EntryConditionBlock);
2659 if (Block && badCFG)
2662 KnownVal = tryEvaluateBool(C);
2666 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2669 addSuccessor(ExitConditionBlock,
2670 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2675 addSuccessor(TransitionBlock, EntryConditionBlock);
2678 Succ = EntryConditionBlock;
2683 Block = createBlock();
2690 Succ = EntryConditionBlock;
2691 return EntryConditionBlock;
2695 if (asc.alwaysAdd(*
this, M)) {
2697 appendStmt(Block, M);
2740 LoopSuccessor = Block;
2743 LoopSuccessor = Succ;
2746 CFGBlock *ExitConditionBlock = createBlock(
false);
2754 appendStmt(ExitConditionBlock, S);
2755 Block = ExitConditionBlock;
2761 AddStmtChoice::NotAlwaysAdd);
2770 Succ = EntryConditionBlock;
2777 save_break(BreakJumpTarget);
2783 Succ = LoopBackBlock = createBlock();
2786 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2787 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
2792 BodyBlock = ContinueJumpTarget.block;
2799 addSuccessor(ExitConditionBlock, BodyBlock);
2804 addSuccessor(ExitConditionBlock, LoopSuccessor);
2807 Block = createBlock();
2835 appendStmt(Block, S);
2850 appendStmt(Block, E);
2862 Semantic = OVE->getSourceExpr();
2880 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2882 addLocalScopeForVarDecl(VD);
2883 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
2891 LoopSuccessor = Block;
2894 LoopSuccessor = Succ;
2897 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2906 save_break(BreakJumpTarget);
2910 Succ = TransitionBlock = createBlock(
false);
2911 TransitionBlock->setLoopTarget(W);
2912 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
2915 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2918 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
2922 if (!isa<CompoundStmt>(W->
getBody()))
2923 addLocalScopeAndDtors(W->
getBody());
2926 BodyBlock = addStmt(W->
getBody());
2929 BodyBlock = ContinueJumpTarget.block;
2930 else if (Block && badCFG)
2937 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2946 std::tie(EntryConditionBlock, ExitConditionBlock) =
2947 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
2952 ExitConditionBlock = createBlock(
false);
2958 Block = ExitConditionBlock;
2959 Block = EntryConditionBlock = addStmt(C);
2964 if (
Expr *Init = VD->getInit()) {
2967 EntryConditionBlock = addStmt(Init);
2968 assert(Block == EntryConditionBlock);
2972 if (Block && badCFG)
2976 const TryResult& KnownVal = tryEvaluateBool(C);
2979 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2982 addSuccessor(ExitConditionBlock,
2983 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2988 addSuccessor(TransitionBlock, EntryConditionBlock);
2995 Succ = EntryConditionBlock;
2996 return EntryConditionBlock;
3015 Block = createBlock(
false);
3018 addSuccessor(Block, &cfg->getExit());
3022 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
3031 Block = createBlock(
false);
3033 if (TryTerminatedBlock)
3035 addSuccessor(Block, TryTerminatedBlock);
3038 addSuccessor(Block, &cfg->getExit());
3042 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
3053 LoopSuccessor = Block;
3055 LoopSuccessor = Succ;
3060 CFGBlock *ExitConditionBlock = createBlock(
false);
3061 CFGBlock *EntryConditionBlock = ExitConditionBlock;
3069 Block = ExitConditionBlock;
3070 EntryConditionBlock = addStmt(C);
3078 Succ = EntryConditionBlock;
3081 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
3091 save_break(BreakJumpTarget);
3094 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
3097 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3104 if (!isa<CompoundStmt>(D->
getBody()))
3105 addLocalScopeAndDtors(D->
getBody());
3108 BodyBlock = addStmt(D->
getBody());
3111 BodyBlock = EntryConditionBlock;
3124 CFGBlock *LoopBackBlock = createBlock();
3127 if (!KnownVal.isFalse())
3129 addSuccessor(ExitConditionBlock, LoopBackBlock);
3131 addSuccessor(ExitConditionBlock,
nullptr);
3136 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3154 Block = createBlock(
false);
3155 Block->setTerminator(C);
3159 if (ContinueJumpTarget.block) {
3160 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
3161 addSuccessor(Block, ContinueJumpTarget.block);
3169 AddStmtChoice asc) {
3171 if (asc.alwaysAdd(*
this, E)) {
3173 appendStmt(Block, E);
3181 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3182 lastBlock = addStmt(VA->getSizeExpr());
3190 if (asc.alwaysAdd(*
this, SE)) {
3192 appendStmt(Block, SE);
3200 CFGBlock *SwitchSuccessor =
nullptr;
3208 addLocalScopeForStmt(Init);
3213 addLocalScopeForVarDecl(VD);
3215 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
3220 SwitchSuccessor = Block;
3221 }
else SwitchSuccessor = Succ;
3225 save_default(DefaultCaseBlock);
3231 DefaultCaseBlock = SwitchSuccessor;
3234 SwitchTerminatedBlock = createBlock(
false);
3238 Succ = SwitchSuccessor;
3239 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3244 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3253 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3255 bool b = tryEvaluate(Terminator->
getCond(), result);
3257 b ? &result :
nullptr);
3261 if (!isa<CompoundStmt>(Terminator->
getBody()))
3262 addLocalScopeAndDtors(Terminator->
getBody());
3264 addStmt(Terminator->
getBody());
3276 bool SwitchAlwaysHasSuccessor =
false;
3277 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3280 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3281 !SwitchAlwaysHasSuccessor);
3284 SwitchTerminatedBlock->setTerminator(Terminator);
3285 Block = SwitchTerminatedBlock;
3291 if (
Expr *Init = VD->getInit()) {
3294 LastBlock = addStmt(Init);
3301 LastBlock = addStmt(Init);
3307 static bool shouldAddCase(
bool &switchExclusivelyCovered,
3314 bool addCase =
false;
3316 if (!switchExclusivelyCovered) {
3320 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3322 if (condInt == lhsInt) {
3324 switchExclusivelyCovered =
true;
3326 else if (condInt > lhsInt) {
3330 if (V2 >= condInt) {
3332 switchExclusivelyCovered =
true;
3346 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3352 while (isa<CaseStmt>(Sub)) {
3353 CFGBlock *currentBlock = createBlock(
false);
3357 addSuccessor(LastBlock, currentBlock);
3359 TopBlock = currentBlock;
3361 addSuccessor(SwitchTerminatedBlock,
3362 shouldAddCase(switchExclusivelyCovered, switchCond,
3364 ? currentBlock :
nullptr);
3366 LastBlock = currentBlock;
3367 CS = cast<CaseStmt>(Sub);
3376 CaseBlock = createBlock();
3387 assert(SwitchTerminatedBlock);
3388 addSuccessor(SwitchTerminatedBlock, CaseBlock,
3389 shouldAddCase(switchExclusivelyCovered, switchCond,
3396 addSuccessor(LastBlock, CaseBlock);
3410 DefaultCaseBlock = Block;
3412 if (!DefaultCaseBlock)
3413 DefaultCaseBlock = createBlock();
3417 DefaultCaseBlock->setLabel(Terminator);
3432 Succ = DefaultCaseBlock;
3434 return DefaultCaseBlock;
3445 TrySuccessor = Block;
3446 }
else TrySuccessor = Succ;
3448 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
3451 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3455 bool HasCatchAll =
false;
3458 Succ = TrySuccessor;
3464 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
3469 addSuccessor(NewTryTerminatedBlock, CatchBlock);
3472 if (PrevTryTerminatedBlock)
3473 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
3475 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3479 Succ = TrySuccessor;
3483 cfg->addTryDispatchBlock(TryTerminatedBlock);
3485 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
3501 LocalScope::const_iterator BeginScopePos = ScopePos;
3502 addLocalScopeForVarDecl(VD);
3503 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
3511 CatchBlock = createBlock();
3517 appendStmt(CatchBlock, CS);
3552 addLocalScopeForStmt(Range);
3554 addLocalScopeForStmt(
Begin);
3556 addLocalScopeForStmt(
End);
3557 addAutomaticObjHandling(ScopePos, save_scope_pos.get(),
S);
3559 LocalScope::const_iterator ContinueScopePos = ScopePos;
3567 LoopSuccessor = Block;
3569 LoopSuccessor = Succ;
3574 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3577 CFGBlock *ConditionBlock = createBlock(
false);
3582 Block = ConditionBlock;
3583 CFGBlock *BeginConditionBlock = addStmt(C);
3586 assert(BeginConditionBlock == ConditionBlock &&
3587 "condition block in for-range was unexpectedly complex");
3588 (void)BeginConditionBlock;
3593 Succ = ConditionBlock;
3596 TryResult KnownVal(
true);
3599 KnownVal = tryEvaluateBool(S->
getCond());
3612 Succ = addStmt(S->
getInc());
3615 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3619 ContinueJumpTarget.block->setLoopTarget(S);
3639 addSuccessor(ConditionBlock,
3640 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
3645 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3648 Block = createBlock();
3655 AddStmtChoice asc) {
3656 if (BuildOpts.AddTemporaryDtors) {
3664 asc = asc.withAlwaysAdd(
true);
3670 AddStmtChoice asc) {
3671 if (asc.alwaysAdd(*
this, E)) {
3673 appendStmt(Block, E);
3676 asc = asc.withAlwaysAdd(
false);
3682 AddStmtChoice asc) {
3684 appendStmt(Block, C);
3686 return VisitChildren(C);
3690 AddStmtChoice asc) {
3693 appendStmt(Block, NE);
3697 if (BuildOpts.AddCXXNewAllocator)
3698 appendNewAllocator(Block, NE);
3708 AddStmtChoice asc) {
3710 appendStmt(Block, DE);
3714 CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
3717 appendDeleteDtor(Block, RD, DE);
3721 return VisitChildren(DE);
3725 AddStmtChoice asc) {
3726 if (asc.alwaysAdd(*
this, E)) {
3728 appendStmt(Block, E);
3730 asc = asc.withAlwaysAdd(
false);
3736 AddStmtChoice asc) {
3738 appendStmt(Block, C);
3739 return VisitChildren(C);
3743 AddStmtChoice asc) {
3744 if (asc.alwaysAdd(*
this, E)) {
3746 appendStmt(Block, E);
3748 return Visit(E->
getSubExpr(), AddStmtChoice());
3753 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
3756 IBlock = createBlock(
false);
3757 cfg->setIndirectGotoBlock(IBlock);
3765 Block = createBlock(
false);
3766 Block->setTerminator(I);
3767 addSuccessor(Block, IBlock);
3771 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
3772 TempDtorContext &Context) {
3773 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
3782 return VisitChildrenForTemporaryDtors(E, Context);
3784 case Stmt::BinaryOperatorClass:
3785 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
3788 case Stmt::CXXBindTemporaryExprClass:
3789 return VisitCXXBindTemporaryExprForTemporaryDtors(
3790 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
3792 case Stmt::BinaryConditionalOperatorClass:
3793 case Stmt::ConditionalOperatorClass:
3794 return VisitConditionalOperatorForTemporaryDtors(
3795 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
3797 case Stmt::ImplicitCastExprClass:
3799 E = cast<CastExpr>(
E)->getSubExpr();
3802 case Stmt::CXXFunctionalCastExprClass:
3804 E = cast<CXXFunctionalCastExpr>(
E)->getSubExpr();
3807 case Stmt::ParenExprClass:
3808 E = cast<ParenExpr>(
E)->getSubExpr();
3811 case Stmt::MaterializeTemporaryExprClass: {
3817 E =
const_cast<Expr *
>(
3818 cast<MaterializeTemporaryExpr>(
E)
3819 ->GetTemporaryExpr()
3820 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
3822 for (
const Expr *CommaLHS : CommaLHSs) {
3823 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
3829 case Stmt::BlockExprClass:
3834 case Stmt::LambdaExprClass: {
3837 auto *LE = cast<LambdaExpr>(
E);
3839 for (
Expr *Init : LE->capture_inits()) {
3840 if (
CFGBlock *R = VisitForTemporaryDtors(
3841 Init,
false, Context))
3847 case Stmt::CXXDefaultArgExprClass:
3848 E = cast<CXXDefaultArgExpr>(
E)->getExpr();
3851 case Stmt::CXXDefaultInitExprClass:
3852 E = cast<CXXDefaultInitExpr>(
E)->getExpr();
3857 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
3858 TempDtorContext &Context) {
3859 if (isa<LambdaExpr>(E)) {
3871 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
3877 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
3881 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
3882 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
3883 RHSExecuted.negate();
3888 TempDtorContext RHSContext(
3889 bothKnownTrue(Context.KnownExecuted, RHSExecuted));
3890 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
3891 InsertTempDtorDecisionBlock(RHSContext);
3901 return LHSBlock ? LHSBlock : RHSBlock;
3909 return RHSBlock ? RHSBlock : LHSBlock;
3912 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
3916 if (!BindToTemporary) {
3928 Block = createNoReturnBlock();
3929 }
else if (Context.needsTempDtorBranch()) {
3933 Block = createBlock();
3937 if (Context.needsTempDtorBranch()) {
3938 Context.setDecisionPoint(Succ, E);
3940 appendTemporaryDtor(Block, E);
3947 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
3949 if (!Context.TerminatorExpr) {
3953 assert(Context.TerminatorExpr);
3954 CFGBlock *Decision = createBlock(
false);
3956 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
3957 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
3958 !Context.KnownExecuted.isTrue());
3962 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
3964 TempDtorContext &Context) {
3968 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
3969 TryResult NegatedVal = ConditionVal;
3970 if (NegatedVal.isKnown()) NegatedVal.negate();
3972 TempDtorContext TrueContext(
3973 bothKnownTrue(Context.KnownExecuted, ConditionVal));
3974 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
3977 Block = ConditionBlock;
3978 Succ = ConditionSucc;
3979 TempDtorContext FalseContext(
3980 bothKnownTrue(Context.KnownExecuted, NegatedVal));
3981 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
3983 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
3984 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
3985 }
else if (TrueContext.TerminatorExpr) {
3987 InsertTempDtorDecisionBlock(TrueContext);
3989 InsertTempDtorDecisionBlock(FalseContext);
4000 bool first_block = begin() == end();
4004 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
4005 Blocks.push_back(Mem, BlkBVC);
4009 Entry = Exit = &back();
4019 return Builder.buildCFG(D, Statement);
4029 llvm_unreachable(
"getDestructorDecl should only be used with "
4032 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
4041 ty = getReferenceInitTemporaryType(astContext, Init);
4046 ty = arrayType->getElementType();
4050 cast<CXXRecordDecl>(recordType->
getDecl());
4054 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
4063 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
4073 llvm_unreachable(
"getKind() returned bogus value");
4087 : ReachableBlock(IsReachable ? B : nullptr),
4088 UnreachableBlock(!IsReachable ? B : nullptr,
4089 B && IsReachable ? AB_Normal : AB_Unreachable) {}
4092 : ReachableBlock(B),
4093 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
4094 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
4102 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
4118 if (S->isAllEnumCasesCovered()) {
4120 if (!L || !isa<CaseStmt>(L))
4136 typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
4137 typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
4140 signed currentBlock;
4146 : currentBlock(0), currStmt(0), LangOpts(LO)
4151 BI != BEnd; ++BI, ++j ) {
4153 const Stmt *stmt= SE->getStmt();
4154 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
4158 case Stmt::DeclStmtClass:
4159 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
4161 case Stmt::IfStmtClass: {
4162 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
4167 case Stmt::ForStmtClass: {
4168 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4173 case Stmt::WhileStmtClass: {
4175 cast<WhileStmt>(
stmt)->getConditionVariable();
4180 case Stmt::SwitchStmtClass: {
4182 cast<SwitchStmt>(
stmt)->getConditionVariable();
4187 case Stmt::CXXCatchStmtClass: {
4189 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
4202 ~StmtPrinterHelper()
override {}
4204 const LangOptions &getLangOpts()
const {
return LangOpts; }
4205 void setBlockID(
signed i) { currentBlock = i; }
4206 void setStmtID(
unsigned i) { currStmt = i; }
4208 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
4209 StmtMapTy::iterator I = StmtMap.find(S);
4211 if (I == StmtMap.end())
4214 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4215 && I->second.second == currStmt) {
4219 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4223 bool handleDecl(
const Decl *D, raw_ostream &OS) {
4224 DeclMapTy::iterator I = DeclMap.find(D);
4226 if (I == DeclMap.end())
4229 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4230 && I->second.second == currStmt) {
4234 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4242 class CFGBlockTerminatorPrint
4243 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4246 StmtPrinterHelper* Helper;
4249 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4251 : OS(os), Helper(helper), Policy(Policy) {
4255 void VisitIfStmt(
IfStmt *I) {
4262 void VisitStmt(
Stmt *Terminator) {
4268 OS <<
"static init " << VD->
getName();
4271 void VisitForStmt(
ForStmt *F) {
4290 void VisitDoStmt(
DoStmt *D) {
4291 OS <<
"do ... while ";
4296 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4308 OS <<
" ? ... : ...";
4312 OS <<
"__builtin_choose_expr( ";
4341 llvm_unreachable(
"Invalid logical operator.");
4345 void VisitExpr(
Expr *E) {
4352 OS <<
"(Temp Dtor) ";
4358 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
4361 const Stmt *S = CS->getStmt();
4362 assert(S !=
nullptr &&
"Expecting non-null Stmt");
4365 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
4369 if (Children.begin() != Children.end()) {
4380 Helper.handledStmt(B->
getRHS(),OS);
4387 if (isa<CXXOperatorCallExpr>(S)) {
4388 OS <<
" (OperatorCall)";
4390 else if (isa<CXXBindTemporaryExpr>(S)) {
4391 OS <<
" (BindTemporary)";
4394 OS <<
" (CXXConstructExpr, " << CCE->getType().getAsString() <<
")";
4396 else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
4397 OS <<
" (" << CE->getStmtClassName() <<
", "
4398 << CE->getCastKindName()
4399 <<
", " << CE->getType().getAsString()
4421 OS <<
" (Base initializer)\n";
4423 OS <<
" (Delegating initializer)\n";
4424 else OS <<
" (Member initializer)\n";
4428 const VarDecl *VD = DE->getVarDecl();
4429 Helper.handleDecl(VD, OS);
4437 OS <<
" (Implicit destructor)\n";
4440 const VarDecl *VD = DE->getVarDecl();
4441 Helper.handleDecl(VD, OS);
4443 OS <<
" (Lifetime ends)\n";
4446 OS <<
"CFGNewAllocator(";
4447 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
4448 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
4456 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
4457 OS <<
"->~" << RD->
getName().str() <<
"()";
4458 OS <<
" (Implicit destructor)\n";
4462 OS <<
" (Base object destructor)\n";
4465 const FieldDecl *FD = ME->getFieldDecl();
4467 OS <<
"this->" << FD->
getName();
4469 OS <<
" (Member object destructor)\n";
4475 OS <<
"() (Temporary object destructor)\n";
4481 StmtPrinterHelper &Helper,
bool print_edges,
4488 OS.changeColor(raw_ostream::YELLOW,
true);
4493 OS <<
" (ENTRY)]\n";
4494 else if (&B == &cfg->
getExit())
4497 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
4499 OS <<
" (NORETURN)]\n";
4512 if (
LabelStmt *L = dyn_cast<LabelStmt>(Label))
4514 else if (
CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
4524 }
else if (isa<DefaultStmt>(Label))
4526 else if (
CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
4536 llvm_unreachable(
"Invalid label statement in CFGBlock.");
4545 I !=
E ; ++
I, ++j ) {
4551 OS << llvm::format(
"%3d", j) <<
": ";
4553 Helper.setStmtID(j);
4561 OS.changeColor(raw_ostream::GREEN);
4565 Helper.setBlockID(-1);
4568 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
4579 const raw_ostream::Colors Color = raw_ostream::BLUE;
4581 OS.changeColor(Color);
4589 OS.changeColor(Color);
4598 bool Reachable =
true;
4601 B = I->getPossiblyUnreachableBlock();
4606 OS <<
"(Unreachable)";
4617 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
4619 OS.changeColor(Color);
4627 OS.changeColor(Color);
4637 bool Reachable =
true;
4640 B = I->getPossiblyUnreachableBlock();
4646 OS <<
"(Unreachable)";
4663 print(llvm::errs(), LO, ShowColors);
4668 StmtPrinterHelper Helper(
this, LO);
4671 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
4676 if (&(**I) == &getEntry() || &(**I) == &getExit())
4679 print_block(OS,
this, **I, Helper,
true, ShowColors);
4683 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
4690 bool ShowColors)
const {
4691 print(llvm::errs(), cfg, LO, ShowColors);
4702 StmtPrinterHelper Helper(cfg, LO);
4703 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
4710 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
4715 Stmt *Terminator = this->Terminator;
4725 case Stmt::CXXForRangeStmtClass:
4726 E = cast<CXXForRangeStmt>(Terminator)->getCond();
4729 case Stmt::ForStmtClass:
4730 E = cast<ForStmt>(Terminator)->getCond();
4733 case Stmt::WhileStmtClass:
4734 E = cast<WhileStmt>(Terminator)->getCond();
4737 case Stmt::DoStmtClass:
4738 E = cast<DoStmt>(Terminator)->getCond();
4741 case Stmt::IfStmtClass:
4742 E = cast<IfStmt>(Terminator)->getCond();
4745 case Stmt::ChooseExprClass:
4746 E = cast<ChooseExpr>(Terminator)->getCond();
4749 case Stmt::IndirectGotoStmtClass:
4750 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
4753 case Stmt::SwitchStmtClass:
4754 E = cast<SwitchStmt>(Terminator)->getCond();
4757 case Stmt::BinaryConditionalOperatorClass:
4758 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
4761 case Stmt::ConditionalOperatorClass:
4762 E = cast<ConditionalOperator>(Terminator)->getCond();
4765 case Stmt::BinaryOperatorClass:
4766 E = cast<BinaryOperator>(Terminator)->getLHS();
4769 case Stmt::ObjCForCollectionStmtClass:
4790 StmtPrinterHelper H(
this, LO);
4792 llvm::ViewGraph(
this,
"CFG");
4806 std::string OutSStr;
4807 llvm::raw_string_ostream Out(OutSStr);
4809 std::string& OutStr = Out.str();
4811 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
4814 for (
unsigned i = 0; i != OutStr.length(); ++i)
4815 if (OutStr[i] ==
'\n') {
4817 OutStr.insert(OutStr.begin()+i+1,
'l');
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0) const
Defines the clang::ASTContext interface.
unsigned getNumInits() const
CFGNewAllocator - Represents C++ allocator call.
StmtClass getStmtClass() const
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.
ArrayRef< Capture > captures() const
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
Stmt - This represents one statement.
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)
bool hasDefinition() const
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)
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...
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
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.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
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()
Iterator for iterating over Stmt * arrays that contain only Expr *.
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
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.
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.
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)
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
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.
Represents the point where the lifetime of an automatic object ends.
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
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()
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S)
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.
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)
static Decl::Kind getKind(const Decl *D)
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.
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
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.
DeclStmt * getBeginStmt()
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const char * getName() const
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
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