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();
39 return D->getLocation();
44 const Expr *tryTransformToIntOrEnumConstant(
const Expr *
E) {
46 if (isa<IntegerLiteral>(E))
49 return isa<EnumConstantDecl>(DR->getDecl()) ? DR :
nullptr;
58 static std::tuple<const DeclRefExpr *, BinaryOperatorKind, const Expr *>
63 const Expr *Constant = tryTransformToIntOrEnumConstant(B->
getRHS());
65 if (Constant ==
nullptr) {
77 Constant = tryTransformToIntOrEnumConstant(B->
getLHS());
81 return std::make_tuple(D, Op, Constant);
90 static bool areExprTypesCompatible(
const Expr *E1,
const Expr *E2) {
93 if (isa<IntegerLiteral>(E1) != isa<IntegerLiteral>(E2))
97 if (isa<IntegerLiteral>(E1))
102 assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
103 auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
104 auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
106 assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
110 assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
129 class AddStmtChoice {
131 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
133 AddStmtChoice(
Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
135 bool alwaysAdd(CFGBuilder &builder,
140 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
141 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
175 class const_iterator {
176 const LocalScope*
Scope;
187 :
Scope(nullptr), VarIter(0) {}
191 const_iterator(
const LocalScope&
S,
unsigned I)
192 :
Scope(&S), VarIter(I) {
195 if (VarIter == 0 &&
Scope)
199 VarDecl *
const* operator->()
const {
200 assert (
Scope &&
"Dereferencing invalid iterator is not allowed");
201 assert (VarIter != 0 &&
"Iterator has invalid value of VarIter member");
202 return &
Scope->Vars[VarIter - 1];
205 return *this->operator->();
208 const_iterator &operator++() {
212 assert (VarIter != 0 &&
"Iterator has invalid value of VarIter member");
218 const_iterator operator++(
int) {
219 const_iterator
P = *
this;
224 bool operator==(
const const_iterator &rhs)
const {
225 return Scope == rhs.Scope && VarIter == rhs.VarIter;
227 bool operator!=(
const const_iterator &rhs)
const {
228 return !(*
this == rhs);
231 explicit operator bool()
const {
232 return *
this != const_iterator();
238 friend class const_iterator;
244 AutomaticVarsTy Vars;
252 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
255 const_iterator
begin()
const {
return const_iterator(*
this, Vars.size()); }
258 Vars.push_back(VD, ctx);
267 const_iterator F = *
this;
268 while (F.Scope != L.Scope) {
269 assert (F != const_iterator()
270 &&
"L iterator is not reachable from F iterator.");
274 D += F.VarIter - L.VarIter;
281 struct BlockScopePosPair {
282 BlockScopePosPair() : block(nullptr) {}
283 BlockScopePosPair(
CFGBlock *b, LocalScope::const_iterator scopePos)
284 : block(b), scopePosition(scopePos) {}
287 LocalScope::const_iterator scopePosition;
297 TryResult(
bool b) :
X(b ? 1 : 0) {}
298 TryResult() :
X(-1) {}
300 bool isTrue()
const {
return X == 1; }
301 bool isFalse()
const {
return X == 0; }
302 bool isKnown()
const {
return X >= 0; }
309 TryResult bothKnownTrue(TryResult R1, TryResult R2) {
310 if (!R1.isKnown() || !R2.isKnown())
312 return TryResult(R1.isTrue() && R2.isTrue());
315 class reverse_children {
319 reverse_children(
Stmt *S);
327 reverse_children::reverse_children(
Stmt *S) {
328 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
332 switch (S->getStmtClass()) {
334 case Stmt::InitListExprClass: {
345 for (
Stmt *SubStmt : S->children())
346 childrenBuf.push_back(SubStmt);
349 children = childrenBuf;
367 typedef BlockScopePosPair JumpTarget;
368 typedef BlockScopePosPair JumpSource;
371 std::unique_ptr<CFG> cfg;
375 JumpTarget ContinueJumpTarget;
376 JumpTarget BreakJumpTarget;
382 LocalScope::const_iterator ScopePos;
385 typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
390 typedef std::vector<JumpSource> BackpatchBlocksTy;
391 BackpatchBlocksTy BackpatchBlocks;
394 typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
395 LabelSetTy AddressTakenLabels;
401 bool switchExclusivelyCovered;
404 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
405 const Stmt *lastLookup;
409 typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy;
410 CachedBoolEvalsTy CachedBoolEvals;
416 Block(nullptr), Succ(nullptr),
417 SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
418 TryTerminatedBlock(nullptr), badCFG(
false), BuildOpts(buildOpts),
419 switchExclusivelyCovered(
false), switchCond(nullptr),
420 cachedEntry(nullptr), lastLookup(nullptr) {}
423 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
466 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
486 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
519 struct TempDtorContext {
521 : IsConditional(
false), KnownExecuted(
true), Succ(nullptr),
522 TerminatorExpr(nullptr) {}
524 TempDtorContext(TryResult KnownExecuted)
525 : IsConditional(
true), KnownExecuted(KnownExecuted), Succ(nullptr),
526 TerminatorExpr(nullptr) {}
534 bool needsTempDtorBranch()
const {
535 return IsConditional && !TerminatorExpr;
545 const bool IsConditional;
546 const TryResult KnownExecuted;
553 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
558 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
560 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
563 void InsertTempDtorDecisionBlock(
const TempDtorContext &
Context,
572 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
573 CFGBlock *createBlock(
bool add_successor =
true);
577 return Visit(S, AddStmtChoice::AlwaysAdd);
580 void addAutomaticObjDtors(LocalScope::const_iterator B,
581 LocalScope::const_iterator E,
Stmt *S);
585 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
587 void addLocalScopeForStmt(
Stmt *S);
588 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
589 LocalScope*
Scope =
nullptr);
590 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
592 void addLocalScopeAndDtors(
Stmt *S);
596 if (alwaysAdd(S) && cachedEntry)
597 cachedEntry->second = B;
600 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
601 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
626 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
627 LocalScope::const_iterator B, LocalScope::const_iterator E);
631 cfg->getBumpVectorContext());
638 cfg->getBumpVectorContext());
644 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
649 const Expr *BoolExpr = RHSExpr;
650 bool IntFirst =
true;
660 llvm::APInt IntValue = IntLiteral->
getValue();
661 if ((IntValue == 1) || (IntValue == 0))
665 !IntValue.isNegative();
668 if (Bok == BO_GT || Bok == BO_GE) {
671 return TryResult(IntFirst == IntLarger);
675 return TryResult(IntFirst != IntLarger);
683 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
688 const Expr *BoolExpr = RHSExpr;
699 if (BitOp && (BitOp->
getOpcode() == BO_And ||
712 llvm::APInt L1 = IntLiteral->
getValue();
713 llvm::APInt L2 = IntLiteral2->
getValue();
714 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
715 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
716 if (BuildOpts.Observer)
717 BuildOpts.Observer->compareBitwiseEquality(B,
721 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
722 llvm::APInt IntValue = IntLiteral->
getValue();
723 if ((IntValue == 1) || (IntValue == 0)) {
726 return TryResult(B->
getOpcode() != BO_EQ);
733 const llvm::APSInt &Value1,
734 const llvm::APSInt &Value2) {
735 assert(Value1.isSigned() == Value2.isSigned());
740 return TryResult(Value1 == Value2);
742 return TryResult(Value1 != Value2);
744 return TryResult(Value1 < Value2);
746 return TryResult(Value1 <= Value2);
748 return TryResult(Value1 > Value2);
750 return TryResult(Value1 >= Value2);
767 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
773 std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS);
775 if (!Decl1 || !Expr1)
781 std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS);
783 if (!Decl2 || !Expr2)
792 if (!areExprTypesCompatible(Expr1, Expr2))
802 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
807 const llvm::APSInt Values[] = {
809 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
813 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
818 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
827 bool AlwaysTrue =
true, AlwaysFalse =
true;
828 for (
const llvm::APSInt &
Value : Values) {
829 TryResult Res1, Res2;
830 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
831 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
833 if (!Res1.isKnown() || !Res2.isKnown())
837 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
838 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
840 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
841 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
845 if (AlwaysTrue || AlwaysFalse) {
846 if (BuildOpts.Observer)
847 BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
848 return TryResult(AlwaysTrue);
855 if (!BuildOpts.PruneTriviallyFalseEdges)
864 TryResult tryEvaluateBool(
Expr *S) {
865 if (!BuildOpts.PruneTriviallyFalseEdges ||
870 if (Bop->isLogicalOp()) {
873 if (I != CachedBoolEvals.end())
877 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
882 switch (Bop->getOpcode()) {
891 if (Bop->getLHS()->EvaluateAsInt(IntVal, *
Context)) {
892 if (!IntVal.getBoolValue()) {
893 return TryResult(
false);
896 if (Bop->getRHS()->EvaluateAsInt(IntVal, *
Context)) {
897 if (!IntVal.getBoolValue()) {
898 return TryResult(
false);
907 return evaluateAsBooleanConditionNoCache(S);
911 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
913 if (Bop->isLogicalOp()) {
914 TryResult LHS = tryEvaluateBool(Bop->getLHS());
918 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
921 TryResult RHS = tryEvaluateBool(Bop->getRHS());
923 if (Bop->getOpcode() == BO_LOr)
924 return LHS.isTrue() || RHS.isTrue();
926 return LHS.isTrue() && RHS.isTrue();
929 TryResult RHS = tryEvaluateBool(Bop->getRHS());
933 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
936 TryResult BopRes = checkIncorrectLogicOperator(Bop);
937 if (BopRes.isKnown())
938 return BopRes.isTrue();
943 }
else if (Bop->isEqualityOp()) {
944 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
945 if (BopRes.isKnown())
946 return BopRes.isTrue();
947 }
else if (Bop->isRelationalOp()) {
948 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
949 if (BopRes.isKnown())
950 return BopRes.isTrue();
963 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
965 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
968 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
969 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
971 if (!BuildOpts.forcedBlkExprs)
974 if (lastLookup == stmt) {
976 assert(cachedEntry->first == stmt);
989 assert(!cachedEntry);
994 if (itr == fb->end()) {
995 cachedEntry =
nullptr;
1006 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1008 if (vat->getSizeExpr())
1011 t = vt->getElementType().getTypePtr();
1022 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1030 Succ = createBlock();
1031 assert(Succ == &cfg->getExit());
1034 if (BuildOpts.AddImplicitDtors)
1036 addImplicitDtorsForDestructor(DD);
1046 for (
auto *I : llvm::reverse(CD->inits())) {
1047 B = addInitializer(I);
1059 E = BackpatchBlocks.end(); I !=
E; ++
I ) {
1067 if (LI == LabelMap.end())
continue;
1069 JumpTarget JT = LI->second;
1070 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1072 addSuccessor(B, JT.block);
1076 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1078 E = AddressTakenLabels.end(); I !=
E; ++
I ) {
1085 if (LI == LabelMap.end())
continue;
1087 addSuccessor(B, LI->second.block);
1091 cfg->setEntry(createBlock());
1093 return std::move(cfg);
1098 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1100 if (add_successor && Succ)
1101 addSuccessor(B, Succ);
1108 CFGBlock *CFGBuilder::createNoReturnBlock() {
1111 addSuccessor(B, &cfg->getExit(), Succ);
1117 if (!BuildOpts.AddInitializers)
1120 bool HasTemporaries =
false;
1126 HasTemporaries = isa<ExprWithCleanups>(Init);
1128 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1131 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1137 appendInitializer(Block, I);
1140 if (HasTemporaries) {
1143 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1145 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1151 appendStmt(Block, Default);
1152 if (
Stmt *Child = Default->getExpr())
1174 Init = EWC->getSubExpr();
1180 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1181 Init = MTE->GetTemporaryExpr();
1186 if (
const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
1187 if ((CE->getCastKind() == CK_DerivedToBase ||
1188 CE->getCastKind() == CK_UncheckedDerivedToBase ||
1189 CE->getCastKind() == CK_NoOp) &&
1191 Init = CE->getSubExpr();
1197 if (
const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
1198 if (!ME->isArrow() && ME->getBase()->isRValue()) {
1199 Init = ME->getBase();
1213 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1214 LocalScope::const_iterator E,
Stmt *S) {
1215 if (!BuildOpts.AddImplicitDtors)
1226 Decls.reserve(B.distance(E));
1227 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1228 Decls.push_back(*I);
1238 Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit());
1243 Block = createNoReturnBlock();
1247 appendAutomaticObjDtor(Block, *I, S);
1254 assert (BuildOpts.AddImplicitDtors
1255 &&
"Can be called only when dtors should be added");
1259 for (
const auto &VI : RD->
vbases()) {
1260 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1263 appendBaseDtor(Block, &VI);
1268 for (
const auto &BI : RD->
bases()) {
1269 if (!BI.isVirtual()) {
1270 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1273 appendBaseDtor(Block, &BI);
1279 for (
auto *FI : RD->
fields()) {
1283 if (AT->getSize() == 0)
1285 QT = AT->getElementType();
1291 appendMemberDtor(Block, FI);
1298 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1301 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1302 return new (alloc.Allocate<LocalScope>())
1308 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1309 if (!BuildOpts.AddImplicitDtors)
1312 LocalScope *Scope =
nullptr;
1316 for (
auto *BI : CS->body()) {
1317 Stmt *SI = BI->stripLabelLikeStatements();
1318 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1319 Scope = addLocalScopeForDeclStmt(DS, Scope);
1326 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
1327 addLocalScopeForDeclStmt(DS);
1332 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1333 LocalScope* Scope) {
1334 if (!BuildOpts.AddImplicitDtors)
1337 for (
auto *DI : DS->
decls())
1338 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1339 Scope = addLocalScopeForVarDecl(VD, Scope);
1346 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1347 LocalScope* Scope) {
1348 if (!BuildOpts.AddImplicitDtors)
1357 default:
return Scope;
1374 Init = EWC->getSubExpr();
1375 if (!isa<MaterializeTemporaryExpr>(Init))
1379 QT = getReferenceInitTemporaryType(*Context, Init);
1384 if (AT->getSize() == 0)
1386 QT = AT->getElementType();
1393 Scope = createOrReuseLocalScope(Scope);
1395 ScopePos = Scope->begin();
1402 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1403 if (!BuildOpts.AddImplicitDtors)
1406 LocalScope::const_iterator scopeBeginPos = ScopePos;
1407 addLocalScopeForStmt(S);
1408 addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
1418 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1419 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1423 for (LocalScope::const_iterator I = B; I !=
E; ++
I)
1431 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1437 if (
Expr *E = dyn_cast<Expr>(S))
1438 S = E->IgnoreParens();
1440 switch (S->getStmtClass()) {
1442 return VisitStmt(S, asc);
1444 case Stmt::AddrLabelExprClass:
1445 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
1447 case Stmt::BinaryConditionalOperatorClass:
1448 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
1450 case Stmt::BinaryOperatorClass:
1451 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
1453 case Stmt::BlockExprClass:
1454 return VisitBlockExpr(cast<BlockExpr>(S), asc);
1456 case Stmt::BreakStmtClass:
1457 return VisitBreakStmt(cast<BreakStmt>(S));
1459 case Stmt::CallExprClass:
1460 case Stmt::CXXOperatorCallExprClass:
1461 case Stmt::CXXMemberCallExprClass:
1462 case Stmt::UserDefinedLiteralClass:
1463 return VisitCallExpr(cast<CallExpr>(S), asc);
1465 case Stmt::CaseStmtClass:
1466 return VisitCaseStmt(cast<CaseStmt>(S));
1468 case Stmt::ChooseExprClass:
1469 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
1471 case Stmt::CompoundStmtClass:
1472 return VisitCompoundStmt(cast<CompoundStmt>(S));
1474 case Stmt::ConditionalOperatorClass:
1475 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
1477 case Stmt::ContinueStmtClass:
1478 return VisitContinueStmt(cast<ContinueStmt>(S));
1480 case Stmt::CXXCatchStmtClass:
1481 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
1483 case Stmt::ExprWithCleanupsClass:
1484 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
1486 case Stmt::CXXDefaultArgExprClass:
1487 case Stmt::CXXDefaultInitExprClass:
1497 return VisitStmt(S, asc);
1499 case Stmt::CXXBindTemporaryExprClass:
1500 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
1502 case Stmt::CXXConstructExprClass:
1503 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
1505 case Stmt::CXXNewExprClass:
1506 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
1508 case Stmt::CXXDeleteExprClass:
1509 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
1511 case Stmt::CXXFunctionalCastExprClass:
1512 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
1514 case Stmt::CXXTemporaryObjectExprClass:
1515 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
1517 case Stmt::CXXThrowExprClass:
1518 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
1520 case Stmt::CXXTryStmtClass:
1521 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
1523 case Stmt::CXXForRangeStmtClass:
1524 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
1526 case Stmt::DeclStmtClass:
1527 return VisitDeclStmt(cast<DeclStmt>(S));
1529 case Stmt::DefaultStmtClass:
1530 return VisitDefaultStmt(cast<DefaultStmt>(S));
1532 case Stmt::DoStmtClass:
1533 return VisitDoStmt(cast<DoStmt>(S));
1535 case Stmt::ForStmtClass:
1536 return VisitForStmt(cast<ForStmt>(S));
1538 case Stmt::GotoStmtClass:
1539 return VisitGotoStmt(cast<GotoStmt>(S));
1541 case Stmt::IfStmtClass:
1542 return VisitIfStmt(cast<IfStmt>(S));
1544 case Stmt::ImplicitCastExprClass:
1545 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
1547 case Stmt::IndirectGotoStmtClass:
1548 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
1550 case Stmt::LabelStmtClass:
1551 return VisitLabelStmt(cast<LabelStmt>(S));
1553 case Stmt::LambdaExprClass:
1554 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
1556 case Stmt::MemberExprClass:
1557 return VisitMemberExpr(cast<MemberExpr>(S), asc);
1559 case Stmt::NullStmtClass:
1562 case Stmt::ObjCAtCatchStmtClass:
1563 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
1565 case Stmt::ObjCAutoreleasePoolStmtClass:
1566 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
1568 case Stmt::ObjCAtSynchronizedStmtClass:
1569 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
1571 case Stmt::ObjCAtThrowStmtClass:
1572 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
1574 case Stmt::ObjCAtTryStmtClass:
1575 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
1577 case Stmt::ObjCForCollectionStmtClass:
1578 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
1580 case Stmt::OpaqueValueExprClass:
1583 case Stmt::PseudoObjectExprClass:
1584 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
1586 case Stmt::ReturnStmtClass:
1587 return VisitReturnStmt(cast<ReturnStmt>(S));
1589 case Stmt::UnaryExprOrTypeTraitExprClass:
1590 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1593 case Stmt::StmtExprClass:
1594 return VisitStmtExpr(cast<StmtExpr>(S), asc);
1596 case Stmt::SwitchStmtClass:
1597 return VisitSwitchStmt(cast<SwitchStmt>(S));
1599 case Stmt::UnaryOperatorClass:
1600 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
1602 case Stmt::WhileStmtClass:
1603 return VisitWhileStmt(cast<WhileStmt>(S));
1607 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
1608 if (asc.alwaysAdd(*
this, S)) {
1610 appendStmt(Block, S);
1613 return VisitChildren(S);
1622 reverse_children RChildren(S);
1623 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
1625 if (
Stmt *Child = *I)
1633 AddStmtChoice asc) {
1634 AddressTakenLabels.insert(A->
getLabel());
1636 if (asc.alwaysAdd(*
this, A)) {
1638 appendStmt(Block, A);
1645 AddStmtChoice asc) {
1646 if (asc.alwaysAdd(*
this, U)) {
1648 appendStmt(Block, U);
1651 return Visit(U->
getSubExpr(), AddStmtChoice());
1655 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1656 appendStmt(ConfluenceBlock, B);
1661 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
1662 ConfluenceBlock).first;
1665 std::pair<CFGBlock*, CFGBlock*>
1679 if (B_RHS->isLogicalOp()) {
1680 std::tie(RHSBlock, ExitBlock) =
1681 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
1689 ExitBlock = RHSBlock = createBlock(
false);
1692 assert(TrueBlock == FalseBlock);
1693 addSuccessor(RHSBlock, TrueBlock);
1697 TryResult KnownVal = tryEvaluateBool(RHS);
1698 if (!KnownVal.isKnown())
1699 KnownVal = tryEvaluateBool(B);
1700 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
1701 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
1705 RHSBlock = addStmt(RHS);
1710 return std::make_pair(
nullptr,
nullptr);
1716 if (B_LHS->isLogicalOp()) {
1718 FalseBlock = RHSBlock;
1720 TrueBlock = RHSBlock;
1725 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
1730 CFGBlock *LHSBlock = createBlock(
false);
1734 CFGBlock *EntryLHSBlock = addStmt(LHS);
1737 return std::make_pair(
nullptr,
nullptr);
1740 TryResult KnownVal = tryEvaluateBool(LHS);
1744 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
1745 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
1748 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
1749 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
1752 return std::make_pair(EntryLHSBlock, ExitBlock);
1757 AddStmtChoice asc) {
1760 return VisitLogicalOperator(B);
1764 appendStmt(Block, B);
1766 return addStmt(B->
getLHS());
1770 if (asc.alwaysAdd(*
this, B)) {
1772 appendStmt(Block, B);
1775 return Visit(B->
getRHS());
1778 if (asc.alwaysAdd(*
this, B)) {
1780 appendStmt(Block, B);
1788 return (LBlock ? LBlock : RBlock);
1791 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
1792 if (asc.alwaysAdd(*
this, E)) {
1794 appendStmt(Block, E);
1806 Block = createBlock(
false);
1807 Block->setTerminator(B);
1811 if (BreakJumpTarget.block) {
1812 addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B);
1813 addSuccessor(Block, BreakJumpTarget.block);
1832 Proto->isNothrow(Ctx))
1846 if (!boundType.
isNull()) calleeType = boundType;
1852 bool AddEHEdge =
false;
1856 if (BuildOpts.AddEHEdges)
1862 bool OmitArguments =
false;
1865 if (FD->isNoReturn())
1867 if (FD->hasAttr<NoThrowAttr>())
1869 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
1870 OmitArguments =
true;
1876 if (OmitArguments) {
1877 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
1878 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
1880 appendStmt(Block, C);
1884 if (!NoReturn && !AddEHEdge) {
1885 return VisitStmt(C, asc.withAlwaysAdd(
true));
1895 Block = createNoReturnBlock();
1897 Block = createBlock();
1899 appendStmt(Block, C);
1903 if (TryTerminatedBlock)
1904 addSuccessor(Block, TryTerminatedBlock);
1906 addSuccessor(Block, &cfg->getExit());
1909 return VisitChildren(C);
1913 AddStmtChoice asc) {
1914 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1915 appendStmt(ConfluenceBlock, C);
1919 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
1920 Succ = ConfluenceBlock;
1926 Succ = ConfluenceBlock;
1932 Block = createBlock(
false);
1934 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
1935 addSuccessor(Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
1936 addSuccessor(Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
1937 Block->setTerminator(C);
1943 LocalScope::const_iterator scopeBeginPos = ScopePos;
1944 if (BuildOpts.AddImplicitDtors) {
1945 addLocalScopeForStmt(C);
1950 addAutomaticObjDtors(ScopePos, scopeBeginPos, C);
1959 if (
CFGBlock *newBlock = addStmt(*I))
1960 LastBlock = newBlock;
1970 AddStmtChoice asc) {
1976 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1977 appendStmt(ConfluenceBlock, C);
1981 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
1987 Succ = ConfluenceBlock;
1991 if (trueExpr != opaqueValue) {
1998 LHSBlock = ConfluenceBlock;
2001 Succ = ConfluenceBlock;
2009 if (Cond->isLogicalOp())
2010 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2013 Block = createBlock(
false);
2016 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2017 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2018 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2019 Block->setTerminator(C);
2025 if (condExpr != opaqueValue)
2033 return addStmt(condExpr);
2044 return VisitDeclSubExpr(DS);
2053 unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
2054 ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
2060 void *Mem = cfg->getAllocator().Allocate(
sizeof(
DeclStmt), A);
2062 cfg->addSyntheticDeclStmt(DSNew, DS);
2065 B = VisitDeclSubExpr(DSNew);
2074 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2083 bool HasTemporaries =
false;
2086 CFGBlock *blockAfterStaticInit =
nullptr;
2088 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2097 blockAfterStaticInit = Succ;
2102 Expr *Init = VD->getInit();
2104 HasTemporaries = isa<ExprWithCleanups>(Init);
2106 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2109 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2115 appendStmt(Block, DS);
2123 if (HasTemporaries) {
2128 LastBlock = newBlock;
2131 if (
CFGBlock *newBlock = Visit(Init))
2132 LastBlock = newBlock;
2138 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2139 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2140 LastBlock = newBlock;
2144 if (ScopePos && VD == *ScopePos)
2148 if (blockAfterStaticInit) {
2150 Block = createBlock(
false);
2151 Block->setTerminator(DS);
2152 addSuccessor(Block, blockAfterStaticInit);
2153 addSuccessor(Block, B);
2174 LocalScope::const_iterator BeginScopePos = ScopePos;
2175 addLocalScopeForStmt(Init);
2176 addAutomaticObjDtors(ScopePos, BeginScopePos, I);
2182 LocalScope::const_iterator BeginScopePos = ScopePos;
2183 addLocalScopeForVarDecl(VD);
2184 addAutomaticObjDtors(ScopePos, BeginScopePos, I);
2207 if (!isa<CompoundStmt>(Else))
2208 addLocalScopeAndDtors(Else);
2210 ElseBlock = addStmt(Else);
2213 ElseBlock = sv.get();
2230 if (!isa<CompoundStmt>(Then))
2231 addLocalScopeAndDtors(Then);
2233 ThenBlock = addStmt(Then);
2239 ThenBlock = createBlock(
false);
2240 addSuccessor(ThenBlock, sv.get());
2257 if (Cond->isLogicalOp())
2258 return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2261 Block = createBlock(
false);
2264 Block->setTerminator(I);
2267 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2271 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2272 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2283 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2289 LastBlock = addStmt(Init);
2305 Block = createBlock(
false);
2307 addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
2311 if (!Block->hasNoReturnElement())
2312 addSuccessor(Block, &cfg->getExit());
2316 return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2325 LabelBlock = createBlock();
2327 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
2328 "label already in map");
2329 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
2335 LabelBlock->setLabel(L);
2349 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2351 if (
Expr *CopyExpr = CI.getCopyExpr()) {
2361 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2364 if (
Expr *Init = *it) {
2377 Block = createBlock(
false);
2378 Block->setTerminator(G);
2383 if (I == LabelMap.end())
2385 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
2387 JumpTarget JT = I->second;
2388 addAutomaticObjDtors(ScopePos, JT.scopePosition, G);
2389 addSuccessor(Block, JT.block);
2406 addLocalScopeForStmt(Init);
2407 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2410 addLocalScopeForVarDecl(VD);
2411 LocalScope::const_iterator ContinueScopePos = ScopePos;
2413 addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F);
2420 LoopSuccessor = Block;
2422 LoopSuccessor = Succ;
2427 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2429 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2442 Block = Succ = TransitionBlock = createBlock(
false);
2443 TransitionBlock->setLoopTarget(F);
2453 assert(Block == Succ);
2461 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
2462 ContinueJumpTarget.block->setLoopTarget(F);
2465 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
2469 if (!isa<CompoundStmt>(F->
getBody()))
2470 addLocalScopeAndDtors(F->
getBody());
2474 BodyBlock = addStmt(F->
getBody());
2479 BodyBlock = ContinueJumpTarget.block;
2488 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2496 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
2497 if (Cond->isLogicalOp()) {
2498 std::tie(EntryConditionBlock, ExitConditionBlock) =
2499 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
2504 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
2505 ExitConditionBlock->setTerminator(F);
2508 TryResult KnownVal(
true);
2514 Block = ExitConditionBlock;
2515 EntryConditionBlock = addStmt(C);
2520 if (
Expr *Init = VD->getInit()) {
2523 EntryConditionBlock = addStmt(Init);
2524 assert(Block == EntryConditionBlock);
2528 if (Block && badCFG)
2531 KnownVal = tryEvaluateBool(C);
2535 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2538 addSuccessor(ExitConditionBlock,
2539 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2544 addSuccessor(TransitionBlock, EntryConditionBlock);
2547 Succ = EntryConditionBlock;
2552 Block = createBlock();
2559 Succ = EntryConditionBlock;
2560 return EntryConditionBlock;
2564 if (asc.alwaysAdd(*
this, M)) {
2566 appendStmt(Block, M);
2609 LoopSuccessor = Block;
2612 LoopSuccessor = Succ;
2615 CFGBlock *ExitConditionBlock = createBlock(
false);
2623 appendStmt(ExitConditionBlock, S);
2624 Block = ExitConditionBlock;
2630 AddStmtChoice::NotAlwaysAdd);
2639 Succ = EntryConditionBlock;
2646 save_break(BreakJumpTarget);
2652 Succ = LoopBackBlock = createBlock();
2655 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2656 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
2661 BodyBlock = ContinueJumpTarget.block;
2668 addSuccessor(ExitConditionBlock, BodyBlock);
2673 addSuccessor(ExitConditionBlock, LoopSuccessor);
2676 Block = createBlock();
2704 appendStmt(Block, S);
2719 appendStmt(Block, E);
2731 Semantic = OVE->getSourceExpr();
2749 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2751 addLocalScopeForVarDecl(VD);
2752 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2760 LoopSuccessor = Block;
2763 LoopSuccessor = Succ;
2766 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
2775 save_break(BreakJumpTarget);
2779 Succ = TransitionBlock = createBlock(
false);
2780 TransitionBlock->setLoopTarget(W);
2781 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
2784 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2787 addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2791 if (!isa<CompoundStmt>(W->
getBody()))
2792 addLocalScopeAndDtors(W->
getBody());
2795 BodyBlock = addStmt(W->
getBody());
2798 BodyBlock = ContinueJumpTarget.block;
2799 else if (Block && badCFG)
2806 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
2814 if (Cond->isLogicalOp()) {
2815 std::tie(EntryConditionBlock, ExitConditionBlock) =
2816 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
2821 ExitConditionBlock = createBlock(
false);
2827 Block = ExitConditionBlock;
2828 Block = EntryConditionBlock = addStmt(C);
2833 if (
Expr *Init = VD->getInit()) {
2836 EntryConditionBlock = addStmt(Init);
2837 assert(Block == EntryConditionBlock);
2841 if (Block && badCFG)
2845 const TryResult& KnownVal = tryEvaluateBool(C);
2848 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
2851 addSuccessor(ExitConditionBlock,
2852 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
2857 addSuccessor(TransitionBlock, EntryConditionBlock);
2864 Succ = EntryConditionBlock;
2865 return EntryConditionBlock;
2884 Block = createBlock(
false);
2887 addSuccessor(Block, &cfg->getExit());
2891 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
2900 Block = createBlock(
false);
2902 if (TryTerminatedBlock)
2904 addSuccessor(Block, TryTerminatedBlock);
2907 addSuccessor(Block, &cfg->getExit());
2911 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
2922 LoopSuccessor = Block;
2924 LoopSuccessor = Succ;
2929 CFGBlock *ExitConditionBlock = createBlock(
false);
2930 CFGBlock *EntryConditionBlock = ExitConditionBlock;
2938 Block = ExitConditionBlock;
2939 EntryConditionBlock = addStmt(C);
2947 Succ = EntryConditionBlock;
2950 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
2960 save_break(BreakJumpTarget);
2963 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
2966 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2973 if (!isa<CompoundStmt>(D->
getBody()))
2974 addLocalScopeAndDtors(D->
getBody());
2977 BodyBlock = addStmt(D->
getBody());
2980 BodyBlock = EntryConditionBlock;
2986 if (!KnownVal.isFalse()) {
2994 CFGBlock *LoopBackBlock = createBlock();
2998 addSuccessor(ExitConditionBlock, LoopBackBlock);
3001 addSuccessor(ExitConditionBlock,
nullptr);
3006 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3024 Block = createBlock(
false);
3025 Block->setTerminator(C);
3029 if (ContinueJumpTarget.block) {
3030 addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C);
3031 addSuccessor(Block, ContinueJumpTarget.block);
3039 AddStmtChoice asc) {
3041 if (asc.alwaysAdd(*
this, E)) {
3043 appendStmt(Block, E);
3051 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3052 lastBlock = addStmt(VA->getSizeExpr());
3060 if (asc.alwaysAdd(*
this, SE)) {
3062 appendStmt(Block, SE);
3070 CFGBlock *SwitchSuccessor =
nullptr;
3078 LocalScope::const_iterator BeginScopePos = ScopePos;
3079 addLocalScopeForStmt(Init);
3080 addAutomaticObjDtors(ScopePos, BeginScopePos, Terminator);
3086 LocalScope::const_iterator SwitchBeginScopePos = ScopePos;
3087 addLocalScopeForVarDecl(VD);
3088 addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator);
3094 SwitchSuccessor = Block;
3095 }
else SwitchSuccessor = Succ;
3099 save_default(DefaultCaseBlock);
3105 DefaultCaseBlock = SwitchSuccessor;
3108 SwitchTerminatedBlock = createBlock(
false);
3112 Succ = SwitchSuccessor;
3113 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3118 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3127 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3129 bool b = tryEvaluate(Terminator->
getCond(), result);
3131 b ? &result :
nullptr);
3135 if (!isa<CompoundStmt>(Terminator->
getBody()))
3136 addLocalScopeAndDtors(Terminator->
getBody());
3138 addStmt(Terminator->
getBody());
3150 bool SwitchAlwaysHasSuccessor =
false;
3151 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3154 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3155 !SwitchAlwaysHasSuccessor);
3158 SwitchTerminatedBlock->setTerminator(Terminator);
3159 Block = SwitchTerminatedBlock;
3165 if (
Expr *Init = VD->getInit()) {
3168 LastBlock = addStmt(Init);
3175 LastBlock = addStmt(Init);
3181 static bool shouldAddCase(
bool &switchExclusivelyCovered,
3188 bool addCase =
false;
3190 if (!switchExclusivelyCovered) {
3194 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3196 if (condInt == lhsInt) {
3198 switchExclusivelyCovered =
true;
3200 else if (condInt > lhsInt) {
3204 if (V2 >= condInt) {
3206 switchExclusivelyCovered =
true;
3220 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3226 while (isa<CaseStmt>(Sub)) {
3227 CFGBlock *currentBlock = createBlock(
false);
3231 addSuccessor(LastBlock, currentBlock);
3233 TopBlock = currentBlock;
3235 addSuccessor(SwitchTerminatedBlock,
3236 shouldAddCase(switchExclusivelyCovered, switchCond,
3238 ? currentBlock :
nullptr);
3240 LastBlock = currentBlock;
3241 CS = cast<CaseStmt>(Sub);
3250 CaseBlock = createBlock();
3261 assert(SwitchTerminatedBlock);
3262 addSuccessor(SwitchTerminatedBlock, CaseBlock,
3263 shouldAddCase(switchExclusivelyCovered, switchCond,
3270 addSuccessor(LastBlock, CaseBlock);
3284 DefaultCaseBlock = Block;
3286 if (!DefaultCaseBlock)
3287 DefaultCaseBlock = createBlock();
3291 DefaultCaseBlock->setLabel(Terminator);
3306 Succ = DefaultCaseBlock;
3308 return DefaultCaseBlock;
3319 TrySuccessor = Block;
3320 }
else TrySuccessor = Succ;
3322 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
3325 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3329 bool HasCatchAll =
false;
3332 Succ = TrySuccessor;
3338 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
3343 addSuccessor(NewTryTerminatedBlock, CatchBlock);
3346 if (PrevTryTerminatedBlock)
3347 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
3349 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3353 Succ = TrySuccessor;
3357 cfg->addTryDispatchBlock(TryTerminatedBlock);
3359 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
3375 LocalScope::const_iterator BeginScopePos = ScopePos;
3376 addLocalScopeForVarDecl(VD);
3377 addAutomaticObjDtors(ScopePos, BeginScopePos, CS);
3385 CatchBlock = createBlock();
3391 appendStmt(CatchBlock, CS);
3426 addLocalScopeForStmt(Range);
3428 addLocalScopeForStmt(Begin);
3430 addLocalScopeForStmt(
End);
3431 addAutomaticObjDtors(ScopePos, save_scope_pos.get(),
S);
3433 LocalScope::const_iterator ContinueScopePos = ScopePos;
3441 LoopSuccessor = Block;
3443 LoopSuccessor = Succ;
3448 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3451 CFGBlock *ConditionBlock = createBlock(
false);
3456 Block = ConditionBlock;
3457 CFGBlock *BeginConditionBlock = addStmt(C);
3460 assert(BeginConditionBlock == ConditionBlock &&
3461 "condition block in for-range was unexpectedly complex");
3462 (void)BeginConditionBlock;
3467 Succ = ConditionBlock;
3470 TryResult KnownVal(
true);
3473 KnownVal = tryEvaluateBool(S->
getCond());
3486 Succ = addStmt(S->
getInc());
3489 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3493 ContinueJumpTarget.block->setLoopTarget(S);
3513 addSuccessor(ConditionBlock,
3514 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
3519 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3522 Block = createBlock();
3529 AddStmtChoice asc) {
3530 if (BuildOpts.AddTemporaryDtors) {
3538 asc = asc.withAlwaysAdd(
true);
3544 AddStmtChoice asc) {
3545 if (asc.alwaysAdd(*
this, E)) {
3547 appendStmt(Block, E);
3550 asc = asc.withAlwaysAdd(
false);
3556 AddStmtChoice asc) {
3558 appendStmt(Block, C);
3560 return VisitChildren(C);
3564 AddStmtChoice asc) {
3567 appendStmt(Block, NE);
3571 if (BuildOpts.AddCXXNewAllocator)
3572 appendNewAllocator(Block, NE);
3582 AddStmtChoice asc) {
3584 appendStmt(Block, DE);
3587 CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
3590 appendDeleteDtor(Block, RD, DE);
3593 return VisitChildren(DE);
3597 AddStmtChoice asc) {
3598 if (asc.alwaysAdd(*
this, E)) {
3600 appendStmt(Block, E);
3602 asc = asc.withAlwaysAdd(
false);
3608 AddStmtChoice asc) {
3610 appendStmt(Block, C);
3611 return VisitChildren(C);
3615 AddStmtChoice asc) {
3616 if (asc.alwaysAdd(*
this, E)) {
3618 appendStmt(Block, E);
3620 return Visit(E->
getSubExpr(), AddStmtChoice());
3625 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
3628 IBlock = createBlock(
false);
3629 cfg->setIndirectGotoBlock(IBlock);
3637 Block = createBlock(
false);
3638 Block->setTerminator(I);
3639 addSuccessor(Block, IBlock);
3643 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
3644 TempDtorContext &Context) {
3645 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
3652 switch (E->getStmtClass()) {
3654 return VisitChildrenForTemporaryDtors(E, Context);
3656 case Stmt::BinaryOperatorClass:
3657 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
3660 case Stmt::CXXBindTemporaryExprClass:
3661 return VisitCXXBindTemporaryExprForTemporaryDtors(
3662 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
3664 case Stmt::BinaryConditionalOperatorClass:
3665 case Stmt::ConditionalOperatorClass:
3666 return VisitConditionalOperatorForTemporaryDtors(
3667 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
3669 case Stmt::ImplicitCastExprClass:
3671 E = cast<CastExpr>(
E)->getSubExpr();
3674 case Stmt::CXXFunctionalCastExprClass:
3676 E = cast<CXXFunctionalCastExpr>(
E)->getSubExpr();
3679 case Stmt::ParenExprClass:
3680 E = cast<ParenExpr>(
E)->getSubExpr();
3683 case Stmt::MaterializeTemporaryExprClass: {
3689 E =
const_cast<Expr *
>(
3690 cast<MaterializeTemporaryExpr>(
E)
3691 ->GetTemporaryExpr()
3692 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
3694 for (
const Expr *CommaLHS : CommaLHSs) {
3695 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
3701 case Stmt::BlockExprClass:
3706 case Stmt::LambdaExprClass: {
3709 auto *LE = cast<LambdaExpr>(
E);
3711 for (
Expr *Init : LE->capture_inits()) {
3712 if (
CFGBlock *R = VisitForTemporaryDtors(
3713 Init,
false, Context))
3719 case Stmt::CXXDefaultArgExprClass:
3720 E = cast<CXXDefaultArgExpr>(
E)->getExpr();
3723 case Stmt::CXXDefaultInitExprClass:
3724 E = cast<CXXDefaultInitExpr>(
E)->getExpr();
3729 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
3730 TempDtorContext &Context) {
3731 if (isa<LambdaExpr>(E)) {
3741 for (
Stmt *Child : E->children())
3743 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
3749 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
3753 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
3754 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
3755 RHSExecuted.negate();
3760 TempDtorContext RHSContext(
3761 bothKnownTrue(Context.KnownExecuted, RHSExecuted));
3762 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
3763 InsertTempDtorDecisionBlock(RHSContext);
3773 return LHSBlock ? LHSBlock : RHSBlock;
3781 return RHSBlock ? RHSBlock : LHSBlock;
3784 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
3788 if (!BindToTemporary) {
3800 Block = createNoReturnBlock();
3801 }
else if (Context.needsTempDtorBranch()) {
3805 Block = createBlock();
3809 if (Context.needsTempDtorBranch()) {
3810 Context.setDecisionPoint(Succ, E);
3812 appendTemporaryDtor(Block, E);
3819 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
3821 if (!Context.TerminatorExpr) {
3825 assert(Context.TerminatorExpr);
3826 CFGBlock *Decision = createBlock(
false);
3828 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
3829 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
3830 !Context.KnownExecuted.isTrue());
3834 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
3836 TempDtorContext &Context) {
3840 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
3841 TryResult NegatedVal = ConditionVal;
3842 if (NegatedVal.isKnown()) NegatedVal.negate();
3844 TempDtorContext TrueContext(
3845 bothKnownTrue(Context.KnownExecuted, ConditionVal));
3846 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
3849 Block = ConditionBlock;
3850 Succ = ConditionSucc;
3851 TempDtorContext FalseContext(
3852 bothKnownTrue(Context.KnownExecuted, NegatedVal));
3853 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
3855 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
3856 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
3857 }
else if (TrueContext.TerminatorExpr) {
3859 InsertTempDtorDecisionBlock(TrueContext);
3861 InsertTempDtorDecisionBlock(FalseContext);
3872 bool first_block =
begin() ==
end();
3876 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
3881 Entry = Exit = &
back();
3891 return Builder.buildCFG(D, Statement);
3900 llvm_unreachable(
"getDestructorDecl should only be used with "
3903 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
3912 ty = getReferenceInitTemporaryType(astContext, Init);
3917 ty = arrayType->getElementType();
3921 cast<CXXRecordDecl>(recordType->
getDecl());
3925 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
3934 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
3944 llvm_unreachable(
"getKind() returned bogus value");
3958 : ReachableBlock(IsReachable ? B : nullptr),
3959 UnreachableBlock(!IsReachable ? B : nullptr,
3960 B && IsReachable ? AB_Normal : AB_Unreachable) {}
3963 : ReachableBlock(B),
3964 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
3965 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
3973 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
3989 if (S->isAllEnumCasesCovered()) {
3991 if (!L || !isa<CaseStmt>(L))
4007 typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
4008 typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
4011 signed currentBlock;
4017 : currentBlock(0), currStmt(0), LangOpts(LO)
4022 BI != BEnd; ++BI, ++j ) {
4024 const Stmt *stmt= SE->getStmt();
4025 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
4028 switch (stmt->getStmtClass()) {
4029 case Stmt::DeclStmtClass:
4030 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
4032 case Stmt::IfStmtClass: {
4033 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
4038 case Stmt::ForStmtClass: {
4039 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4044 case Stmt::WhileStmtClass: {
4046 cast<WhileStmt>(
stmt)->getConditionVariable();
4051 case Stmt::SwitchStmtClass: {
4053 cast<SwitchStmt>(
stmt)->getConditionVariable();
4058 case Stmt::CXXCatchStmtClass: {
4060 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
4073 ~StmtPrinterHelper()
override {}
4075 const LangOptions &getLangOpts()
const {
return LangOpts; }
4076 void setBlockID(
signed i) { currentBlock = i; }
4077 void setStmtID(
unsigned i) { currStmt = i; }
4079 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
4082 if (I == StmtMap.end())
4085 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4086 && I->second.second == currStmt) {
4090 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4094 bool handleDecl(
const Decl *D, raw_ostream &OS) {
4097 if (I == DeclMap.end())
4100 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4101 && I->second.second == currStmt) {
4105 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4113 class CFGBlockTerminatorPrint
4114 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4117 StmtPrinterHelper* Helper;
4120 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4122 : OS(os), Helper(helper), Policy(Policy) {
4126 void VisitIfStmt(
IfStmt *I) {
4129 C->printPretty(OS, Helper, Policy);
4133 void VisitStmt(
Stmt *Terminator) {
4134 Terminator->printPretty(OS, Helper, Policy);
4139 OS <<
"static init " << VD->
getName();
4142 void VisitForStmt(
ForStmt *F) {
4148 C->printPretty(OS, Helper, Policy);
4158 C->printPretty(OS, Helper, Policy);
4161 void VisitDoStmt(
DoStmt *D) {
4162 OS <<
"do ... while ";
4164 C->printPretty(OS, Helper, Policy);
4167 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4169 Terminator->
getCond()->printPretty(OS, Helper, Policy);
4178 Cond->printPretty(OS, Helper, Policy);
4179 OS <<
" ? ... : ...";
4183 OS <<
"__builtin_choose_expr( ";
4185 Cond->printPretty(OS, Helper, Policy);
4192 T->printPretty(OS, Helper, Policy);
4202 B->
getLHS()->printPretty(OS, Helper, Policy);
4212 llvm_unreachable(
"Invalid logical operator.");
4216 void VisitExpr(
Expr *E) {
4217 E->printPretty(OS, Helper, Policy);
4223 OS <<
"(Temp Dtor) ";
4229 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
4232 const Stmt *S = CS->getStmt();
4233 assert(S !=
nullptr &&
"Expecting non-null Stmt");
4236 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
4240 if (Children.begin() != Children.end()) {
4251 Helper.handledStmt(B->
getRHS(),OS);
4256 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4258 if (isa<CXXOperatorCallExpr>(S)) {
4259 OS <<
" (OperatorCall)";
4261 else if (isa<CXXBindTemporaryExpr>(S)) {
4262 OS <<
" (BindTemporary)";
4265 OS <<
" (CXXConstructExpr, " << CCE->getType().getAsString() <<
")";
4267 else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
4268 OS <<
" (" << CE->getStmtClassName() <<
", "
4269 << CE->getCastKindName()
4270 <<
", " << CE->getType().getAsString()
4288 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4292 OS <<
" (Base initializer)\n";
4294 OS <<
" (Delegating initializer)\n";
4295 else OS <<
" (Member initializer)\n";
4299 const VarDecl *VD = DE->getVarDecl();
4300 Helper.handleDecl(VD, OS);
4308 OS <<
" (Implicit destructor)\n";
4311 OS <<
"CFGNewAllocator(";
4312 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
4313 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
4321 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
4322 OS <<
"->~" << RD->
getName().str() <<
"()";
4323 OS <<
" (Implicit destructor)\n";
4327 OS <<
" (Base object destructor)\n";
4330 const FieldDecl *FD = ME->getFieldDecl();
4332 OS <<
"this->" << FD->
getName();
4334 OS <<
" (Member object destructor)\n";
4340 OS <<
"() (Temporary object destructor)\n";
4346 StmtPrinterHelper &Helper,
bool print_edges,
4353 OS.changeColor(raw_ostream::YELLOW,
true);
4358 OS <<
" (ENTRY)]\n";
4359 else if (&B == &cfg->
getExit())
4362 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
4364 OS <<
" (NORETURN)]\n";
4377 if (
LabelStmt *L = dyn_cast<LabelStmt>(Label))
4379 else if (
CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
4382 C->
getLHS()->printPretty(OS, &Helper,
4386 C->
getRHS()->printPretty(OS, &Helper,
4389 }
else if (isa<DefaultStmt>(Label))
4391 else if (
CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
4401 llvm_unreachable(
"Invalid label statement in CFGBlock.");
4410 I !=
E ; ++
I, ++j ) {
4416 OS << llvm::format(
"%3d", j) <<
": ";
4418 Helper.setStmtID(j);
4426 OS.changeColor(raw_ostream::GREEN);
4430 Helper.setBlockID(-1);
4433 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
4444 const raw_ostream::Colors Color = raw_ostream::BLUE;
4446 OS.changeColor(Color);
4454 OS.changeColor(Color);
4463 bool Reachable =
true;
4466 B = I->getPossiblyUnreachableBlock();
4471 OS <<
"(Unreachable)";
4482 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
4484 OS.changeColor(Color);
4492 OS.changeColor(Color);
4502 bool Reachable =
true;
4505 B = I->getPossiblyUnreachableBlock();
4511 OS <<
"(Unreachable)";
4528 print(llvm::errs(), LO, ShowColors);
4533 StmtPrinterHelper Helper(
this, LO);
4536 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
4541 if (&(**I) == &getEntry() || &(**I) == &getExit())
4544 print_block(OS,
this, **I, Helper,
true, ShowColors);
4548 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
4555 bool ShowColors)
const {
4556 print(llvm::errs(), cfg, LO, ShowColors);
4567 StmtPrinterHelper Helper(cfg, LO);
4568 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
4575 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
4580 Stmt *Terminator = this->Terminator;
4586 switch (Terminator->getStmtClass()) {
4590 case Stmt::CXXForRangeStmtClass:
4591 E = cast<CXXForRangeStmt>(Terminator)->getCond();
4594 case Stmt::ForStmtClass:
4595 E = cast<ForStmt>(Terminator)->getCond();
4598 case Stmt::WhileStmtClass:
4599 E = cast<WhileStmt>(Terminator)->getCond();
4602 case Stmt::DoStmtClass:
4603 E = cast<DoStmt>(Terminator)->getCond();
4606 case Stmt::IfStmtClass:
4607 E = cast<IfStmt>(Terminator)->getCond();
4610 case Stmt::ChooseExprClass:
4611 E = cast<ChooseExpr>(Terminator)->getCond();
4614 case Stmt::IndirectGotoStmtClass:
4615 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
4618 case Stmt::SwitchStmtClass:
4619 E = cast<SwitchStmt>(Terminator)->getCond();
4622 case Stmt::BinaryConditionalOperatorClass:
4623 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
4626 case Stmt::ConditionalOperatorClass:
4627 E = cast<ConditionalOperator>(Terminator)->getCond();
4630 case Stmt::BinaryOperatorClass:
4631 E = cast<BinaryOperator>(Terminator)->getLHS();
4634 case Stmt::ObjCForCollectionStmtClass:
4655 StmtPrinterHelper H(
this, LO);
4657 llvm::ViewGraph(
this,
"CFG");
4658 GraphHelper =
nullptr;
4671 std::string OutSStr;
4672 llvm::raw_string_ostream Out(OutSStr);
4673 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
4674 std::string& OutStr = Out.str();
4676 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
4679 for (
unsigned i = 0; i != OutStr.length(); ++i)
4680 if (OutStr[i] ==
'\n') {
4682 OutStr.insert(OutStr.begin()+i+1,
'l');
Defines the clang::ASTContext interface.
unsigned getNumInits() const
CFGNewAllocator - Represents C++ allocator call.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
static const VariableArrayType * FindVA(QualType Ty)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
A class which contains all the information about a particular captured value.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
ArrayRef< Capture > captures() const
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
QualType getType() const
Retrieves the type of the base class.
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
std::reverse_iterator< body_iterator > reverse_body_iterator
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
bool isArgumentType() const
IfStmt - This represents an if/then/else.
bool isRecordType() const
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
llvm::BumpPtrAllocator & getAllocator()
The base class of the type hierarchy.
Represents Objective-C's @throw statement.
CFGDeleteDtor - Represents C++ object destructor generated from a call to delete. ...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
const Expr * getInit() const
Represents a call to a C++ constructor.
const Stmt * getElse() const
bool isBlockPointerType() const
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
unsigned IgnoreDefaultsWithCoveredEnums
Represents a C++ constructor within a class.
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFG that outputs to an ostream.
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Expr * getInit() const
Get the initializer.
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
const Expr * getCallee() const
unsigned succ_size() const
Describes how types, statements, expressions, and declarations should be printed. ...
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E)
A C++ throw-expression (C++ [except.throw]).
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
static bool isAssignmentOp(Opcode Opc)
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
LabelStmt - Represents a label, which has a substatement.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void setLoopTarget(const Stmt *loopTarget)
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)
unsigned getNumSemanticExprs() const
bool isReferenceType() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated for automatic object or t...
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
void setTerminator(CFGTerminator Term)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isAnyDestructorNoReturn() const
Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn...
StorageClass getStorageClass() const
Returns the storage class as written in the source.
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
Represents Objective-C's @catch statement.
const CompoundStmt * getSynchBody() const
IndirectGotoStmt - This represents an indirect goto.
Describes an C or C++ initializer list.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
const LangOptions & getLangOpts() const
Expr * getTrueExpr() const
APValue Val
Val - This is the value the expression can be folded to.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Stmt * getHandlerBlock() const
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Expr * getInitializer()
The initializer of this new-expression.
field_range fields() const
unsigned pred_size() const
ElementList::const_iterator const_iterator
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
A builtin binary operation expression such as "x + y" or "x <= y".
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
RecordDecl * getDecl() const
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const DeclStmt * getConditionVariableDeclStmt() const
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
Scope - A scope is a transient data structure that is used while parsing the program.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
detail::InMemoryDirectory::const_iterator I
arg_iterator placement_arg_end()
llvm::APInt getValue() const
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents a prototype with parameter type info, e.g.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
CFGBlock - Represents a single basic block in a source-level CFG.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
bool isFunctionPointerType() const
LabelDecl * getDecl() const
bool isKnownToHaveBooleanValue() const
isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...
QualType getPointeeType() const
Expr - This represents one expression.
Stmt * getTerminatorCondition(bool StripParens=true)
bool isNoReturn(ASTContext &astContext) const
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "while" statement, if any.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Represents a C++ functional cast expression that builds a temporary object.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
Represents Objective-C's @synchronized statement.
CXXTryStmt - A C++ try block, including all handlers.
const SwitchCase * getSwitchCaseList() const
AdjacentBlocks::const_iterator const_pred_iterator
Expr * getSubExpr() const
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
unsigned getBlockID() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
const DeclStmt * getConditionVariableDeclStmt() const
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
const DeclStmt * getConditionVariableDeclStmt() const
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
CFGBaseDtor - Represents C++ object destructor implicitly generated for base object in destructor...
The result type of a method or function.
void viewCFG(const LangOptions &LO) const
ElementList::iterator iterator
DoStmt - This represents a 'do/while' stmt.
LabelDecl * getLabel() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
bool hasNoReturnElement() const
CFGTerminator getTerminator()
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const
EvaluateAsBooleanCondition - Return true if this is a constant which we we can fold and convert to a ...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Encodes a location in the source.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
const TemplateArgument * iterator
Represents a C++ temporary.
FieldDecl * getAnyMember() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
void setLabel(Stmt *Statement)
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
buildCFG - Builds a CFG from an AST.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
const Expr * getCond() const
bool isTemporaryDtorsBranch() const
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
reverse_body_iterator body_rend()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)
decl_iterator decl_begin()
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
reverse_decl_iterator decl_rbegin()
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "switch" statement, if any.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
static QualType findBoundMemberType(const Expr *expr)
Given an expression of bound-member type, find the type of the member.
Expr ** getInits()
Retrieve the set of initializers.
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
static bool isLogicalOp(Opcode Opc)
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
void print(raw_ostream &OS, const CFG *cfg, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFGBlock that outputs to an ostream.
const BlockDecl * getBlockDecl() const
QualType getType() const
Return the type wrapped by this type source info.
AdjacentBlocks::const_iterator const_succ_iterator
const Decl * getSingleDecl() const
QualType getPointeeType() const
AddrLabelExpr - The GNU address of label extension, representing &&label.
ast_type_traits::DynTypedNode Node
void push_back(const_reference Elt, BumpVectorContext &C)
Represents a template argument.
pred_iterator pred_begin()
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "if" statement, if any.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
EvalResult is a struct with detailed info about an evaluated expression.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
const Stmt * getBody() const
ExprIterator arg_iterator
static StmtPrinterHelper * GraphHelper
const Expr * getSynchExpr() const
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
unsigned getNumHandlers() const
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
detail::InMemoryDirectory::const_iterator E
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
This class represents a potential adjacent block in the CFG.
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
const Stmt * getThen() const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
SwitchStmt - This represents a 'switch' stmt.
CFGBlock * getIndirectGotoBlock()
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
const T * getAs() const
Member-template getAs<specific type>'.
Expr * getFalseExpr() const
const Stmt * getSubStmt() const
Represents Objective-C's collection statement.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Represents a C++ base or member initializer.
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
reverse_decl_iterator decl_rend()
Base for LValueReferenceType and RValueReferenceType.
CanQualType BoundMemberTy
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
LabelDecl * getLabel() const
const DeclStmt * getConditionVariableDeclStmt() const
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
Represents a base class of a C++ class.
arg_iterator placement_arg_begin()
DeclStmt * getRangeStmt()
GotoStmt - This represents a direct goto.
A use of a default initializer in a constructor or in aggregate initialization.
unsigned IgnoreNullPredecessors
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
void setHasNoReturnElement()
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Represents a C++ struct/union/class.
BoundNodesTreeBuilder *const Builder
ContinueStmt - This represents a continue.
reverse_body_iterator body_rbegin()
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
CXXCatchStmt - This represents a C++ catch block.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr.type.conv]).
bool operator!=(CanQual< T > x, CanQual< U > y)
WhileStmt - This represents a 'while' stmt.
const Expr * getCond() const
CFGElement - Represents a top-level expression in a basic block.
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
CFGTerminator - Represents CFGBlock terminator statement.
CompoundStmt * getTryBlock()
CFGMemberDtor - Represents C++ object destructor implicitly generated for member object in destructor...
Represents Objective-C's @try ... @catch ... @finally statement.
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Full-expression storage duration (for temporaries).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument for this lambda expression...
VarDecl * getExceptionDecl() const
A reference to a declared variable, function, enum, etc.
std::reverse_iterator< decl_iterator > reverse_decl_iterator
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
BreakStmt - This represents a break.
CFGInitializer - Represents C++ base or member initializer from constructor's initialization list...
Expr * getSemanticExpr(unsigned index)
const Expr * getSubExpr() const
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
Represents a C array with a specified size that is not an integer-constant-expression.
CFGBlock * createBlock()
createBlock - Create a new block in the CFG.
DeclStmt * getBeginStmt()
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const char * getName() const
Represents Objective-C's @autoreleasepool Statement.
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
const CXXDestructorDecl * getDestructor() const
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
CFGTemporaryDtor - Represents C++ object destructor implicitly generated at the end of full expressio...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Defines enum values for all the target-independent builtin functions.
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
QualType getArgumentType() const