38 #include "llvm/ADT/APInt.h" 39 #include "llvm/ADT/APSInt.h" 40 #include "llvm/ADT/ArrayRef.h" 41 #include "llvm/ADT/DenseMap.h" 42 #include "llvm/ADT/Optional.h" 43 #include "llvm/ADT/STLExtras.h" 44 #include "llvm/ADT/SetVector.h" 45 #include "llvm/ADT/SmallPtrSet.h" 46 #include "llvm/ADT/SmallVector.h" 47 #include "llvm/Support/Allocator.h" 48 #include "llvm/Support/Casting.h" 49 #include "llvm/Support/Compiler.h" 50 #include "llvm/Support/DOTGraphTraits.h" 51 #include "llvm/Support/ErrorHandling.h" 52 #include "llvm/Support/Format.h" 53 #include "llvm/Support/GraphWriter.h" 54 #include "llvm/Support/SaveAndRestore.h" 55 #include "llvm/Support/raw_ostream.h" 63 using namespace clang;
66 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
67 if (
Expr *Ex = VD->getInit())
68 return Ex->getSourceRange().getEnd();
76 if (isa<IntegerLiteral>(E))
79 return isa<EnumConstantDecl>(DR->getDecl()) ? DR :
nullptr;
88 static std::tuple<const DeclRefExpr *, BinaryOperatorKind, const Expr *>
95 if (Constant ==
nullptr) {
101 else if (Op == BO_LT)
103 else if (Op == BO_LE)
111 return std::make_tuple(D, Op, Constant);
123 if (isa<IntegerLiteral>(E1) != isa<IntegerLiteral>(E2))
127 if (isa<IntegerLiteral>(E1))
132 assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
133 auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
134 auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
136 assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
140 assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
160 class AddStmtChoice {
162 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
164 AddStmtChoice(
Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
166 bool alwaysAdd(CFGBuilder &builder,
171 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
172 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
202 friend class const_iterator;
208 class const_iterator {
209 const LocalScope*
Scope =
nullptr;
213 unsigned VarIter = 0;
219 const_iterator() =
default;
223 const_iterator(
const LocalScope& S,
unsigned I)
224 : Scope(&S), VarIter(I) {
227 if (VarIter == 0 && Scope)
231 VarDecl *
const* operator->()
const {
232 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
233 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
234 return &Scope->Vars[VarIter - 1];
237 return *this->operator->();
240 const_iterator &operator++() {
244 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
250 const_iterator operator++(
int) {
251 const_iterator
P = *
this;
256 bool operator==(
const const_iterator &rhs)
const {
257 return Scope == rhs.Scope && VarIter == rhs.VarIter;
259 bool operator!=(
const const_iterator &rhs)
const {
260 return !(*
this == rhs);
263 explicit operator bool()
const {
264 return *
this != const_iterator();
268 const_iterator shared_parent(const_iterator L);
275 AutomaticVarsTy Vars;
284 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
287 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
290 Vars.push_back(VD, ctx);
301 const_iterator F = *
this;
302 while (F.Scope != L.Scope) {
303 assert(F != const_iterator() &&
304 "L iterator is not reachable from F iterator.");
308 D += F.VarIter - L.VarIter;
316 LocalScope::const_iterator
317 LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
318 llvm::SmallPtrSet<const LocalScope *, 4> ScopesOfL;
320 ScopesOfL.insert(L.Scope);
321 if (L == const_iterator())
326 const_iterator F = *
this;
328 if (ScopesOfL.count(F.Scope))
330 assert(F != const_iterator() &&
331 "L iterator is not reachable from F iterator.");
341 struct BlockScopePosPair {
343 LocalScope::const_iterator scopePosition;
345 BlockScopePosPair() =
default;
346 BlockScopePosPair(
CFGBlock *b, LocalScope::const_iterator scopePos)
347 : block(b), scopePosition(scopePos) {}
358 TryResult() =
default;
359 TryResult(
bool b) :
X(b ? 1 : 0) {}
361 bool isTrue()
const {
return X == 1; }
362 bool isFalse()
const {
return X == 0; }
363 bool isKnown()
const {
return X >= 0; }
374 if (!R1.isKnown() || !R2.isKnown())
376 return TryResult(R1.isTrue() && R2.isTrue());
381 class reverse_children {
386 reverse_children(
Stmt *S);
390 iterator begin()
const {
return children.rbegin(); }
391 iterator end()
const {
return children.rend(); }
396 reverse_children::reverse_children(
Stmt *S) {
397 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
403 case Stmt::InitListExprClass: {
415 childrenBuf.push_back(SubStmt);
437 using JumpTarget = BlockScopePosPair;
438 using JumpSource = BlockScopePosPair;
441 std::unique_ptr<CFG> cfg;
449 JumpTarget ContinueJumpTarget;
450 JumpTarget BreakJumpTarget;
451 JumpTarget SEHLeaveJumpTarget;
452 CFGBlock *SwitchTerminatedBlock =
nullptr;
453 CFGBlock *DefaultCaseBlock =
nullptr;
457 CFGBlock *TryTerminatedBlock =
nullptr;
460 LocalScope::const_iterator ScopePos;
463 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
468 using BackpatchBlocksTy = std::vector<JumpSource>;
469 BackpatchBlocksTy BackpatchBlocks;
473 LabelSetTy AddressTakenLabels;
479 bool switchExclusivelyCovered =
false;
482 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
483 const Stmt *lastLookup =
nullptr;
487 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
488 CachedBoolEvalsTy CachedBoolEvals;
493 : Context(astContext), cfg(
new CFG()),
494 BuildOpts(buildOpts) {}
497 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
540 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
564 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
597 struct TempDtorContext {
598 TempDtorContext() =
default;
599 TempDtorContext(TryResult KnownExecuted)
600 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
608 bool needsTempDtorBranch()
const {
609 return IsConditional && !TerminatorExpr;
619 const bool IsConditional =
false;
620 const TryResult KnownExecuted =
true;
627 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
628 TempDtorContext &Context);
629 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *E, TempDtorContext &Context);
631 TempDtorContext &Context);
632 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
634 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
636 TempDtorContext &Context);
637 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
646 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
647 CFGBlock *createBlock(
bool add_successor =
true);
651 return Visit(S, AddStmtChoice::AlwaysAdd);
655 void addLoopExit(
const Stmt *LoopStmt);
656 void addAutomaticObjDtors(LocalScope::const_iterator B,
657 LocalScope::const_iterator E,
Stmt *S);
658 void addLifetimeEnds(LocalScope::const_iterator B,
659 LocalScope::const_iterator E,
Stmt *S);
660 void addAutomaticObjHandling(LocalScope::const_iterator B,
661 LocalScope::const_iterator E,
Stmt *S);
665 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
667 void addLocalScopeForStmt(
Stmt *S);
668 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
669 LocalScope* Scope =
nullptr);
670 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope* Scope =
nullptr);
672 void addLocalScopeAndDtors(
Stmt *S);
677 if (alwaysAdd(S) && cachedEntry)
678 cachedEntry->second = B;
681 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
682 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
713 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
721 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
722 LocalScope::const_iterator B, LocalScope::const_iterator E);
724 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
725 LocalScope::const_iterator B,
726 LocalScope::const_iterator E);
730 cfg->getBumpVectorContext());
737 cfg->getBumpVectorContext());
743 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
748 const Expr *BoolExpr = RHSExpr;
749 bool IntFirst =
true;
759 llvm::APInt IntValue = IntLiteral->
getValue();
760 if ((IntValue == 1) || (IntValue == 0))
764 !IntValue.isNegative();
767 if (Bok == BO_GT || Bok == BO_GE) {
770 return TryResult(IntFirst == IntLarger);
774 return TryResult(IntFirst != IntLarger);
782 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
787 const Expr *BoolExpr = RHSExpr;
798 if (BitOp && (BitOp->
getOpcode() == BO_And ||
811 llvm::APInt L1 = IntLiteral->
getValue();
812 llvm::APInt L2 = IntLiteral2->
getValue();
813 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
814 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
820 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
821 llvm::APInt IntValue = IntLiteral->
getValue();
822 if ((IntValue == 1) || (IntValue == 0)) {
825 return TryResult(B->
getOpcode() != BO_EQ);
832 const llvm::APSInt &Value1,
833 const llvm::APSInt &Value2) {
834 assert(Value1.isSigned() == Value2.isSigned());
839 return TryResult(Value1 == Value2);
841 return TryResult(Value1 != Value2);
843 return TryResult(Value1 < Value2);
845 return TryResult(Value1 <= Value2);
847 return TryResult(Value1 > Value2);
849 return TryResult(Value1 >= Value2);
866 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
874 if (!Decl1 || !Expr1)
882 if (!Decl2 || !Expr2)
901 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
906 const llvm::APSInt Values[] = {
908 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
912 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
917 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
926 bool AlwaysTrue =
true, AlwaysFalse =
true;
927 for (
const llvm::APSInt &
Value : Values) {
928 TryResult Res1, Res2;
929 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
930 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
932 if (!Res1.isKnown() || !Res2.isKnown())
936 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
937 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
939 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
940 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
944 if (AlwaysTrue || AlwaysFalse) {
947 return TryResult(AlwaysTrue);
963 TryResult tryEvaluateBool(
Expr *S) {
969 if (Bop->isLogicalOp()) {
971 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
972 if (I != CachedBoolEvals.end())
976 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
977 CachedBoolEvals[S] =
Result;
981 switch (Bop->getOpcode()) {
990 if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) {
991 if (!IntVal.getBoolValue()) {
992 return TryResult(
false);
995 if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) {
996 if (!IntVal.getBoolValue()) {
997 return TryResult(
false);
1006 return evaluateAsBooleanConditionNoCache(S);
1010 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1012 if (Bop->isLogicalOp()) {
1013 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1014 if (LHS.isKnown()) {
1017 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1018 return LHS.isTrue();
1020 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1021 if (RHS.isKnown()) {
1022 if (Bop->getOpcode() == BO_LOr)
1023 return LHS.isTrue() || RHS.isTrue();
1025 return LHS.isTrue() && RHS.isTrue();
1028 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1029 if (RHS.isKnown()) {
1032 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1033 return RHS.isTrue();
1035 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1036 if (BopRes.isKnown())
1037 return BopRes.isTrue();
1042 }
else if (Bop->isEqualityOp()) {
1043 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1044 if (BopRes.isKnown())
1045 return BopRes.isTrue();
1046 }
else if (Bop->isRelationalOp()) {
1047 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1048 if (BopRes.isKnown())
1049 return BopRes.isTrue();
1060 bool hasTrivialDestructor(
VarDecl *VD);
1065 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1067 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
1070 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
1071 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1073 if (!BuildOpts.forcedBlkExprs)
1076 if (lastLookup == stmt) {
1078 assert(cachedEntry->first == stmt);
1091 assert(!cachedEntry);
1095 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1096 if (itr == fb->end()) {
1097 cachedEntry =
nullptr;
1101 cachedEntry = &*itr;
1108 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1110 if (vat->getSizeExpr())
1113 t = vt->getElementType().getTypePtr();
1124 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1132 Succ = createBlock();
1133 assert(Succ == &cfg->getExit());
1136 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1137 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1139 if (BuildOpts.AddImplicitDtors)
1141 addImplicitDtorsForDestructor(DD);
1151 for (
auto *I : llvm::reverse(CD->inits())) {
1152 B = addInitializer(I);
1163 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1164 E = BackpatchBlocks.end(); I != E; ++I ) {
1168 LabelMapTy::iterator LI = LabelMap.find(G->
getLabel());
1172 if (LI == LabelMap.end())
continue;
1174 JumpTarget JT = LI->second;
1175 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1177 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1179 addSuccessor(B, JT.block);
1183 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1184 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1185 E = AddressTakenLabels.end(); I != E; ++I ) {
1187 LabelMapTy::iterator LI = LabelMap.find(*I);
1191 if (LI == LabelMap.end())
continue;
1193 addSuccessor(B, LI->second.block);
1197 cfg->setEntry(createBlock());
1199 return std::move(cfg);
1204 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1206 if (add_successor && Succ)
1207 addSuccessor(B, Succ);
1214 CFGBlock *CFGBuilder::createNoReturnBlock() {
1217 addSuccessor(B, &cfg->getExit(), Succ);
1223 if (!BuildOpts.AddInitializers)
1226 bool HasTemporaries =
false;
1232 HasTemporaries = isa<ExprWithCleanups>(Init);
1234 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1236 TempDtorContext Context;
1237 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1243 appendInitializer(Block, I);
1246 if (HasTemporaries) {
1249 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1251 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1274 bool *FoundMTE =
nullptr) {
1281 Init = EWC->getSubExpr();
1287 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1288 Init = MTE->GetTemporaryExpr();
1295 if (
const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
1296 if ((CE->getCastKind() == CK_DerivedToBase ||
1297 CE->getCastKind() == CK_UncheckedDerivedToBase ||
1298 CE->getCastKind() == CK_NoOp) &&
1300 Init = CE->getSubExpr();
1306 if (
const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
1307 if (!ME->isArrow() && ME->getBase()->isRValue()) {
1308 Init = ME->getBase();
1321 void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1322 if(!BuildOpts.AddLoopExit)
1325 appendLoopExit(Block, LoopStmt);
1328 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1329 LocalScope::const_iterator E,
1331 if (BuildOpts.AddImplicitDtors)
1332 addAutomaticObjDtors(B, E, S);
1333 if (BuildOpts.AddLifetime)
1334 addLifetimeEnds(B, E, S);
1338 void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1339 LocalScope::const_iterator E,
Stmt *S) {
1340 if (!BuildOpts.AddLifetime)
1350 LocalScope::const_iterator
P = B.shared_parent(E);
1351 int dist = B.distance(P);
1358 DeclsTrivial.reserve(dist);
1359 DeclsNonTrivial.reserve(dist);
1361 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1362 if (hasTrivialDestructor(*I))
1363 DeclsTrivial.push_back(*I);
1365 DeclsNonTrivial.push_back(*I);
1371 E = DeclsTrivial.rend();
1373 appendLifetimeEnds(Block, *I, S);
1376 I = DeclsNonTrivial.rbegin(),
1377 E = DeclsNonTrivial.rend();
1379 appendLifetimeEnds(Block, *I, S);
1385 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1386 LocalScope::const_iterator E,
Stmt *S) {
1387 if (!BuildOpts.AddImplicitDtors)
1398 Decls.reserve(B.distance(E));
1399 for (LocalScope::const_iterator I = B; I != E; ++I)
1400 Decls.push_back(*I);
1414 if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
1415 Block = createNoReturnBlock();
1419 appendAutomaticObjDtor(Block, *I, S);
1426 assert(BuildOpts.AddImplicitDtors &&
1427 "Can be called only when dtors should be added");
1431 for (
const auto &VI : RD->
vbases()) {
1432 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1435 appendBaseDtor(Block, &VI);
1440 for (
const auto &BI : RD->
bases()) {
1441 if (!BI.isVirtual()) {
1442 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1445 appendBaseDtor(Block, &BI);
1451 for (
auto *FI : RD->
fields()) {
1455 if (AT->getSize() == 0)
1457 QT = AT->getElementType();
1461 if (!CD->hasTrivialDestructor()) {
1463 appendMemberDtor(Block, FI);
1470 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1473 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1474 return new (alloc.Allocate<LocalScope>())
1480 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1481 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
1484 LocalScope *Scope =
nullptr;
1488 for (
auto *BI : CS->body()) {
1490 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1491 Scope = addLocalScopeForDeclStmt(DS, Scope);
1499 addLocalScopeForDeclStmt(DS);
1504 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1505 LocalScope* Scope) {
1506 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
1509 for (
auto *DI : DS->
decls())
1510 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1511 Scope = addLocalScopeForVarDecl(VD, Scope);
1515 bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
1532 bool FoundMTE =
false;
1540 if (AT->getSize() == 0)
1542 QT = AT->getElementType();
1547 return !CD->hasDefinition() || CD->hasTrivialDestructor();
1554 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1555 LocalScope* Scope) {
1556 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1557 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1558 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
1567 default:
return Scope;
1570 if (BuildOpts.AddImplicitDtors) {
1571 if (!hasTrivialDestructor(VD)) {
1573 Scope = createOrReuseLocalScope(Scope);
1575 ScopePos = Scope->begin();
1580 assert(BuildOpts.AddLifetime);
1582 Scope = createOrReuseLocalScope(Scope);
1584 ScopePos = Scope->begin();
1590 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1591 LocalScope::const_iterator scopeBeginPos = ScopePos;
1592 addLocalScopeForStmt(S);
1593 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
1603 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1604 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1605 if (!BuildOpts.AddImplicitDtors)
1610 for (LocalScope::const_iterator I = B; I != E; ++I)
1620 void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
1621 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
1622 if (!BuildOpts.AddLifetime)
1627 for (LocalScope::const_iterator I = B; I != E; ++I)
1634 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1640 if (
Expr *E = dyn_cast<Expr>(S))
1641 S = E->IgnoreParens();
1645 return VisitStmt(S, asc);
1647 case Stmt::AddrLabelExprClass:
1648 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
1650 case Stmt::BinaryConditionalOperatorClass:
1651 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
1653 case Stmt::BinaryOperatorClass:
1654 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
1656 case Stmt::BlockExprClass:
1657 return VisitBlockExpr(cast<BlockExpr>(S), asc);
1659 case Stmt::BreakStmtClass:
1660 return VisitBreakStmt(cast<BreakStmt>(S));
1662 case Stmt::CallExprClass:
1663 case Stmt::CXXOperatorCallExprClass:
1664 case Stmt::CXXMemberCallExprClass:
1665 case Stmt::UserDefinedLiteralClass:
1666 return VisitCallExpr(cast<CallExpr>(S), asc);
1668 case Stmt::CaseStmtClass:
1669 return VisitCaseStmt(cast<CaseStmt>(S));
1671 case Stmt::ChooseExprClass:
1672 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
1674 case Stmt::CompoundStmtClass:
1675 return VisitCompoundStmt(cast<CompoundStmt>(S));
1677 case Stmt::ConditionalOperatorClass:
1678 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
1680 case Stmt::ContinueStmtClass:
1681 return VisitContinueStmt(cast<ContinueStmt>(S));
1683 case Stmt::CXXCatchStmtClass:
1684 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
1686 case Stmt::ExprWithCleanupsClass:
1687 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
1689 case Stmt::CXXDefaultArgExprClass:
1690 case Stmt::CXXDefaultInitExprClass:
1700 return VisitStmt(S, asc);
1702 case Stmt::CXXBindTemporaryExprClass:
1703 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
1705 case Stmt::CXXConstructExprClass:
1706 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
1708 case Stmt::CXXNewExprClass:
1709 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
1711 case Stmt::CXXDeleteExprClass:
1712 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
1714 case Stmt::CXXFunctionalCastExprClass:
1715 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
1717 case Stmt::CXXTemporaryObjectExprClass:
1718 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
1720 case Stmt::CXXThrowExprClass:
1721 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
1723 case Stmt::CXXTryStmtClass:
1724 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
1726 case Stmt::CXXForRangeStmtClass:
1727 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
1729 case Stmt::DeclStmtClass:
1730 return VisitDeclStmt(cast<DeclStmt>(S));
1732 case Stmt::DefaultStmtClass:
1733 return VisitDefaultStmt(cast<DefaultStmt>(S));
1735 case Stmt::DoStmtClass:
1736 return VisitDoStmt(cast<DoStmt>(S));
1738 case Stmt::ForStmtClass:
1739 return VisitForStmt(cast<ForStmt>(S));
1741 case Stmt::GotoStmtClass:
1742 return VisitGotoStmt(cast<GotoStmt>(S));
1744 case Stmt::IfStmtClass:
1745 return VisitIfStmt(cast<IfStmt>(S));
1747 case Stmt::ImplicitCastExprClass:
1748 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
1750 case Stmt::IndirectGotoStmtClass:
1751 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
1753 case Stmt::LabelStmtClass:
1754 return VisitLabelStmt(cast<LabelStmt>(S));
1756 case Stmt::LambdaExprClass:
1757 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
1759 case Stmt::MemberExprClass:
1760 return VisitMemberExpr(cast<MemberExpr>(S), asc);
1762 case Stmt::NullStmtClass:
1765 case Stmt::ObjCAtCatchStmtClass:
1766 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
1768 case Stmt::ObjCAutoreleasePoolStmtClass:
1769 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
1771 case Stmt::ObjCAtSynchronizedStmtClass:
1772 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
1774 case Stmt::ObjCAtThrowStmtClass:
1775 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
1777 case Stmt::ObjCAtTryStmtClass:
1778 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
1780 case Stmt::ObjCForCollectionStmtClass:
1781 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
1783 case Stmt::OpaqueValueExprClass:
1786 case Stmt::PseudoObjectExprClass:
1787 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
1789 case Stmt::ReturnStmtClass:
1790 return VisitReturnStmt(cast<ReturnStmt>(S));
1792 case Stmt::SEHExceptStmtClass:
1793 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
1795 case Stmt::SEHFinallyStmtClass:
1796 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
1798 case Stmt::SEHLeaveStmtClass:
1799 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
1801 case Stmt::SEHTryStmtClass:
1802 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
1804 case Stmt::UnaryExprOrTypeTraitExprClass:
1805 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1808 case Stmt::StmtExprClass:
1809 return VisitStmtExpr(cast<StmtExpr>(S), asc);
1811 case Stmt::SwitchStmtClass:
1812 return VisitSwitchStmt(cast<SwitchStmt>(S));
1814 case Stmt::UnaryOperatorClass:
1815 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
1817 case Stmt::WhileStmtClass:
1818 return VisitWhileStmt(cast<WhileStmt>(S));
1822 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
1823 if (asc.alwaysAdd(*
this, S)) {
1825 appendStmt(Block, S);
1828 return VisitChildren(S);
1837 reverse_children RChildren(S);
1838 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
1840 if (
Stmt *Child = *I)
1848 AddStmtChoice asc) {
1849 AddressTakenLabels.insert(A->
getLabel());
1851 if (asc.alwaysAdd(*
this, A)) {
1853 appendStmt(Block, A);
1860 AddStmtChoice asc) {
1861 if (asc.alwaysAdd(*
this, U)) {
1863 appendStmt(Block, U);
1866 return Visit(U->
getSubExpr(), AddStmtChoice());
1870 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1871 appendStmt(ConfluenceBlock, B);
1876 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
1877 ConfluenceBlock).first;
1880 std::pair<CFGBlock*, CFGBlock*>
1893 if (B_RHS->isLogicalOp()) {
1894 std::tie(RHSBlock, ExitBlock) =
1895 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
1903 ExitBlock = RHSBlock = createBlock(
false);
1908 TryResult KnownVal = tryEvaluateBool(RHS);
1909 if (!KnownVal.isKnown())
1910 KnownVal = tryEvaluateBool(B);
1913 assert(TrueBlock == FalseBlock);
1914 addSuccessor(RHSBlock, TrueBlock);
1918 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
1919 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
1923 RHSBlock = addStmt(RHS);
1928 return std::make_pair(
nullptr,
nullptr);
1934 if (B_LHS->isLogicalOp()) {
1936 FalseBlock = RHSBlock;
1938 TrueBlock = RHSBlock;
1943 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
1948 CFGBlock *LHSBlock = createBlock(
false);
1952 CFGBlock *EntryLHSBlock = addStmt(LHS);
1955 return std::make_pair(
nullptr,
nullptr);
1958 TryResult KnownVal = tryEvaluateBool(LHS);
1962 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
1963 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
1966 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
1967 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
1970 return std::make_pair(EntryLHSBlock, ExitBlock);
1974 AddStmtChoice asc) {
1977 return VisitLogicalOperator(B);
1981 appendStmt(Block, B);
1983 return addStmt(B->
getLHS());
1987 if (asc.alwaysAdd(*
this, B)) {
1989 appendStmt(Block, B);
1992 return Visit(B->
getRHS());
1995 if (asc.alwaysAdd(*
this, B)) {
1997 appendStmt(Block, B);
2005 return (LBlock ? LBlock : RBlock);
2008 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2009 if (asc.alwaysAdd(*
this, E)) {
2011 appendStmt(Block, E);
2023 Block = createBlock(
false);
2024 Block->setTerminator(B);
2028 if (BreakJumpTarget.block) {
2029 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2030 addSuccessor(Block, BreakJumpTarget.block);
2048 Proto->isNothrow(Ctx))
2062 if (!boundType.
isNull()) calleeType = boundType;
2068 bool AddEHEdge =
false;
2072 if (BuildOpts.AddEHEdges)
2078 bool OmitArguments =
false;
2081 if (FD->isNoReturn())
2083 if (FD->hasAttr<NoThrowAttr>())
2085 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
2086 OmitArguments =
true;
2092 if (OmitArguments) {
2093 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2094 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2096 appendStmt(Block, C);
2100 if (!NoReturn && !AddEHEdge) {
2101 return VisitStmt(C, asc.withAlwaysAdd(
true));
2111 Block = createNoReturnBlock();
2113 Block = createBlock();
2115 appendStmt(Block, C);
2119 if (TryTerminatedBlock)
2120 addSuccessor(Block, TryTerminatedBlock);
2122 addSuccessor(Block, &cfg->getExit());
2125 return VisitChildren(C);
2129 AddStmtChoice asc) {
2130 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2131 appendStmt(ConfluenceBlock, C);
2135 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2136 Succ = ConfluenceBlock;
2142 Succ = ConfluenceBlock;
2148 Block = createBlock(
false);
2150 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2151 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2152 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2153 Block->setTerminator(C);
2158 LocalScope::const_iterator scopeBeginPos = ScopePos;
2159 addLocalScopeForStmt(C);
2164 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2173 if (
CFGBlock *newBlock = addStmt(*I))
2174 LastBlock = newBlock;
2184 AddStmtChoice asc) {
2190 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2191 appendStmt(ConfluenceBlock, C);
2195 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2201 Succ = ConfluenceBlock;
2205 if (trueExpr != opaqueValue) {
2212 LHSBlock = ConfluenceBlock;
2215 Succ = ConfluenceBlock;
2223 if (Cond->isLogicalOp())
2224 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2227 Block = createBlock(
false);
2230 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2231 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2232 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2233 Block->setTerminator(C);
2239 if (condExpr != opaqueValue)
2247 return addStmt(condExpr);
2258 return VisitDeclSubExpr(DS);
2273 void *Mem = cfg->getAllocator().Allocate(
sizeof(
DeclStmt), A);
2275 cfg->addSyntheticDeclStmt(DSNew, DS);
2278 B = VisitDeclSubExpr(DSNew);
2287 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2296 bool HasTemporaries =
false;
2299 CFGBlock *blockAfterStaticInit =
nullptr;
2301 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2310 blockAfterStaticInit = Succ;
2315 Expr *Init = VD->getInit();
2317 HasTemporaries = isa<ExprWithCleanups>(Init);
2319 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2321 TempDtorContext Context;
2322 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2328 appendStmt(Block, DS);
2336 if (HasTemporaries) {
2341 LastBlock = newBlock;
2344 if (
CFGBlock *newBlock = Visit(Init))
2345 LastBlock = newBlock;
2351 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2352 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2353 LastBlock = newBlock;
2357 if (ScopePos && VD == *ScopePos)
2361 if (blockAfterStaticInit) {
2363 Block = createBlock(
false);
2364 Block->setTerminator(DS);
2365 addSuccessor(Block, blockAfterStaticInit);
2366 addSuccessor(Block, B);
2387 addLocalScopeForStmt(Init);
2392 addLocalScopeForVarDecl(VD);
2394 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
2416 if (!isa<CompoundStmt>(Else))
2417 addLocalScopeAndDtors(Else);
2419 ElseBlock = addStmt(Else);
2422 ElseBlock = sv.get();
2439 if (!isa<CompoundStmt>(Then))
2440 addLocalScopeAndDtors(Then);
2442 ThenBlock = addStmt(Then);
2448 ThenBlock = createBlock(
false);
2449 addSuccessor(ThenBlock, sv.get());
2469 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2472 Block = createBlock(
false);
2475 Block->setTerminator(I);
2478 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2482 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2483 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2488 LastBlock = addStmt(I->
getCond());
2494 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2501 LastBlock = addStmt(Init);
2516 Block = createBlock(
false);
2518 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), R);
2522 if (!Block->hasNoReturnElement())
2523 addSuccessor(Block, &cfg->getExit());
2527 return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2540 if (!SEHExceptBlock)
2541 SEHExceptBlock = createBlock();
2543 appendStmt(SEHExceptBlock, ES);
2546 SEHExceptBlock->setLabel(ES);
2555 return SEHExceptBlock;
2559 return VisitCompoundStmt(FS->
getBlock());
2569 Block = createBlock(
false);
2570 Block->setTerminator(LS);
2574 if (SEHLeaveJumpTarget.block) {
2575 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
2576 addSuccessor(Block, SEHLeaveJumpTarget.block);
2586 CFGBlock *SEHTrySuccessor =
nullptr;
2591 SEHTrySuccessor = Block;
2592 }
else SEHTrySuccessor = Succ;
2598 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
2601 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
2608 Succ = SEHTrySuccessor;
2610 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
2615 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
2617 if (PrevSEHTryTerminatedBlock)
2618 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
2620 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
2623 Succ = SEHTrySuccessor;
2627 NewTryTerminatedBlock);
2628 cfg->addTryDispatchBlock(TryTerminatedBlock);
2634 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
2636 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
2647 LabelBlock = createBlock();
2649 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
2650 "label already in map");
2651 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
2657 LabelBlock->setLabel(L);
2671 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2673 if (
Expr *CopyExpr = CI.getCopyExpr()) {
2683 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2686 if (
Expr *Init = *it) {
2699 Block = createBlock(
false);
2700 Block->setTerminator(G);
2703 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
2705 if (I == LabelMap.end())
2707 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
2709 JumpTarget JT = I->second;
2710 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
2711 addSuccessor(Block, JT.block);
2728 addLocalScopeForStmt(Init);
2729 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2732 addLocalScopeForVarDecl(VD);
2733 LocalScope::const_iterator ContinueScopePos = ScopePos;
2735 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
2744 LoopSuccessor = Block;
2746 LoopSuccessor = Succ;
2751 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2753 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2766 Block = Succ = TransitionBlock = createBlock(
false);
2767 TransitionBlock->setLoopTarget(F);
2777 assert(Block == Succ);
2785 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
2786 ContinueJumpTarget.block->setLoopTarget(F);
2789 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
2793 if (!isa<CompoundStmt>(F->
getBody()))
2794 addLocalScopeAndDtors(F->
getBody());
2798 BodyBlock = addStmt(F->
getBody());
2803 BodyBlock = ContinueJumpTarget.block;
2812 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2820 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
2821 if (Cond->isLogicalOp()) {
2822 std::tie(EntryConditionBlock, ExitConditionBlock) =
2823 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
2828 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
2829 ExitConditionBlock->setTerminator(F);
2832 TryResult KnownVal(
true);
2838 Block = ExitConditionBlock;
2839 EntryConditionBlock = addStmt(C);
2847 EntryConditionBlock = addStmt(Init);
2848 assert(Block == EntryConditionBlock);
2852 if (Block && badCFG)
2855 KnownVal = tryEvaluateBool(C);
2859 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
2862 addSuccessor(ExitConditionBlock,
2863 KnownVal.isTrue() ? nullptr : LoopSuccessor);
2867 addSuccessor(TransitionBlock, EntryConditionBlock);
2870 Succ = EntryConditionBlock;
2875 Block = createBlock();
2882 Succ = EntryConditionBlock;
2883 return EntryConditionBlock;
2887 if (asc.alwaysAdd(*
this, M)) {
2889 appendStmt(Block, M);
2931 LoopSuccessor = Block;
2934 LoopSuccessor = Succ;
2937 CFGBlock *ExitConditionBlock = createBlock(
false);
2945 appendStmt(ExitConditionBlock, S);
2946 Block = ExitConditionBlock;
2952 AddStmtChoice::NotAlwaysAdd);
2961 Succ = EntryConditionBlock;
2968 save_break(BreakJumpTarget);
2974 Succ = LoopBackBlock = createBlock();
2977 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2978 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
2983 BodyBlock = ContinueJumpTarget.block;
2990 addSuccessor(ExitConditionBlock, BodyBlock);
2995 addSuccessor(ExitConditionBlock, LoopSuccessor);
2998 Block = createBlock();
3026 appendStmt(Block, S);
3041 appendStmt(Block, E);
3053 Semantic = OVE->getSourceExpr();
3071 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3073 addLocalScopeForVarDecl(VD);
3074 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3083 LoopSuccessor = Block;
3086 LoopSuccessor = Succ;
3089 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3098 save_break(BreakJumpTarget);
3102 Succ = TransitionBlock = createBlock(
false);
3103 TransitionBlock->setLoopTarget(W);
3104 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3107 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3110 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3114 if (!isa<CompoundStmt>(W->
getBody()))
3115 addLocalScopeAndDtors(W->
getBody());
3118 BodyBlock = addStmt(W->
getBody());
3121 BodyBlock = ContinueJumpTarget.block;
3122 else if (Block && badCFG)
3129 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3137 if (Cond->isLogicalOp()) {
3138 std::tie(EntryConditionBlock, ExitConditionBlock) =
3139 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3144 ExitConditionBlock = createBlock(
false);
3145 ExitConditionBlock->setTerminator(W);
3150 Block = ExitConditionBlock;
3151 Block = EntryConditionBlock = addStmt(C);
3159 EntryConditionBlock = addStmt(Init);
3160 assert(Block == EntryConditionBlock);
3164 if (Block && badCFG)
3168 const TryResult& KnownVal = tryEvaluateBool(C);
3171 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3174 addSuccessor(ExitConditionBlock,
3175 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3179 addSuccessor(TransitionBlock, EntryConditionBlock);
3186 Succ = EntryConditionBlock;
3187 return EntryConditionBlock;
3205 Block = createBlock(
false);
3208 addSuccessor(Block, &cfg->getExit());
3212 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
3221 Block = createBlock(
false);
3223 if (TryTerminatedBlock)
3225 addSuccessor(Block, TryTerminatedBlock);
3228 addSuccessor(Block, &cfg->getExit());
3232 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
3245 LoopSuccessor = Block;
3247 LoopSuccessor = Succ;
3252 CFGBlock *ExitConditionBlock = createBlock(
false);
3253 CFGBlock *EntryConditionBlock = ExitConditionBlock;
3261 Block = ExitConditionBlock;
3262 EntryConditionBlock = addStmt(C);
3270 Succ = EntryConditionBlock;
3273 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
3283 save_break(BreakJumpTarget);
3286 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
3289 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3296 if (!isa<CompoundStmt>(D->
getBody()))
3297 addLocalScopeAndDtors(D->
getBody());
3300 BodyBlock = addStmt(D->
getBody());
3303 BodyBlock = EntryConditionBlock;
3316 CFGBlock *LoopBackBlock = createBlock();
3319 if (!KnownVal.isFalse())
3321 addSuccessor(ExitConditionBlock, LoopBackBlock);
3323 addSuccessor(ExitConditionBlock,
nullptr);
3328 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3346 Block = createBlock(
false);
3347 Block->setTerminator(C);
3351 if (ContinueJumpTarget.block) {
3352 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
3353 addSuccessor(Block, ContinueJumpTarget.block);
3361 AddStmtChoice asc) {
3362 if (asc.alwaysAdd(*
this, E)) {
3364 appendStmt(Block, E);
3372 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3373 lastBlock = addStmt(VA->getSizeExpr());
3381 if (asc.alwaysAdd(*
this, SE)) {
3383 appendStmt(Block, SE);
3391 CFGBlock *SwitchSuccessor =
nullptr;
3399 addLocalScopeForStmt(Init);
3404 addLocalScopeForVarDecl(VD);
3406 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
3411 SwitchSuccessor = Block;
3412 }
else SwitchSuccessor = Succ;
3416 save_default(DefaultCaseBlock);
3422 DefaultCaseBlock = SwitchSuccessor;
3425 SwitchTerminatedBlock = createBlock(
false);
3429 Succ = SwitchSuccessor;
3430 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3435 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3444 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3446 bool b = tryEvaluate(Terminator->
getCond(), result);
3448 b ? &result :
nullptr);
3452 if (!isa<CompoundStmt>(Terminator->
getBody()))
3453 addLocalScopeAndDtors(Terminator->
getBody());
3455 addStmt(Terminator->
getBody());
3467 bool SwitchAlwaysHasSuccessor =
false;
3468 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3471 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3472 !SwitchAlwaysHasSuccessor);
3475 SwitchTerminatedBlock->setTerminator(Terminator);
3476 Block = SwitchTerminatedBlock;
3485 LastBlock = addStmt(Init);
3492 LastBlock = addStmt(Init);
3505 bool addCase =
false;
3507 if (!switchExclusivelyCovered) {
3511 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3513 if (condInt == lhsInt) {
3515 switchExclusivelyCovered =
true;
3517 else if (condInt > lhsInt) {
3520 const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
3521 if (V2 >= condInt) {
3523 switchExclusivelyCovered =
true;
3537 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3543 while (isa<CaseStmt>(Sub)) {
3544 CFGBlock *currentBlock = createBlock(
false);
3548 addSuccessor(LastBlock, currentBlock);
3550 TopBlock = currentBlock;
3552 addSuccessor(SwitchTerminatedBlock,
3555 ? currentBlock :
nullptr);
3557 LastBlock = currentBlock;
3558 CS = cast<CaseStmt>(Sub);
3567 CaseBlock = createBlock();
3578 assert(SwitchTerminatedBlock);
3579 addSuccessor(SwitchTerminatedBlock, CaseBlock,
3587 addSuccessor(LastBlock, CaseBlock);
3601 DefaultCaseBlock = Block;
3603 if (!DefaultCaseBlock)
3604 DefaultCaseBlock = createBlock();
3608 DefaultCaseBlock->setLabel(Terminator);
3623 Succ = DefaultCaseBlock;
3625 return DefaultCaseBlock;
3636 TrySuccessor = Block;
3637 }
else TrySuccessor = Succ;
3639 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
3642 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3646 bool HasCatchAll =
false;
3649 Succ = TrySuccessor;
3655 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
3660 addSuccessor(NewTryTerminatedBlock, CatchBlock);
3663 if (PrevTryTerminatedBlock)
3664 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
3666 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3670 Succ = TrySuccessor;
3674 cfg->addTryDispatchBlock(TryTerminatedBlock);
3676 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
3692 LocalScope::const_iterator BeginScopePos = ScopePos;
3693 addLocalScopeForVarDecl(VD);
3694 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
3702 CatchBlock = createBlock();
3708 appendStmt(CatchBlock, CS);
3743 addLocalScopeForStmt(Range);
3745 addLocalScopeForStmt(
Begin);
3747 addLocalScopeForStmt(
End);
3748 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
3750 LocalScope::const_iterator ContinueScopePos = ScopePos;
3758 LoopSuccessor = Block;
3760 LoopSuccessor = Succ;
3765 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3768 CFGBlock *ConditionBlock = createBlock(
false);
3773 Block = ConditionBlock;
3774 CFGBlock *BeginConditionBlock = addStmt(C);
3777 assert(BeginConditionBlock == ConditionBlock &&
3778 "condition block in for-range was unexpectedly complex");
3779 (void)BeginConditionBlock;
3784 Succ = ConditionBlock;
3787 TryResult KnownVal(
true);
3790 KnownVal = tryEvaluateBool(S->
getCond());
3803 Succ = addStmt(S->
getInc());
3806 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3810 ContinueJumpTarget.block->setLoopTarget(S);
3830 addSuccessor(ConditionBlock,
3831 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
3836 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3839 Block = createBlock();
3846 AddStmtChoice asc) {
3847 if (BuildOpts.AddTemporaryDtors) {
3850 TempDtorContext Context;
3851 VisitForTemporaryDtors(E->
getSubExpr(),
false, Context);
3855 asc = asc.withAlwaysAdd(
true);
3861 AddStmtChoice asc) {
3862 if (asc.alwaysAdd(*
this, E)) {
3864 appendStmt(Block, E);
3867 asc = asc.withAlwaysAdd(
false);
3873 AddStmtChoice asc) {
3875 appendStmt(Block, C);
3877 return VisitChildren(C);
3881 AddStmtChoice asc) {
3883 appendStmt(Block, NE);
3887 if (BuildOpts.AddCXXNewAllocator)
3888 appendNewAllocator(Block, NE);
3898 AddStmtChoice asc) {
3900 appendStmt(Block, DE);
3907 appendDeleteDtor(Block, RD, DE);
3911 return VisitChildren(DE);
3915 AddStmtChoice asc) {
3916 if (asc.alwaysAdd(*
this, E)) {
3918 appendStmt(Block, E);
3920 asc = asc.withAlwaysAdd(
false);
3926 AddStmtChoice asc) {
3928 appendStmt(Block, C);
3929 return VisitChildren(C);
3933 AddStmtChoice asc) {
3934 if (asc.alwaysAdd(*
this, E)) {
3936 appendStmt(Block, E);
3938 return Visit(E->
getSubExpr(), AddStmtChoice());
3943 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
3946 IBlock = createBlock(
false);
3947 cfg->setIndirectGotoBlock(IBlock);
3955 Block = createBlock(
false);
3956 Block->setTerminator(I);
3957 addSuccessor(Block, IBlock);
3961 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
3962 TempDtorContext &Context) {
3963 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
3972 return VisitChildrenForTemporaryDtors(E, Context);
3974 case Stmt::BinaryOperatorClass:
3975 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
3978 case Stmt::CXXBindTemporaryExprClass:
3979 return VisitCXXBindTemporaryExprForTemporaryDtors(
3980 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
3982 case Stmt::BinaryConditionalOperatorClass:
3983 case Stmt::ConditionalOperatorClass:
3984 return VisitConditionalOperatorForTemporaryDtors(
3985 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
3987 case Stmt::ImplicitCastExprClass:
3989 E = cast<CastExpr>(E)->getSubExpr();
3992 case Stmt::CXXFunctionalCastExprClass:
3994 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
3997 case Stmt::ParenExprClass:
3998 E = cast<ParenExpr>(E)->getSubExpr();
4001 case Stmt::MaterializeTemporaryExprClass: {
4007 E =
const_cast<Expr *
>(
4008 cast<MaterializeTemporaryExpr>(E)
4009 ->GetTemporaryExpr()
4010 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4012 for (
const Expr *CommaLHS : CommaLHSs) {
4013 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
4019 case Stmt::BlockExprClass:
4024 case Stmt::LambdaExprClass: {
4027 auto *LE = cast<LambdaExpr>(E);
4029 for (
Expr *Init : LE->capture_inits()) {
4030 if (
CFGBlock *R = VisitForTemporaryDtors(
4031 Init,
false, Context))
4037 case Stmt::CXXDefaultArgExprClass:
4038 E = cast<CXXDefaultArgExpr>(E)->getExpr();
4041 case Stmt::CXXDefaultInitExprClass:
4042 E = cast<CXXDefaultInitExpr>(E)->getExpr();
4047 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
4048 TempDtorContext &Context) {
4049 if (isa<LambdaExpr>(E)) {
4061 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
4067 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
4070 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4071 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
4072 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
4073 RHSExecuted.negate();
4078 TempDtorContext RHSContext(
4080 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
4081 InsertTempDtorDecisionBlock(RHSContext);
4089 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4090 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4091 return LHSBlock ? LHSBlock : RHSBlock;
4097 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4098 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4099 return RHSBlock ? RHSBlock : LHSBlock;
4102 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
4106 if (!BindToTemporary) {
4118 Block = createNoReturnBlock();
4119 }
else if (Context.needsTempDtorBranch()) {
4123 Block = createBlock();
4127 if (Context.needsTempDtorBranch()) {
4128 Context.setDecisionPoint(Succ, E);
4130 appendTemporaryDtor(Block, E);
4137 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
4139 if (!Context.TerminatorExpr) {
4143 assert(Context.TerminatorExpr);
4144 CFGBlock *Decision = createBlock(
false);
4146 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
4147 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
4148 !Context.KnownExecuted.isTrue());
4152 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
4154 TempDtorContext &Context) {
4155 VisitForTemporaryDtors(E->
getCond(),
false, Context);
4158 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
4159 TryResult NegatedVal = ConditionVal;
4160 if (NegatedVal.isKnown()) NegatedVal.negate();
4162 TempDtorContext TrueContext(
4164 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
4167 Block = ConditionBlock;
4168 Succ = ConditionSucc;
4169 TempDtorContext FalseContext(
4171 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
4173 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
4174 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
4175 }
else if (TrueContext.TerminatorExpr) {
4177 InsertTempDtorDecisionBlock(TrueContext);
4179 InsertTempDtorDecisionBlock(FalseContext);
4188 bool first_block = begin() == end();
4192 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
4193 Blocks.push_back(Mem, BlkBVC);
4197 Entry = Exit = &back();
4206 CFGBuilder Builder(C, BO);
4207 return Builder.buildCFG(D, Statement);
4218 llvm_unreachable(
"getDestructorDecl should only be used with " 4221 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
4239 cast<CXXRecordDecl>(recordType->
getDecl());
4243 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
4252 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
4261 llvm_unreachable(
"getKind() returned bogus value");
4275 : ReachableBlock(IsReachable ? B : nullptr),
4276 UnreachableBlock(!IsReachable ? B : nullptr,
4277 B && IsReachable ? AB_Normal : AB_Unreachable) {}
4280 : ReachableBlock(B),
4281 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
4282 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
4290 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
4292 Succs.push_back(Succ, C);
4305 if (S->isAllEnumCasesCovered()) {
4307 if (!L || !isa<CaseStmt>(L))
4323 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
4324 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
4328 signed currentBlock = 0;
4329 unsigned currStmt = 0;
4338 BI != BEnd; ++BI, ++j ) {
4340 const Stmt *stmt= SE->getStmt();
4341 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
4345 case Stmt::DeclStmtClass:
4346 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
4348 case Stmt::IfStmtClass: {
4349 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
4354 case Stmt::ForStmtClass: {
4355 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4360 case Stmt::WhileStmtClass: {
4362 cast<WhileStmt>(
stmt)->getConditionVariable();
4367 case Stmt::SwitchStmtClass: {
4369 cast<SwitchStmt>(
stmt)->getConditionVariable();
4374 case Stmt::CXXCatchStmtClass: {
4376 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
4389 ~StmtPrinterHelper()
override =
default;
4391 const LangOptions &getLangOpts()
const {
return LangOpts; }
4392 void setBlockID(
signed i) { currentBlock = i; }
4393 void setStmtID(
unsigned i) { currStmt = i; }
4395 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
4396 StmtMapTy::iterator I = StmtMap.find(S);
4398 if (I == StmtMap.end())
4401 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4402 && I->second.second == currStmt) {
4406 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4410 bool handleDecl(
const Decl *D, raw_ostream &OS) {
4411 DeclMapTy::iterator I = DeclMap.find(D);
4413 if (I == DeclMap.end())
4416 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4417 && I->second.second == currStmt) {
4421 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4426 class CFGBlockTerminatorPrint
4427 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4429 StmtPrinterHelper* Helper;
4433 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4435 : OS(os), Helper(helper), Policy(Policy) {
4439 void VisitIfStmt(
IfStmt *I) {
4446 void VisitStmt(
Stmt *Terminator) {
4452 OS <<
"static init " << VD->
getName();
4455 void VisitForStmt(
ForStmt *F) {
4474 void VisitDoStmt(
DoStmt *D) {
4475 OS <<
"do ... while ";
4480 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4495 Cond->printPretty(OS, Helper, Policy);
4496 OS <<
" ? ... : ...";
4500 OS <<
"__builtin_choose_expr( ";
4502 Cond->printPretty(OS, Helper, Policy);
4529 llvm_unreachable(
"Invalid logical operator.");
4533 void VisitExpr(
Expr *E) {
4540 OS <<
"(Temp Dtor) ";
4547 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
4550 const Stmt *S = CS->getStmt();
4551 assert(S !=
nullptr &&
"Expecting non-null Stmt");
4554 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
4558 if (Children.begin() != Children.end()) {
4567 if (B->getOpcode() == BO_Comma) {
4569 Helper.handledStmt(B->getRHS(),OS);
4576 if (isa<CXXOperatorCallExpr>(S)) {
4577 OS <<
" (OperatorCall)";
4579 else if (isa<CXXBindTemporaryExpr>(S)) {
4580 OS <<
" (BindTemporary)";
4583 OS <<
" (CXXConstructExpr, " << CCE->getType().getAsString() <<
")";
4585 else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
4586 OS <<
" (" << CE->getStmtClassName() <<
", " 4587 << CE->getCastKindName()
4588 <<
", " << CE->getType().getAsString()
4605 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4609 OS <<
" (Base initializer)\n";
4611 OS <<
" (Delegating initializer)\n";
4612 else OS <<
" (Member initializer)\n";
4615 const VarDecl *VD = DE->getVarDecl();
4616 Helper.handleDecl(VD, OS);
4624 OS <<
" (Implicit destructor)\n";
4626 const VarDecl *VD = DE->getVarDecl();
4627 Helper.handleDecl(VD, OS);
4629 OS <<
" (Lifetime ends)\n";
4631 const Stmt *LoopStmt = LE->getLoopStmt();
4634 OS <<
"CFGNewAllocator(";
4635 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
4636 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
4644 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
4645 OS <<
"->~" << RD->
getName().str() <<
"()";
4646 OS <<
" (Implicit destructor)\n";
4650 OS <<
" (Base object destructor)\n";
4652 const FieldDecl *FD = ME->getFieldDecl();
4654 OS <<
"this->" << FD->
getName();
4656 OS <<
" (Member object destructor)\n";
4661 OS <<
"() (Temporary object destructor)\n";
4667 StmtPrinterHelper &Helper,
bool print_edges,
4673 OS.changeColor(raw_ostream::YELLOW,
true);
4678 OS <<
" (ENTRY)]\n";
4679 else if (&B == &cfg->
getExit())
4682 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
4684 OS <<
" (NORETURN)]\n";
4708 }
else if (isa<DefaultStmt>(
Label))
4724 llvm_unreachable(
"Invalid label statement in CFGBlock.");
4733 I != E ; ++I, ++j ) {
4738 OS << llvm::format(
"%3d", j) <<
": ";
4740 Helper.setStmtID(j);
4748 OS.changeColor(raw_ostream::GREEN);
4752 Helper.setBlockID(-1);
4755 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
4766 const raw_ostream::Colors Color = raw_ostream::BLUE;
4768 OS.changeColor(Color);
4776 OS.changeColor(Color);
4784 bool Reachable =
true;
4787 B = I->getPossiblyUnreachableBlock();
4792 OS <<
"(Unreachable)";
4803 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
4805 OS.changeColor(Color);
4813 OS.changeColor(Color);
4822 bool Reachable =
true;
4825 B = I->getPossiblyUnreachableBlock();
4831 OS <<
"(Unreachable)";
4847 print(llvm::errs(), LO, ShowColors);
4852 StmtPrinterHelper Helper(
this, LO);
4855 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
4858 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
4860 if (&(**I) == &getEntry() || &(**I) == &getExit())
4863 print_block(OS,
this, **I, Helper,
true, ShowColors);
4867 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
4874 bool ShowColors)
const {
4875 print(llvm::errs(), cfg, LO, ShowColors);
4886 StmtPrinterHelper Helper(cfg, LO);
4887 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
4894 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
4899 Stmt *Terminator = this->Terminator;
4909 case Stmt::CXXForRangeStmtClass:
4910 E = cast<CXXForRangeStmt>(Terminator)->getCond();
4913 case Stmt::ForStmtClass:
4914 E = cast<ForStmt>(Terminator)->getCond();
4917 case Stmt::WhileStmtClass:
4918 E = cast<WhileStmt>(Terminator)->getCond();
4921 case Stmt::DoStmtClass:
4922 E = cast<DoStmt>(Terminator)->getCond();
4925 case Stmt::IfStmtClass:
4926 E = cast<IfStmt>(Terminator)->getCond();
4929 case Stmt::ChooseExprClass:
4930 E = cast<ChooseExpr>(Terminator)->getCond();
4933 case Stmt::IndirectGotoStmtClass:
4934 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
4937 case Stmt::SwitchStmtClass:
4938 E = cast<SwitchStmt>(Terminator)->getCond();
4941 case Stmt::BinaryConditionalOperatorClass:
4942 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
4945 case Stmt::ConditionalOperatorClass:
4946 E = cast<ConditionalOperator>(Terminator)->getCond();
4949 case Stmt::BinaryOperatorClass:
4950 E = cast<BinaryOperator>(Terminator)->getLHS();
4953 case Stmt::ObjCForCollectionStmtClass:
4973 StmtPrinterHelper H(
this, LO);
4975 llvm::ViewGraph(
this,
"CFG");
4976 GraphHelper =
nullptr;
4988 std::string OutSStr;
4989 llvm::raw_string_ostream Out(OutSStr);
4990 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
4991 std::string& OutStr = Out.str();
4993 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
4996 for (
unsigned i = 0; i != OutStr.length(); ++i)
4997 if (OutStr[i] ==
'\n') {
4999 OutStr.insert(OutStr.begin()+i+1,
'l');
unsigned getNumSemanticExprs() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Defines the clang::ASTContext interface.
const BlockDecl * getBlockDecl() const
CFGNewAllocator - Represents C++ allocator call.
const CXXDestructorDecl * getDestructor() const
An instance of this class is created to represent a function declaration or definition.
Expr * getInit() const
Get the initializer.
const Stmt * getElse() const
CompoundStmt * getBlock() const
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...
A class which contains all the information about a particular captured value.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
static SourceLocation GetEndLoc(Decl *D)
AdjacentBlocks::const_iterator const_pred_iterator
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
ElementList::iterator iterator
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
const DeclStmt * getConditionVariableDeclStmt() const
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
Stmt - This represents one statement.
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
IfStmt - This represents an if/then/else.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
StorageClass getStorageClass() const
Returns the storage class as written in the source.
C Language Family Type Representation.
bool isRecordType() const
unsigned getBlockID() const
Decl - This represents one declaration (or definition), e.g.
Stmt * getHandlerBlock() const
static QualType getReferenceInitTemporaryType(ASTContext &Context, const Expr *Init, bool *FoundMTE=nullptr)
Retrieve the type of the temporary object whose lifetime was extended by a local reference with the g...
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Expr * getFalseExpr() 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.
Represents a call to a C++ constructor.
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.
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "while" statement, if any.
unsigned succ_size() const
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
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...
VarDecl - An instance of this class is created to represent a variable declaration or definition...
const T * getAs() const
Member-template getAs<specific type>'.
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
const char * getName() const
Describes how types, statements, expressions, and declarations should be printed. ...
Defines the Objective-C statement AST node classes.
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 ...
static bool isAssignmentOp(Opcode Opc)
Defines the clang::Expr interface and subclasses for C++ expressions.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "switch" statement, if any.
const Stmt * getSubStmt() const
const char * getStmtClassName() const
LabelStmt - Represents a label, which has a substatement.
const AstTypeMatcher< RecordType > recordType
Matches record types (e.g.
static TryResult bothKnownTrue(TryResult R1, TryResult R2)
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
QualType getPointeeType() const
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)
field_range fields() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
Defines the ExceptionSpecificationType enumeration and various utility functions. ...
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated for automatic object or t...
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
bool isReferenceType() const
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
void setTerminator(CFGTerminator Term)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents Objective-C's @catch statement.
AdjacentBlocks::const_iterator const_succ_iterator
IndirectGotoStmt - This represents an indirect goto.
Describes an C or C++ initializer list.
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 ...
ForStmt - This represents a 'for (init;cond;inc)' stmt.
APValue Val
Val - This is the value the expression can be folded to.
LabelDecl * getDecl() const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
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.
A builtin binary operation expression such as "x + y" or "x <= y".
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
static bool areExprTypesCompatible(const Expr *E1, const Expr *E2)
For an expression x == Foo && x == Bar, this determines whether the Foo and Bar are either of the sam...
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.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, const ASTContext *Context=nullptr) const
Scope - A scope is a transient data structure that is used while parsing the program.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
FieldDecl * getAnyMember() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
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.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
arg_iterator placement_arg_end()
Iterator for iterating over Stmt * arrays that contain only Expr *.
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
CFGBlockListTy::const_iterator const_iterator
CompoundStmt - This represents a group of statements like { stmt stmt }.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a prototype with parameter type info, e.g.
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
static bool shouldAddCase(bool &switchExclusivelyCovered, const Expr::EvalResult *switchCond, const CaseStmt *CS, ASTContext &Ctx)
CFGBlock - Represents a single basic block in a source-level CFG.
const DeclStmt * getConditionVariableDeclStmt() const
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool isNoReturn(ASTContext &astContext) const
Expr - This represents one expression.
Defines the clang::LangOptions interface.
Stmt * getTerminatorCondition(bool StripParens=true)
static std::tuple< const DeclRefExpr *, BinaryOperatorKind, const Expr * > tryNormalizeBinaryOperator(const BinaryOperator *B)
Tries to interpret a binary operator into Decl Op Expr form, if Expr is an integer literal or an enum...
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
const FunctionProtoType * T
Represents a C++ functional cast expression that builds a temporary object.
const Stmt * getThen() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
VarDecl * getExceptionDecl() const
unsigned getNumInits() const
const Expr * getCallee() const
QualType getArgumentType() const
const CompoundStmt * getSynchBody() const
ElementList::const_iterator const_iterator
bool isTemporaryDtorsBranch() const
Represents Objective-C's @synchronized statement.
CXXTryStmt - A C++ try block, including all handlers.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
std::reverse_iterator< body_iterator > reverse_body_iterator
LabelDecl * getLabel() const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
static bool CanThrow(Expr *E, ASTContext &Ctx)
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
CFGBaseDtor - Represents C++ object destructor implicitly generated for base object in destructor...
Expr * getTrueExpr() const
The result type of a method or function.
QualType getDestroyedType() const
Retrieve the type being destroyed.
const Expr * getSubExpr() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
DoStmt - This represents a 'do/while' stmt.
std::reverse_iterator< decl_iterator > reverse_decl_iterator
RecordDecl * getDecl() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
CFGTerminator getTerminator()
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Encodes a location in the source.
unsigned getNumHandlers() const
Expr * getSubExpr() const
Represents a C++ temporary.
const SwitchCase * getSwitchCaseList() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
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. ...
bool PruneTriviallyFalseEdges
reverse_body_iterator body_rend()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
decl_iterator decl_begin()
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
bool isKnownToHaveBooleanValue() const
isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...
reverse_decl_iterator decl_rbegin()
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
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.
static bool isLogicalOp(Opcode Opc)
static const Expr * tryTransformToIntOrEnumConstant(const Expr *E)
Helper for tryNormalizeBinaryOperator.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
bool isArgumentType() const
const DeclStmt * getConditionVariableDeclStmt() const
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Defines various enumerations that describe declaration and type specifiers.
AddrLabelExpr - The GNU address of label extension, representing &&label.
ast_type_traits::DynTypedNode Node
pred_iterator pred_begin()
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "if" statement, if any.
Dataflow Directional Tag Classes.
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. ...
ArrayRef< Capture > captures() const
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
static const VariableArrayType * FindVA(const Type *t)
const Expr * getInit() const
unsigned pred_size() const
StmtClass getStmtClass() const
static StmtPrinterHelper * GraphHelper
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
bool isAnyDestructorNoReturn() const
Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn...
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
SEHExceptStmt * getExceptHandler() const
Returns 0 if not defined.
const Decl * getSingleDecl() const
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
const Expr * getSynchExpr() const
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
This class represents a potential adjacent block in the CFG.
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
Represents the point where the lifetime of an automatic object ends.
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
const Stmt * getBody() const
llvm::APInt getValue() const
Represents a __leave statement.
LabelDecl * getLabel() const
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...
Represents Objective-C's collection statement.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Represents a C++ base or member initializer.
reverse_decl_iterator decl_rend()
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S)
Base for LValueReferenceType and RValueReferenceType.
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFG that outputs to an ostream.
CanQualType BoundMemberTy
Represents a base class of a C++ class.
arg_iterator placement_arg_begin()
DeclStmt * getRangeStmt()
SEHFinallyStmt * getFinallyHandler() const
GotoStmt - This represents a direct goto.
A use of a default initializer in a constructor or in aggregate initialization.
unsigned IgnoreNullPredecessors
bool hasNoReturnElement() const
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.
void viewCFG(const LangOptions &LO) const
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
ContinueStmt - This represents a continue.
reverse_body_iterator body_rbegin()
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Expr * getFilterExpr() const
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.
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 dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
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...
A reference to a declared variable, function, enum, etc.
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)
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
const Expr * getCond() 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.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
DeclStmt * getBeginStmt()
const Expr * getCond() const
bool isFunctionPointerType() const
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const LangOptions & getLangOpts() const
Represents Objective-C's @autoreleasepool Statement.
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
CompoundStmt * getTryBlock() const
CFGTemporaryDtor - Represents C++ object destructor implicitly generated at the end of full expressio...
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Defines enum values for all the target-independent builtin functions.
CompoundStmt * getBlock() const
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
const DeclStmt * getConditionVariableDeclStmt() const
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
QualType getType() const
Retrieves the type of the base class.
Represents the point where a loop ends.