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();
59 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
61 AddStmtChoice(
Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
63 bool alwaysAdd(CFGBuilder &builder,
68 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
69 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
103 class const_iterator {
104 const LocalScope*
Scope;
115 :
Scope(nullptr), VarIter(0) {}
119 const_iterator(
const LocalScope&
S,
unsigned I)
120 :
Scope(&S), VarIter(I) {
123 if (VarIter == 0 &&
Scope)
127 VarDecl *
const* operator->()
const {
128 assert (
Scope &&
"Dereferencing invalid iterator is not allowed");
129 assert (VarIter != 0 &&
"Iterator has invalid value of VarIter member");
130 return &
Scope->Vars[VarIter - 1];
133 return *this->operator->();
136 const_iterator &operator++() {
140 assert (VarIter != 0 &&
"Iterator has invalid value of VarIter member");
146 const_iterator operator++(
int) {
147 const_iterator
P = *
this;
152 bool operator==(
const const_iterator &rhs)
const {
153 return Scope == rhs.Scope && VarIter == rhs.VarIter;
155 bool operator!=(
const const_iterator &rhs)
const {
156 return !(*
this == rhs);
159 explicit operator bool()
const {
160 return *
this != const_iterator();
163 int distance(const_iterator L);
166 friend class const_iterator;
172 AutomaticVarsTy Vars;
180 : ctx(ctx), Vars(ctx, 4), Prev(P) {}
183 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
186 Vars.push_back(VD, ctx);
193 int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
195 const_iterator F = *
this;
196 while (F.Scope != L.Scope) {
197 assert (F != const_iterator()
198 &&
"L iterator is not reachable from F iterator.");
202 D += F.VarIter - L.VarIter;
209 struct BlockScopePosPair {
210 BlockScopePosPair() : block(nullptr) {}
211 BlockScopePosPair(
CFGBlock *b, LocalScope::const_iterator scopePos)
212 : block(b), scopePosition(scopePos) {}
215 LocalScope::const_iterator scopePosition;
225 TryResult(
bool b) :
X(b ? 1 : 0) {}
226 TryResult() :
X(-1) {}
228 bool isTrue()
const {
return X == 1; }
229 bool isFalse()
const {
return X == 0; }
230 bool isKnown()
const {
return X >= 0; }
237 TryResult bothKnownTrue(TryResult R1, TryResult R2) {
238 if (!R1.isKnown() || !R2.isKnown())
240 return TryResult(R1.isTrue() && R2.isTrue());
243 class reverse_children {
247 reverse_children(
Stmt *S);
250 iterator begin()
const {
return children.rbegin(); }
251 iterator end()
const {
return children.rend(); }
255 reverse_children::reverse_children(
Stmt *S) {
256 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
260 switch (S->getStmtClass()) {
262 case Stmt::InitListExprClass: {
273 for (
Stmt *SubStmt : S->children())
274 childrenBuf.push_back(SubStmt);
277 children = childrenBuf;
295 typedef BlockScopePosPair JumpTarget;
296 typedef BlockScopePosPair JumpSource;
299 std::unique_ptr<CFG> cfg;
303 JumpTarget ContinueJumpTarget;
304 JumpTarget BreakJumpTarget;
310 LocalScope::const_iterator ScopePos;
313 typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
318 typedef std::vector<JumpSource> BackpatchBlocksTy;
319 BackpatchBlocksTy BackpatchBlocks;
322 typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
323 LabelSetTy AddressTakenLabels;
329 bool switchExclusivelyCovered;
332 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
333 const Stmt *lastLookup;
337 typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy;
338 CachedBoolEvalsTy CachedBoolEvals;
344 Block(nullptr), Succ(nullptr),
345 SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
346 TryTerminatedBlock(nullptr), badCFG(
false), BuildOpts(buildOpts),
347 switchExclusivelyCovered(
false), switchCond(nullptr),
348 cachedEntry(nullptr), lastLookup(nullptr) {}
351 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
393 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
413 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
446 struct TempDtorContext {
448 : IsConditional(
false), KnownExecuted(
true), Succ(nullptr),
449 TerminatorExpr(nullptr) {}
451 TempDtorContext(TryResult KnownExecuted)
452 : IsConditional(
true), KnownExecuted(KnownExecuted), Succ(nullptr),
453 TerminatorExpr(nullptr) {}
461 bool needsTempDtorBranch()
const {
462 return IsConditional && !TerminatorExpr;
472 const bool IsConditional;
473 const TryResult KnownExecuted;
480 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
485 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
487 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
490 void InsertTempDtorDecisionBlock(
const TempDtorContext &
Context,
499 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
500 CFGBlock *createBlock(
bool add_successor =
true);
504 return Visit(S, AddStmtChoice::AlwaysAdd);
507 void addAutomaticObjDtors(LocalScope::const_iterator B,
508 LocalScope::const_iterator E,
Stmt *S);
512 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
514 void addLocalScopeForStmt(
Stmt *S);
515 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
516 LocalScope*
Scope =
nullptr);
517 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
519 void addLocalScopeAndDtors(
Stmt *S);
523 if (alwaysAdd(S) && cachedEntry)
524 cachedEntry->second = B;
527 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
528 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
553 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
554 LocalScope::const_iterator B, LocalScope::const_iterator E);
558 cfg->getBumpVectorContext());
565 cfg->getBumpVectorContext());
571 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
576 const Expr *BoolExpr = RHSExpr;
577 bool IntFirst =
true;
587 llvm::APInt IntValue = IntLiteral->
getValue();
588 if ((IntValue == 1) || (IntValue == 0))
592 !IntValue.isNegative();
598 return TryResult(IntFirst == IntLarger);
602 return TryResult(IntFirst != IntLarger);
610 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
615 const Expr *BoolExpr = RHSExpr;
639 llvm::APInt L1 = IntLiteral->
getValue();
640 llvm::APInt L2 = IntLiteral2->
getValue();
643 if (BuildOpts.Observer)
644 BuildOpts.Observer->compareBitwiseEquality(B,
648 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
649 llvm::APInt IntValue = IntLiteral->
getValue();
650 if ((IntValue == 1) || (IntValue == 0)) {
660 const llvm::APSInt &Value1,
661 const llvm::APSInt &Value2) {
662 assert(Value1.isSigned() == Value2.isSigned());
667 return TryResult(Value1 == Value2);
669 return TryResult(Value1 != Value2);
671 return TryResult(Value1 < Value2);
673 return TryResult(Value1 <= Value2);
675 return TryResult(Value1 > Value2);
677 return TryResult(Value1 >= Value2);
694 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
699 dyn_cast<
DeclRefExpr>(LHS->getLHS()->IgnoreParenImpCasts());
702 if (!Decl1 && !Literal1) {
705 else if (BO1 ==
BO_GE)
707 else if (BO1 ==
BO_LT)
709 else if (BO1 ==
BO_LE)
711 Decl1 = dyn_cast<
DeclRefExpr>(LHS->getRHS()->IgnoreParenImpCasts());
712 Literal1 = dyn_cast<
IntegerLiteral>(LHS->getLHS()->IgnoreParens());
715 if (!Decl1 || !Literal1)
720 dyn_cast<
DeclRefExpr>(RHS->getLHS()->IgnoreParenImpCasts());
723 if (!Decl2 && !Literal2) {
726 else if (BO2 ==
BO_GE)
728 else if (BO2 ==
BO_LT)
730 else if (BO2 ==
BO_LE)
732 Decl2 = dyn_cast<
DeclRefExpr>(RHS->getRHS()->IgnoreParenImpCasts());
733 Literal2 = dyn_cast<
IntegerLiteral>(RHS->getLHS()->IgnoreParens());
736 if (!Decl2 || !Literal2)
745 if (!Literal1->EvaluateAsInt(L1, *
Context) ||
746 !Literal2->EvaluateAsInt(L2, *
Context))
750 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
755 const llvm::APSInt Values[] = {
757 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
761 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
766 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
775 bool AlwaysTrue =
true, AlwaysFalse =
true;
776 for (
unsigned int ValueIndex = 0;
777 ValueIndex <
sizeof(Values) /
sizeof(Values[0]);
779 llvm::APSInt
Value = Values[ValueIndex];
780 TryResult Res1, Res2;
781 Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);
782 Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
784 if (!Res1.isKnown() || !Res2.isKnown())
788 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
789 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
791 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
792 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
796 if (AlwaysTrue || AlwaysFalse) {
797 if (BuildOpts.Observer)
798 BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
799 return TryResult(AlwaysTrue);
806 if (!BuildOpts.PruneTriviallyFalseEdges)
815 TryResult tryEvaluateBool(
Expr *S) {
816 if (!BuildOpts.PruneTriviallyFalseEdges ||
821 if (Bop->isLogicalOp()) {
823 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
824 if (I != CachedBoolEvals.end())
828 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
833 switch (Bop->getOpcode()) {
842 if (Bop->getLHS()->EvaluateAsInt(IntVal, *
Context)) {
843 if (!IntVal.getBoolValue()) {
844 return TryResult(
false);
847 if (Bop->getRHS()->EvaluateAsInt(IntVal, *
Context)) {
848 if (!IntVal.getBoolValue()) {
849 return TryResult(
false);
858 return evaluateAsBooleanConditionNoCache(S);
862 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
864 if (Bop->isLogicalOp()) {
865 TryResult LHS = tryEvaluateBool(Bop->getLHS());
869 if (LHS.isTrue() == (Bop->getOpcode() ==
BO_LOr))
872 TryResult RHS = tryEvaluateBool(Bop->getRHS());
874 if (Bop->getOpcode() ==
BO_LOr)
875 return LHS.isTrue() || RHS.isTrue();
877 return LHS.isTrue() && RHS.isTrue();
880 TryResult RHS = tryEvaluateBool(Bop->getRHS());
884 if (RHS.isTrue() == (Bop->getOpcode() ==
BO_LOr))
887 TryResult BopRes = checkIncorrectLogicOperator(Bop);
888 if (BopRes.isKnown())
889 return BopRes.isTrue();
894 }
else if (Bop->isEqualityOp()) {
895 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
896 if (BopRes.isKnown())
897 return BopRes.isTrue();
898 }
else if (Bop->isRelationalOp()) {
899 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
900 if (BopRes.isKnown())
901 return BopRes.isTrue();
914 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
916 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
919 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
920 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
922 if (!BuildOpts.forcedBlkExprs)
925 if (lastLookup == stmt) {
927 assert(cachedEntry->first == stmt);
940 assert(!cachedEntry);
944 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
945 if (itr == fb->end()) {
946 cachedEntry =
nullptr;
957 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
959 if (vat->getSizeExpr())
962 t = vt->getElementType().getTypePtr();
973 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
981 Succ = createBlock();
982 assert(Succ == &cfg->getExit());
985 if (BuildOpts.AddImplicitDtors)
987 addImplicitDtorsForDestructor(DD);
998 E = CD->init_rend(); I != E; ++I) {
999 B = addInitializer(*I);
1010 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1011 E = BackpatchBlocks.end(); I != E; ++I ) {
1015 LabelMapTy::iterator LI = LabelMap.find(G->
getLabel());
1019 if (LI == LabelMap.end())
continue;
1021 JumpTarget JT = LI->second;
1022 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1024 addSuccessor(B, JT.block);
1028 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1029 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1030 E = AddressTakenLabels.end(); I != E; ++I ) {
1033 LabelMapTy::iterator LI = LabelMap.find(*I);
1037 if (LI == LabelMap.end())
continue;
1039 addSuccessor(B, LI->second.block);
1043 cfg->setEntry(createBlock());
1045 return std::move(cfg);
1050 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1052 if (add_successor && Succ)
1053 addSuccessor(B, Succ);
1060 CFGBlock *CFGBuilder::createNoReturnBlock() {
1063 addSuccessor(B, &cfg->getExit(), Succ);
1069 if (!BuildOpts.AddInitializers)
1072 bool HasTemporaries =
false;
1078 HasTemporaries = isa<ExprWithCleanups>(Init);
1080 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1083 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1089 appendInitializer(Block, I);
1092 if (HasTemporaries) {
1095 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1097 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1103 appendStmt(Block, Default);
1104 if (
Stmt *Child = Default->getExpr())
1126 Init = EWC->getSubExpr();
1132 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1133 Init = MTE->GetTemporaryExpr();
1138 if (
const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
1141 CE->getCastKind() ==
CK_NoOp) &&
1143 Init = CE->getSubExpr();
1149 if (
const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
1150 if (!ME->isArrow() && ME->getBase()->isRValue()) {
1151 Init = ME->getBase();
1165 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1166 LocalScope::const_iterator E,
Stmt *S) {
1167 if (!BuildOpts.AddImplicitDtors)
1178 Decls.reserve(B.distance(E));
1179 for (LocalScope::const_iterator I = B; I != E; ++I)
1180 Decls.push_back(*I);
1190 Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit());
1195 Block = createNoReturnBlock();
1199 appendAutomaticObjDtor(Block, *I, S);
1206 assert (BuildOpts.AddImplicitDtors
1207 &&
"Can be called only when dtors should be added");
1211 for (
const auto &VI : RD->
vbases()) {
1212 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1215 appendBaseDtor(Block, &VI);
1220 for (
const auto &BI : RD->
bases()) {
1221 if (!BI.isVirtual()) {
1222 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1225 appendBaseDtor(Block, &BI);
1231 for (
auto *FI : RD->
fields()) {
1235 if (AT->getSize() == 0)
1237 QT = AT->getElementType();
1243 appendMemberDtor(Block, FI);
1250 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1252 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1253 Scope = alloc.Allocate<LocalScope>();
1255 new (Scope) LocalScope(ctx, ScopePos);
1262 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1263 if (!BuildOpts.AddImplicitDtors)
1266 LocalScope *Scope =
nullptr;
1270 for (
auto *BI : CS->body()) {
1271 Stmt *SI = BI->stripLabelLikeStatements();
1272 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1273 Scope = addLocalScopeForDeclStmt(DS, Scope);
1280 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
1281 addLocalScopeForDeclStmt(DS);
1286 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1287 LocalScope* Scope) {
1288 if (!BuildOpts.AddImplicitDtors)
1291 for (
auto *DI : DS->
decls())
1292 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1293 Scope = addLocalScopeForVarDecl(VD, Scope);
1300 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1301 LocalScope* Scope) {
1302 if (!BuildOpts.AddImplicitDtors)
1311 default:
return Scope;
1328 Init = EWC->getSubExpr();
1329 if (!isa<MaterializeTemporaryExpr>(Init))
1333 QT = getReferenceInitTemporaryType(*Context, Init);
1338 if (AT->getSize() == 0)
1340 QT = AT->getElementType();
1347 Scope = createOrReuseLocalScope(Scope);
1349 ScopePos = Scope->begin();
1356 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1357 if (!BuildOpts.AddImplicitDtors)
1360 LocalScope::const_iterator scopeBeginPos = ScopePos;
1361 addLocalScopeForStmt(S);
1362 addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
1372 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1373 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1377 for (LocalScope::const_iterator I = B; I != E; ++I)
1385 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1391 if (
Expr *E = dyn_cast<Expr>(S))
1392 S = E->IgnoreParens();
1394 switch (S->getStmtClass()) {
1396 return VisitStmt(S, asc);
1398 case Stmt::AddrLabelExprClass:
1399 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
1401 case Stmt::BinaryConditionalOperatorClass:
1402 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
1404 case Stmt::BinaryOperatorClass:
1405 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
1407 case Stmt::BlockExprClass:
1408 return VisitNoRecurse(cast<Expr>(S), asc);
1410 case Stmt::BreakStmtClass:
1411 return VisitBreakStmt(cast<BreakStmt>(S));
1413 case Stmt::CallExprClass:
1414 case Stmt::CXXOperatorCallExprClass:
1415 case Stmt::CXXMemberCallExprClass:
1416 case Stmt::UserDefinedLiteralClass:
1417 return VisitCallExpr(cast<CallExpr>(S), asc);
1419 case Stmt::CaseStmtClass:
1420 return VisitCaseStmt(cast<CaseStmt>(S));
1422 case Stmt::ChooseExprClass:
1423 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
1425 case Stmt::CompoundStmtClass:
1426 return VisitCompoundStmt(cast<CompoundStmt>(S));
1428 case Stmt::ConditionalOperatorClass:
1429 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
1431 case Stmt::ContinueStmtClass:
1432 return VisitContinueStmt(cast<ContinueStmt>(S));
1434 case Stmt::CXXCatchStmtClass:
1435 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
1437 case Stmt::ExprWithCleanupsClass:
1438 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
1440 case Stmt::CXXDefaultArgExprClass:
1441 case Stmt::CXXDefaultInitExprClass:
1451 return VisitStmt(S, asc);
1453 case Stmt::CXXBindTemporaryExprClass:
1454 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
1456 case Stmt::CXXConstructExprClass:
1457 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
1459 case Stmt::CXXNewExprClass:
1460 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
1462 case Stmt::CXXDeleteExprClass:
1463 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
1465 case Stmt::CXXFunctionalCastExprClass:
1466 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
1468 case Stmt::CXXTemporaryObjectExprClass:
1469 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
1471 case Stmt::CXXThrowExprClass:
1472 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
1474 case Stmt::CXXTryStmtClass:
1475 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
1477 case Stmt::CXXForRangeStmtClass:
1478 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
1480 case Stmt::DeclStmtClass:
1481 return VisitDeclStmt(cast<DeclStmt>(S));
1483 case Stmt::DefaultStmtClass:
1484 return VisitDefaultStmt(cast<DefaultStmt>(S));
1486 case Stmt::DoStmtClass:
1487 return VisitDoStmt(cast<DoStmt>(S));
1489 case Stmt::ForStmtClass:
1490 return VisitForStmt(cast<ForStmt>(S));
1492 case Stmt::GotoStmtClass:
1493 return VisitGotoStmt(cast<GotoStmt>(S));
1495 case Stmt::IfStmtClass:
1496 return VisitIfStmt(cast<IfStmt>(S));
1498 case Stmt::ImplicitCastExprClass:
1499 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
1501 case Stmt::IndirectGotoStmtClass:
1502 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
1504 case Stmt::LabelStmtClass:
1505 return VisitLabelStmt(cast<LabelStmt>(S));
1507 case Stmt::LambdaExprClass:
1508 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
1510 case Stmt::MemberExprClass:
1511 return VisitMemberExpr(cast<MemberExpr>(S), asc);
1513 case Stmt::NullStmtClass:
1516 case Stmt::ObjCAtCatchStmtClass:
1517 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
1519 case Stmt::ObjCAutoreleasePoolStmtClass:
1520 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
1522 case Stmt::ObjCAtSynchronizedStmtClass:
1523 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
1525 case Stmt::ObjCAtThrowStmtClass:
1526 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
1528 case Stmt::ObjCAtTryStmtClass:
1529 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
1531 case Stmt::ObjCForCollectionStmtClass:
1532 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
1534 case Stmt::OpaqueValueExprClass:
1537 case Stmt::PseudoObjectExprClass:
1538 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
1540 case Stmt::ReturnStmtClass:
1541 return VisitReturnStmt(cast<ReturnStmt>(S));
1543 case Stmt::UnaryExprOrTypeTraitExprClass:
1544 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1547 case Stmt::StmtExprClass:
1548 return VisitStmtExpr(cast<StmtExpr>(S), asc);
1550 case Stmt::SwitchStmtClass:
1551 return VisitSwitchStmt(cast<SwitchStmt>(S));
1553 case Stmt::UnaryOperatorClass:
1554 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
1556 case Stmt::WhileStmtClass:
1557 return VisitWhileStmt(cast<WhileStmt>(S));
1561 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
1562 if (asc.alwaysAdd(*
this, S)) {
1564 appendStmt(Block, S);
1567 return VisitChildren(S);
1576 reverse_children RChildren(S);
1577 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
1579 if (
Stmt *Child = *I)
1587 AddStmtChoice asc) {
1588 AddressTakenLabels.insert(A->
getLabel());
1590 if (asc.alwaysAdd(*
this, A)) {
1592 appendStmt(Block, A);
1599 AddStmtChoice asc) {
1600 if (asc.alwaysAdd(*
this, U)) {
1602 appendStmt(Block, U);
1605 return Visit(U->
getSubExpr(), AddStmtChoice());
1609 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1610 appendStmt(ConfluenceBlock, B);
1615 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
1616 ConfluenceBlock).first;
1619 std::pair<CFGBlock*, CFGBlock*>
1633 if (B_RHS->isLogicalOp()) {
1634 std::tie(RHSBlock, ExitBlock) =
1635 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
1643 ExitBlock = RHSBlock = createBlock(
false);
1646 assert(TrueBlock == FalseBlock);
1647 addSuccessor(RHSBlock, TrueBlock);
1651 TryResult KnownVal = tryEvaluateBool(RHS);
1652 if (!KnownVal.isKnown())
1653 KnownVal = tryEvaluateBool(B);
1654 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
1655 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
1659 RHSBlock = addStmt(RHS);
1664 return std::make_pair(
nullptr,
nullptr);
1670 if (B_LHS->isLogicalOp()) {
1672 FalseBlock = RHSBlock;
1674 TrueBlock = RHSBlock;
1679 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
1684 CFGBlock *LHSBlock = createBlock(
false);
1688 CFGBlock *EntryLHSBlock = addStmt(LHS);
1691 return std::make_pair(
nullptr,
nullptr);
1694 TryResult KnownVal = tryEvaluateBool(LHS);
1698 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
1699 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
1702 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
1703 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
1706 return std::make_pair(EntryLHSBlock, ExitBlock);
1711 AddStmtChoice asc) {
1714 return VisitLogicalOperator(B);
1718 appendStmt(Block, B);
1720 return addStmt(B->
getLHS());
1724 if (asc.alwaysAdd(*
this, B)) {
1726 appendStmt(Block, B);
1729 return Visit(B->
getRHS());
1732 if (asc.alwaysAdd(*
this, B)) {
1734 appendStmt(Block, B);
1742 return (LBlock ? LBlock : RBlock);
1745 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
1746 if (asc.alwaysAdd(*
this, E)) {
1748 appendStmt(Block, E);
1760 Block = createBlock(
false);
1761 Block->setTerminator(B);
1765 if (BreakJumpTarget.block) {
1766 addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B);
1767 addSuccessor(Block, BreakJumpTarget.block);
1786 Proto->isNothrow(Ctx))
1800 if (!boundType.
isNull()) calleeType = boundType;
1806 bool AddEHEdge =
false;
1810 if (BuildOpts.AddEHEdges)
1816 bool OmitArguments =
false;
1819 if (FD->isNoReturn())
1821 if (FD->
hasAttr<NoThrowAttr>())
1823 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
1824 OmitArguments =
true;
1830 if (OmitArguments) {
1831 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
1832 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
1834 appendStmt(Block, C);
1838 if (!NoReturn && !AddEHEdge) {
1839 return VisitStmt(C, asc.withAlwaysAdd(
true));
1849 Block = createNoReturnBlock();
1851 Block = createBlock();
1853 appendStmt(Block, C);
1857 if (TryTerminatedBlock)
1858 addSuccessor(Block, TryTerminatedBlock);
1860 addSuccessor(Block, &cfg->getExit());
1863 return VisitChildren(C);
1867 AddStmtChoice asc) {
1868 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1869 appendStmt(ConfluenceBlock, C);
1873 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
1874 Succ = ConfluenceBlock;
1880 Succ = ConfluenceBlock;
1886 Block = createBlock(
false);
1888 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
1889 addSuccessor(Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
1890 addSuccessor(Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
1891 Block->setTerminator(C);
1897 addLocalScopeAndDtors(C);
1904 if (
CFGBlock *newBlock = addStmt(*I))
1905 LastBlock = newBlock;
1915 AddStmtChoice asc) {
1921 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1922 appendStmt(ConfluenceBlock, C);
1926 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
1932 Succ = ConfluenceBlock;
1936 if (trueExpr != opaqueValue) {
1943 LHSBlock = ConfluenceBlock;
1946 Succ = ConfluenceBlock;
1954 if (Cond->isLogicalOp())
1955 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
1958 Block = createBlock(
false);
1961 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
1962 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
1963 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
1964 Block->setTerminator(C);
1970 if (condExpr != opaqueValue)
1978 return addStmt(condExpr);
1989 return VisitDeclSubExpr(DS);
1998 unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
1999 ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
2005 void *Mem = cfg->getAllocator().Allocate(
sizeof(
DeclStmt), A);
2007 cfg->addSyntheticDeclStmt(DSNew, DS);
2010 B = VisitDeclSubExpr(DSNew);
2019 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2028 bool HasTemporaries =
false;
2031 CFGBlock *blockAfterStaticInit =
nullptr;
2033 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2042 blockAfterStaticInit = Succ;
2047 Expr *Init = VD->getInit();
2049 HasTemporaries = isa<ExprWithCleanups>(Init);
2051 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2054 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2060 appendStmt(Block, DS);
2068 if (HasTemporaries) {
2073 LastBlock = newBlock;
2076 if (
CFGBlock *newBlock = Visit(Init))
2077 LastBlock = newBlock;
2083 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2084 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2085 LastBlock = newBlock;
2089 if (ScopePos && VD == *ScopePos)
2093 if (blockAfterStaticInit) {
2095 Block = createBlock(
false);
2096 Block->setTerminator(DS);
2097 addSuccessor(Block, blockAfterStaticInit);
2098 addSuccessor(Block, B);
2120 LocalScope::const_iterator BeginScopePos = ScopePos;
2121 addLocalScopeForVarDecl(VD);
2122 addAutomaticObjDtors(ScopePos, BeginScopePos, I);
2145 if (!isa<CompoundStmt>(Else))
2146 addLocalScopeAndDtors(Else);
2148 ElseBlock = addStmt(Else);
2151 ElseBlock = sv.get();
2168 if (!isa<CompoundStmt>(Then))
2169 addLocalScopeAndDtors(Then);
2171 ThenBlock = addStmt(Then);
2177 ThenBlock = createBlock(
false);
2178 addSuccessor(ThenBlock, sv.get());
2195 if (Cond->isLogicalOp())
2196 return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2199 Block = createBlock(
false);
2202 Block->setTerminator(I);
2205 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2209 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2210 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2221 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2237 Block = createBlock(
false);
2239 addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
2243 if (!Block->hasNoReturnElement())
2244 addSuccessor(Block, &cfg->getExit());
2248 return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2257 LabelBlock = createBlock();
2259 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
2260 "label already in map");
2261 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
2267 LabelBlock->setLabel(L);
2281 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2284 if (
Expr *Init = *it) {
2297 Block = createBlock(
false);
2298 Block->setTerminator(G);
2301 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
2303 if (I == LabelMap.end())
2305 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
2307 JumpTarget JT = I->second;
2308 addAutomaticObjDtors(ScopePos, JT.scopePosition, G);
2309 addSuccessor(Block, JT.block);
2326 addLocalScopeForStmt(Init);
2327 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2330 addLocalScopeForVarDecl(VD);
2331 LocalScope::const_iterator ContinueScopePos = ScopePos;
2333 addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F);
2340 LoopSuccessor = Block;
2342 LoopSuccessor = Succ;
2347 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2349 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2362 Block = Succ = TransitionBlock = createBlock(
false);
2363 TransitionBlock->setLoopTarget(F);
2373 assert(Block == Succ);
2381 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
2382 ContinueJumpTarget.block->setLoopTarget(F);
2385 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
2389 if (!isa<CompoundStmt>(F->
getBody()))
2390 addLocalScopeAndDtors(F->
getBody());
2394 BodyBlock = addStmt(F->
getBody());
2399 BodyBlock = ContinueJumpTarget.block;
2408 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2416 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
2417 if (Cond->isLogicalOp()) {
2418 std::tie(EntryConditionBlock, ExitConditionBlock) =
2419 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
2424 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
2425 ExitConditionBlock->setTerminator(F);
2428 TryResult KnownVal(
true);
2434 Block = ExitConditionBlock;
2435 EntryConditionBlock = addStmt(C);
2440 if (
Expr *Init = VD->getInit()) {
2443 EntryConditionBlock = addStmt(Init);
2444 assert(Block == EntryConditionBlock);
2448 if (Block && badCFG)
2451 KnownVal = tryEvaluateBool(C);
2455 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2458 addSuccessor(ExitConditionBlock,
2459 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2464 addSuccessor(TransitionBlock, EntryConditionBlock);
2467 Succ = EntryConditionBlock;
2472 Block = createBlock();
2479 Succ = EntryConditionBlock;
2480 return EntryConditionBlock;
2484 if (asc.alwaysAdd(*
this, M)) {
2486 appendStmt(Block, M);
2529 LoopSuccessor = Block;
2532 LoopSuccessor = Succ;
2535 CFGBlock *ExitConditionBlock = createBlock(
false);
2543 appendStmt(ExitConditionBlock, S);
2544 Block = ExitConditionBlock;
2550 AddStmtChoice::NotAlwaysAdd);
2559 Succ = EntryConditionBlock;
2566 save_break(BreakJumpTarget);
2572 Succ = LoopBackBlock = createBlock();
2575 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2576 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
2581 BodyBlock = ContinueJumpTarget.block;
2588 addSuccessor(ExitConditionBlock, BodyBlock);
2593 addSuccessor(ExitConditionBlock, LoopSuccessor);
2596 Block = createBlock();
2624 appendStmt(Block, S);
2639 appendStmt(Block, E);
2651 Semantic = OVE->getSourceExpr();
2669 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2671 addLocalScopeForVarDecl(VD);
2672 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2680 LoopSuccessor = Block;
2683 LoopSuccessor = Succ;
2686 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2695 save_break(BreakJumpTarget);
2699 Succ = TransitionBlock = createBlock(
false);
2700 TransitionBlock->setLoopTarget(W);
2701 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
2704 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2707 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2711 if (!isa<CompoundStmt>(W->
getBody()))
2712 addLocalScopeAndDtors(W->
getBody());
2715 BodyBlock = addStmt(W->
getBody());
2718 BodyBlock = ContinueJumpTarget.block;
2719 else if (Block && badCFG)
2726 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2734 if (Cond->isLogicalOp()) {
2735 std::tie(EntryConditionBlock, ExitConditionBlock) =
2736 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
2741 ExitConditionBlock = createBlock(
false);
2747 Block = ExitConditionBlock;
2748 Block = EntryConditionBlock = addStmt(C);
2753 if (
Expr *Init = VD->getInit()) {
2756 EntryConditionBlock = addStmt(Init);
2757 assert(Block == EntryConditionBlock);
2761 if (Block && badCFG)
2765 const TryResult& KnownVal = tryEvaluateBool(C);
2768 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2771 addSuccessor(ExitConditionBlock,
2772 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2777 addSuccessor(TransitionBlock, EntryConditionBlock);
2784 Succ = EntryConditionBlock;
2785 return EntryConditionBlock;
2804 Block = createBlock(
false);
2807 addSuccessor(Block, &cfg->getExit());
2811 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
2820 Block = createBlock(
false);
2822 if (TryTerminatedBlock)
2824 addSuccessor(Block, TryTerminatedBlock);
2827 addSuccessor(Block, &cfg->getExit());
2831 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
2842 LoopSuccessor = Block;
2844 LoopSuccessor = Succ;
2849 CFGBlock *ExitConditionBlock = createBlock(
false);
2850 CFGBlock *EntryConditionBlock = ExitConditionBlock;
2858 Block = ExitConditionBlock;
2859 EntryConditionBlock = addStmt(C);
2867 Succ = EntryConditionBlock;
2870 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
2880 save_break(BreakJumpTarget);
2883 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
2886 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2893 if (!isa<CompoundStmt>(D->
getBody()))
2894 addLocalScopeAndDtors(D->
getBody());
2897 BodyBlock = addStmt(D->
getBody());
2900 BodyBlock = EntryConditionBlock;
2906 if (!KnownVal.isFalse()) {
2914 CFGBlock *LoopBackBlock = createBlock();
2918 addSuccessor(ExitConditionBlock, LoopBackBlock);
2921 addSuccessor(ExitConditionBlock,
nullptr);
2926 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2944 Block = createBlock(
false);
2945 Block->setTerminator(C);
2949 if (ContinueJumpTarget.block) {
2950 addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C);
2951 addSuccessor(Block, ContinueJumpTarget.block);
2959 AddStmtChoice asc) {
2961 if (asc.alwaysAdd(*
this, E)) {
2963 appendStmt(Block, E);
2971 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
2972 lastBlock = addStmt(VA->getSizeExpr());
2980 if (asc.alwaysAdd(*
this, SE)) {
2982 appendStmt(Block, SE);
2990 CFGBlock *SwitchSuccessor =
nullptr;
2999 LocalScope::const_iterator SwitchBeginScopePos = ScopePos;
3000 addLocalScopeForVarDecl(VD);
3001 addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator);
3007 SwitchSuccessor = Block;
3008 }
else SwitchSuccessor = Succ;
3012 save_default(DefaultCaseBlock);
3018 DefaultCaseBlock = SwitchSuccessor;
3021 SwitchTerminatedBlock = createBlock(
false);
3025 Succ = SwitchSuccessor;
3026 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3031 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3040 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3042 bool b = tryEvaluate(Terminator->
getCond(), result);
3044 b ? &result :
nullptr);
3048 if (!isa<CompoundStmt>(Terminator->
getBody()))
3049 addLocalScopeAndDtors(Terminator->
getBody());
3051 addStmt(Terminator->
getBody());
3063 bool SwitchAlwaysHasSuccessor =
false;
3064 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3067 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3068 !SwitchAlwaysHasSuccessor);
3071 SwitchTerminatedBlock->setTerminator(Terminator);
3072 Block = SwitchTerminatedBlock;
3078 if (
Expr *Init = VD->getInit()) {
3081 LastBlock = addStmt(Init);
3088 static bool shouldAddCase(
bool &switchExclusivelyCovered,
3095 bool addCase =
false;
3097 if (!switchExclusivelyCovered) {
3101 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3103 if (condInt == lhsInt) {
3105 switchExclusivelyCovered =
true;
3107 else if (condInt < lhsInt) {
3111 if (V2 <= condInt) {
3113 switchExclusivelyCovered =
true;
3127 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3133 while (isa<CaseStmt>(Sub)) {
3134 CFGBlock *currentBlock = createBlock(
false);
3138 addSuccessor(LastBlock, currentBlock);
3140 TopBlock = currentBlock;
3142 addSuccessor(SwitchTerminatedBlock,
3143 shouldAddCase(switchExclusivelyCovered, switchCond,
3145 ? currentBlock :
nullptr);
3147 LastBlock = currentBlock;
3148 CS = cast<CaseStmt>(Sub);
3157 CaseBlock = createBlock();
3168 assert(SwitchTerminatedBlock);
3169 addSuccessor(SwitchTerminatedBlock, CaseBlock,
3170 shouldAddCase(switchExclusivelyCovered, switchCond,
3177 addSuccessor(LastBlock, CaseBlock);
3191 DefaultCaseBlock = Block;
3193 if (!DefaultCaseBlock)
3194 DefaultCaseBlock = createBlock();
3198 DefaultCaseBlock->setLabel(Terminator);
3213 Succ = DefaultCaseBlock;
3215 return DefaultCaseBlock;
3226 TrySuccessor = Block;
3227 }
else TrySuccessor = Succ;
3229 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
3232 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3236 bool HasCatchAll =
false;
3239 Succ = TrySuccessor;
3245 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
3250 addSuccessor(NewTryTerminatedBlock, CatchBlock);
3253 if (PrevTryTerminatedBlock)
3254 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
3256 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3260 Succ = TrySuccessor;
3264 cfg->addTryDispatchBlock(TryTerminatedBlock);
3266 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
3282 LocalScope::const_iterator BeginScopePos = ScopePos;
3283 addLocalScopeForVarDecl(VD);
3284 addAutomaticObjDtors(ScopePos, BeginScopePos, CS);
3292 CatchBlock = createBlock();
3298 appendStmt(CatchBlock, CS);
3333 addLocalScopeForStmt(Range);
3335 addLocalScopeForStmt(BeginEnd);
3336 addAutomaticObjDtors(ScopePos, save_scope_pos.get(),
S);
3338 LocalScope::const_iterator ContinueScopePos = ScopePos;
3346 LoopSuccessor = Block;
3348 LoopSuccessor = Succ;
3353 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3356 CFGBlock *ConditionBlock = createBlock(
false);
3361 Block = ConditionBlock;
3362 CFGBlock *BeginConditionBlock = addStmt(C);
3365 assert(BeginConditionBlock == ConditionBlock &&
3366 "condition block in for-range was unexpectedly complex");
3367 (void)BeginConditionBlock;
3372 Succ = ConditionBlock;
3375 TryResult KnownVal(
true);
3378 KnownVal = tryEvaluateBool(S->
getCond());
3391 Succ = addStmt(S->
getInc());
3392 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3396 ContinueJumpTarget.block->setLoopTarget(S);
3416 addSuccessor(ConditionBlock,
3417 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
3422 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3425 Block = createBlock();
3431 AddStmtChoice asc) {
3432 if (BuildOpts.AddTemporaryDtors) {
3440 asc = asc.withAlwaysAdd(
true);
3446 AddStmtChoice asc) {
3447 if (asc.alwaysAdd(*
this, E)) {
3449 appendStmt(Block, E);
3452 asc = asc.withAlwaysAdd(
false);
3458 AddStmtChoice asc) {
3460 appendStmt(Block, C);
3462 return VisitChildren(C);
3466 AddStmtChoice asc) {
3469 appendStmt(Block, NE);
3473 if (BuildOpts.AddCXXNewAllocator)
3474 appendNewAllocator(Block, NE);
3484 AddStmtChoice asc) {
3486 appendStmt(Block, DE);
3489 CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
3492 appendDeleteDtor(Block, RD, DE);
3495 return VisitChildren(DE);
3499 AddStmtChoice asc) {
3500 if (asc.alwaysAdd(*
this, E)) {
3502 appendStmt(Block, E);
3504 asc = asc.withAlwaysAdd(
false);
3510 AddStmtChoice asc) {
3512 appendStmt(Block, C);
3513 return VisitChildren(C);
3517 AddStmtChoice asc) {
3518 if (asc.alwaysAdd(*
this, E)) {
3520 appendStmt(Block, E);
3522 return Visit(E->
getSubExpr(), AddStmtChoice());
3527 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
3530 IBlock = createBlock(
false);
3531 cfg->setIndirectGotoBlock(IBlock);
3539 Block = createBlock(
false);
3540 Block->setTerminator(I);
3541 addSuccessor(Block, IBlock);
3545 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
3546 TempDtorContext &Context) {
3547 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
3554 switch (E->getStmtClass()) {
3556 return VisitChildrenForTemporaryDtors(E, Context);
3558 case Stmt::BinaryOperatorClass:
3559 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
3562 case Stmt::CXXBindTemporaryExprClass:
3563 return VisitCXXBindTemporaryExprForTemporaryDtors(
3564 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
3566 case Stmt::BinaryConditionalOperatorClass:
3567 case Stmt::ConditionalOperatorClass:
3568 return VisitConditionalOperatorForTemporaryDtors(
3569 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
3571 case Stmt::ImplicitCastExprClass:
3573 E = cast<CastExpr>(E)->getSubExpr();
3576 case Stmt::CXXFunctionalCastExprClass:
3578 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
3581 case Stmt::ParenExprClass:
3582 E = cast<ParenExpr>(E)->getSubExpr();
3585 case Stmt::MaterializeTemporaryExprClass: {
3591 E =
const_cast<Expr *
>(
3592 cast<MaterializeTemporaryExpr>(E)
3593 ->GetTemporaryExpr()
3594 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
3596 for (
const Expr *CommaLHS : CommaLHSs) {
3597 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
3603 case Stmt::BlockExprClass:
3608 case Stmt::LambdaExprClass: {
3611 auto *LE = cast<LambdaExpr>(E);
3613 for (
Expr *Init : LE->capture_inits()) {
3614 if (
CFGBlock *R = VisitForTemporaryDtors(
3615 Init,
false, Context))
3621 case Stmt::CXXDefaultArgExprClass:
3622 E = cast<CXXDefaultArgExpr>(E)->getExpr();
3625 case Stmt::CXXDefaultInitExprClass:
3626 E = cast<CXXDefaultInitExpr>(E)->getExpr();
3631 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
3632 TempDtorContext &Context) {
3633 if (isa<LambdaExpr>(E)) {
3643 for (
Stmt *Child : E->children())
3645 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
3651 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
3655 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
3657 RHSExecuted.negate();
3662 TempDtorContext RHSContext(
3663 bothKnownTrue(Context.KnownExecuted, RHSExecuted));
3664 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
3665 InsertTempDtorDecisionBlock(RHSContext);
3675 return LHSBlock ? LHSBlock : RHSBlock;
3683 return RHSBlock ? RHSBlock : LHSBlock;
3686 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
3690 if (!BindToTemporary) {
3702 Block = createNoReturnBlock();
3703 }
else if (Context.needsTempDtorBranch()) {
3707 Block = createBlock();
3711 if (Context.needsTempDtorBranch()) {
3712 Context.setDecisionPoint(Succ, E);
3714 appendTemporaryDtor(Block, E);
3721 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
3723 if (!Context.TerminatorExpr) {
3727 assert(Context.TerminatorExpr);
3728 CFGBlock *Decision = createBlock(
false);
3730 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
3731 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
3732 !Context.KnownExecuted.isTrue());
3736 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
3738 TempDtorContext &Context) {
3742 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
3743 TryResult NegatedVal = ConditionVal;
3744 if (NegatedVal.isKnown()) NegatedVal.negate();
3746 TempDtorContext TrueContext(
3747 bothKnownTrue(Context.KnownExecuted, ConditionVal));
3748 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
3751 Block = ConditionBlock;
3752 Succ = ConditionSucc;
3753 TempDtorContext FalseContext(
3754 bothKnownTrue(Context.KnownExecuted, NegatedVal));
3755 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
3757 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
3758 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
3759 }
else if (TrueContext.TerminatorExpr) {
3761 InsertTempDtorDecisionBlock(TrueContext);
3763 InsertTempDtorDecisionBlock(FalseContext);
3774 bool first_block =
begin() ==
end();
3778 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
3783 Entry = Exit = &
back();
3793 return Builder.buildCFG(D, Statement);
3802 llvm_unreachable(
"getDestructorDecl should only be used with "
3805 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
3809 ty = arrayType->getElementType();
3813 cast<CXXRecordDecl>(recordType->
getDecl());
3817 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
3826 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
3836 llvm_unreachable(
"getKind() returned bogus value");
3850 : ReachableBlock(IsReachable ? B : nullptr),
3851 UnreachableBlock(!IsReachable ? B : nullptr,
3852 B && IsReachable ? AB_Normal : AB_Unreachable) {}
3855 : ReachableBlock(B),
3856 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
3857 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
3865 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
3881 if (S->isAllEnumCasesCovered()) {
3883 if (!L || !isa<CaseStmt>(L))
3899 typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
3900 typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
3903 signed currentBlock;
3909 : currentBlock(0), currStmt(0), LangOpts(LO)
3914 BI != BEnd; ++BI, ++j ) {
3916 const Stmt *stmt= SE->getStmt();
3917 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
3920 switch (stmt->getStmtClass()) {
3921 case Stmt::DeclStmtClass:
3922 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
3924 case Stmt::IfStmtClass: {
3925 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
3930 case Stmt::ForStmtClass: {
3931 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
3936 case Stmt::WhileStmtClass: {
3938 cast<WhileStmt>(
stmt)->getConditionVariable();
3943 case Stmt::SwitchStmtClass: {
3945 cast<SwitchStmt>(
stmt)->getConditionVariable();
3950 case Stmt::CXXCatchStmtClass: {
3952 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
3965 ~StmtPrinterHelper()
override {}
3967 const LangOptions &getLangOpts()
const {
return LangOpts; }
3968 void setBlockID(
signed i) { currentBlock = i; }
3969 void setStmtID(
unsigned i) { currStmt = i; }
3971 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
3972 StmtMapTy::iterator I = StmtMap.find(S);
3974 if (I == StmtMap.end())
3977 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
3978 && I->second.second == currStmt) {
3982 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
3986 bool handleDecl(
const Decl *D, raw_ostream &OS) {
3987 DeclMapTy::iterator I = DeclMap.find(D);
3989 if (I == DeclMap.end())
3992 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
3993 && I->second.second == currStmt) {
3997 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4005 class CFGBlockTerminatorPrint
4006 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4009 StmtPrinterHelper* Helper;
4012 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4014 : OS(os), Helper(helper), Policy(Policy) {
4018 void VisitIfStmt(
IfStmt *I) {
4021 C->printPretty(OS, Helper, Policy);
4025 void VisitStmt(
Stmt *Terminator) {
4026 Terminator->printPretty(OS, Helper, Policy);
4031 OS <<
"static init " << VD->
getName();
4034 void VisitForStmt(
ForStmt *F) {
4040 C->printPretty(OS, Helper, Policy);
4050 C->printPretty(OS, Helper, Policy);
4053 void VisitDoStmt(
DoStmt *D) {
4054 OS <<
"do ... while ";
4056 C->printPretty(OS, Helper, Policy);
4059 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4061 Terminator->
getCond()->printPretty(OS, Helper, Policy);
4070 Cond->printPretty(OS, Helper, Policy);
4071 OS <<
" ? ... : ...";
4075 OS <<
"__builtin_choose_expr( ";
4077 Cond->printPretty(OS, Helper, Policy);
4084 T->printPretty(OS, Helper, Policy);
4094 B->
getLHS()->printPretty(OS, Helper, Policy);
4104 llvm_unreachable(
"Invalid logical operator.");
4108 void VisitExpr(
Expr *E) {
4109 E->printPretty(OS, Helper, Policy);
4115 OS <<
"(Temp Dtor) ";
4121 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
4124 const Stmt *S = CS->getStmt();
4125 assert(S !=
nullptr &&
"Expecting non-null Stmt");
4128 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
4142 Helper.handledStmt(B->
getRHS(),OS);
4147 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4149 if (isa<CXXOperatorCallExpr>(S)) {
4150 OS <<
" (OperatorCall)";
4152 else if (isa<CXXBindTemporaryExpr>(S)) {
4153 OS <<
" (BindTemporary)";
4156 OS <<
" (CXXConstructExpr, " << CCE->getType().getAsString() <<
")";
4158 else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
4159 OS <<
" (" << CE->getStmtClassName() <<
", "
4160 << CE->getCastKindName()
4161 <<
", " << CE->getType().getAsString()
4179 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4183 OS <<
" (Base initializer)\n";
4185 OS <<
" (Delegating initializer)\n";
4186 else OS <<
" (Member initializer)\n";
4190 const VarDecl *VD = DE->getVarDecl();
4191 Helper.handleDecl(VD, OS);
4199 OS <<
" (Implicit destructor)\n";
4202 OS <<
"CFGNewAllocator(";
4203 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
4204 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
4212 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
4213 OS <<
"->~" << RD->
getName().str() <<
"()";
4214 OS <<
" (Implicit destructor)\n";
4218 OS <<
" (Base object destructor)\n";
4221 const FieldDecl *FD = ME->getFieldDecl();
4223 OS <<
"this->" << FD->
getName();
4225 OS <<
" (Member object destructor)\n";
4231 OS <<
"() (Temporary object destructor)\n";
4237 StmtPrinterHelper &Helper,
bool print_edges,
4244 OS.changeColor(raw_ostream::YELLOW,
true);
4249 OS <<
" (ENTRY)]\n";
4250 else if (&B == &cfg->
getExit())
4253 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
4255 OS <<
" (NORETURN)]\n";
4268 if (
LabelStmt *L = dyn_cast<LabelStmt>(Label))
4270 else if (
CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
4273 C->
getLHS()->printPretty(OS, &Helper,
4277 C->
getRHS()->printPretty(OS, &Helper,
4280 }
else if (isa<DefaultStmt>(Label))
4282 else if (
CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
4292 llvm_unreachable(
"Invalid label statement in CFGBlock.");
4301 I != E ; ++I, ++j ) {
4307 OS << llvm::format(
"%3d", j) <<
": ";
4309 Helper.setStmtID(j);
4317 OS.changeColor(raw_ostream::GREEN);
4321 Helper.setBlockID(-1);
4324 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
4335 const raw_ostream::Colors Color = raw_ostream::BLUE;
4337 OS.changeColor(Color);
4345 OS.changeColor(Color);
4354 bool Reachable =
true;
4357 B = I->getPossiblyUnreachableBlock();
4362 OS <<
"(Unreachable)";
4373 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
4375 OS.changeColor(Color);
4383 OS.changeColor(Color);
4393 bool Reachable =
true;
4396 B = I->getPossiblyUnreachableBlock();
4402 OS <<
"(Unreachable)";
4419 print(llvm::errs(), LO, ShowColors);
4424 StmtPrinterHelper Helper(
this, LO);
4427 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
4430 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
4432 if (&(**I) == &getEntry() || &(**I) == &getExit())
4435 print_block(OS,
this, **I, Helper,
true, ShowColors);
4439 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
4446 bool ShowColors)
const {
4447 print(llvm::errs(), cfg, LO, ShowColors);
4458 StmtPrinterHelper Helper(cfg, LO);
4459 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
4466 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
4471 Stmt *Terminator = this->Terminator;
4477 switch (Terminator->getStmtClass()) {
4481 case Stmt::CXXForRangeStmtClass:
4482 E = cast<CXXForRangeStmt>(Terminator)->getCond();
4485 case Stmt::ForStmtClass:
4486 E = cast<ForStmt>(Terminator)->getCond();
4489 case Stmt::WhileStmtClass:
4490 E = cast<WhileStmt>(Terminator)->getCond();
4493 case Stmt::DoStmtClass:
4494 E = cast<DoStmt>(Terminator)->getCond();
4497 case Stmt::IfStmtClass:
4498 E = cast<IfStmt>(Terminator)->getCond();
4501 case Stmt::ChooseExprClass:
4502 E = cast<ChooseExpr>(Terminator)->getCond();
4505 case Stmt::IndirectGotoStmtClass:
4506 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
4509 case Stmt::SwitchStmtClass:
4510 E = cast<SwitchStmt>(Terminator)->getCond();
4513 case Stmt::BinaryConditionalOperatorClass:
4514 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
4517 case Stmt::ConditionalOperatorClass:
4518 E = cast<ConditionalOperator>(Terminator)->getCond();
4521 case Stmt::BinaryOperatorClass:
4522 E = cast<BinaryOperator>(Terminator)->getLHS();
4525 case Stmt::ObjCForCollectionStmtClass:
4546 StmtPrinterHelper H(
this, LO);
4548 llvm::ViewGraph(
this,
"CFG");
4549 GraphHelper =
nullptr;
4562 std::string OutSStr;
4563 llvm::raw_string_ostream Out(OutSStr);
4564 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
4565 std::string& OutStr = Out.str();
4567 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
4570 for (
unsigned i = 0; i != OutStr.length(); ++i)
4571 if (OutStr[i] ==
'\n') {
4573 OutStr.insert(OutStr.begin()+i+1,
'l');
Defines the clang::ASTContext interface.
unsigned getNumInits() const
CFGNewAllocator - Represents C++ allocator call.
static const VariableArrayType * FindVA(QualType Ty)
StringRef getName() 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
CXXCatchStmt * getHandler(unsigned i)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
bool isArgumentType() const
bool isRecordType() const
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()
Represents Objective-C's @throw statement.
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.
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]).
static bool isAssignmentOp(Opcode Opc)
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
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
bool isCompleteDefinition() const
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
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. For the computed linkage of symbol, see getLinkage.
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
Represents Objective-C's @catch statement.
const CompoundStmt * getSynchBody() const
Describes an C or C++ initializer list.
const LangOptions & getLangOpts() const
Expr * getTrueExpr() const
std::reverse_iterator< init_const_iterator > init_const_reverse_iterator
APValue Val
Val - This is the value the expression can be folded to.
const CXXRecordDecl * getParent() const
capture_init_iterator capture_init_end() const
Retrieve the iterator pointing one past the last initialization argument for this lambda expression...
Stmt * getHandlerBlock() const
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
A builtin binary operation expression such as "x + y" or "x <= y".
bool isValueDependent() const
RecordDecl * getDecl() const
bool isUnsignedIntegerType() const
const DeclStmt * getConditionVariableDeclStmt() const
const Type * getBaseClass() const
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
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...
arg_iterator placement_arg_end()
llvm::APInt getValue() const
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const
capture_init_iterator capture_init_begin() const
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
QualType getPointeeType() const
bool isFunctionPointerType() const
LabelDecl * getDecl() const
bool isKnownToHaveBooleanValue() const
QualType getPointeeType() const
Stmt * getTerminatorCondition(bool StripParens=true)
bool isNoReturn(ASTContext &astContext) const
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.
Represents a C++ destructor within a class.
Represents Objective-C's @synchronized statement.
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
unsigned getBlockID() const
const DeclStmt * getConditionVariableDeclStmt() const
const DeclStmt * getConditionVariableDeclStmt() const
The result type of a method or function.
void viewCFG(const LangOptions &LO) const
ElementList::iterator iterator
LabelDecl * getLabel() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
bool hasNoReturnElement() const
CFGTerminator getTerminator()
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
const Type * getTypePtr() const
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
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.
const Expr * getCond() const
bool isTemporaryDtorsBranch() const
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
reverse_body_iterator body_rend()
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
reverse_decl_iterator decl_rbegin()
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "switch" statement, if any.
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. Returns null if this is an ove...
Expr ** getInits()
Retrieve the set of initializers.
bool isTypeDependent() const
bool isAllEnumCasesCovered() const
static bool isLogicalOp(Opcode Opc)
void print(raw_ostream &OS, const CFG *cfg, const LangOptions &LO, bool ShowColors) 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. The opaque value will...
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
EvalResult is a struct with detailed info about an evaluated expression.
Represents a delete expression for memory deallocation and destructor calls, e.g. "delete[] pArray"...
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)
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
const Stmt * getThen() const
QualType getNonReferenceType() const
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
CFGBlock * getIndirectGotoBlock()
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Expr * getFalseExpr() const
DeclStmt * getBeginEndStmt()
const Stmt * getSubStmt() const
Represents Objective-C's collection statement.
Represents a C++ base or member initializer.
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
reverse_decl_iterator decl_rend()
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
Represents a base class of a C++ class.
arg_iterator placement_arg_begin()
DeclStmt * getRangeStmt()
A use of a default initializer in a constructor or in aggregate initialization.
unsigned IgnoreNullPredecessors
void setHasNoReturnElement()
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Represents a C++ struct/union/class.
BoundNodesTreeBuilder *const Builder
reverse_body_iterator body_rbegin()
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr.type.conv]).
bool operator!=(CanQual< T > x, CanQual< U > y)
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.
CompoundStmt * getTryBlock()
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).
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
VarDecl * getExceptionDecl() const
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
std::reverse_iterator< decl_iterator > reverse_decl_iterator
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
Expr * getSemanticExpr(unsigned index)
const Expr * getSubExpr() const
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
SourceLocation getLocation() const
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
const char * getName() const
Represents Objective-C's @autoreleasepool Statement.
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.
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
QualType getArgumentType() const