39 #include "llvm/ADT/APInt.h" 40 #include "llvm/ADT/APSInt.h" 41 #include "llvm/ADT/ArrayRef.h" 42 #include "llvm/ADT/DenseMap.h" 43 #include "llvm/ADT/Optional.h" 44 #include "llvm/ADT/STLExtras.h" 45 #include "llvm/ADT/SetVector.h" 46 #include "llvm/ADT/SmallPtrSet.h" 47 #include "llvm/ADT/SmallVector.h" 48 #include "llvm/Support/Allocator.h" 49 #include "llvm/Support/Casting.h" 50 #include "llvm/Support/Compiler.h" 51 #include "llvm/Support/DOTGraphTraits.h" 52 #include "llvm/Support/ErrorHandling.h" 53 #include "llvm/Support/Format.h" 54 #include "llvm/Support/GraphWriter.h" 55 #include "llvm/Support/SaveAndRestore.h" 56 #include "llvm/Support/raw_ostream.h" 64 using namespace clang;
67 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
68 if (
Expr *Ex = VD->getInit())
69 return Ex->getSourceRange().getEnd();
77 if (isa<IntegerLiteral>(E))
80 return isa<EnumConstantDecl>(DR->getDecl()) ? DR :
nullptr;
89 static std::tuple<const DeclRefExpr *, BinaryOperatorKind, const Expr *>
96 if (Constant ==
nullptr) {
100 else if (Op == BO_GE)
102 else if (Op == BO_LT)
104 else if (Op == BO_LE)
112 return std::make_tuple(D, Op, Constant);
124 if (isa<IntegerLiteral>(E1) != isa<IntegerLiteral>(E2))
128 if (isa<IntegerLiteral>(E1))
133 assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
134 auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
135 auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
137 assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
141 assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
161 class AddStmtChoice {
163 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
165 AddStmtChoice(
Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
167 bool alwaysAdd(CFGBuilder &builder,
172 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
173 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
203 friend class const_iterator;
209 class const_iterator {
210 const LocalScope*
Scope =
nullptr;
214 unsigned VarIter = 0;
220 const_iterator() =
default;
224 const_iterator(
const LocalScope& S,
unsigned I)
225 : Scope(&S), VarIter(I) {
228 if (VarIter == 0 && Scope)
232 VarDecl *
const* operator->()
const {
233 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
234 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
235 return &Scope->Vars[VarIter - 1];
238 const VarDecl *getFirstVarInScope()
const {
239 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
240 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
241 return Scope->Vars[0];
245 return *this->operator->();
248 const_iterator &operator++() {
252 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
258 const_iterator operator++(
int) {
259 const_iterator
P = *
this;
264 bool operator==(
const const_iterator &rhs)
const {
265 return Scope == rhs.Scope && VarIter == rhs.VarIter;
267 bool operator!=(
const const_iterator &rhs)
const {
268 return !(*
this == rhs);
271 explicit operator bool()
const {
272 return *
this != const_iterator();
276 const_iterator shared_parent(const_iterator L);
277 bool pointsToFirstDeclaredVar() {
return VarIter == 1; }
284 AutomaticVarsTy Vars;
293 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
296 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
299 Vars.push_back(VD, ctx);
310 const_iterator F = *
this;
311 while (F.Scope != L.Scope) {
312 assert(F != const_iterator() &&
313 "L iterator is not reachable from F iterator.");
317 D += F.VarIter - L.VarIter;
325 LocalScope::const_iterator
326 LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
327 llvm::SmallPtrSet<const LocalScope *, 4> ScopesOfL;
329 ScopesOfL.insert(L.Scope);
330 if (L == const_iterator())
335 const_iterator F = *
this;
337 if (ScopesOfL.count(F.Scope))
339 assert(F != const_iterator() &&
340 "L iterator is not reachable from F iterator.");
350 struct BlockScopePosPair {
352 LocalScope::const_iterator scopePosition;
354 BlockScopePosPair() =
default;
355 BlockScopePosPair(
CFGBlock *
b, LocalScope::const_iterator scopePos)
356 : block(b), scopePosition(scopePos) {}
367 TryResult() =
default;
368 TryResult(
bool b) :
X(b ? 1 : 0) {}
370 bool isTrue()
const {
return X == 1; }
371 bool isFalse()
const {
return X == 0; }
372 bool isKnown()
const {
return X >= 0; }
383 if (!R1.isKnown() || !R2.isKnown())
385 return TryResult(R1.isTrue() && R2.isTrue());
390 class reverse_children {
395 reverse_children(
Stmt *S);
399 iterator begin()
const {
return children.rbegin(); }
400 iterator end()
const {
return children.rend(); }
405 reverse_children::reverse_children(
Stmt *S) {
406 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
412 case Stmt::InitListExprClass: {
424 childrenBuf.push_back(SubStmt);
446 using JumpTarget = BlockScopePosPair;
447 using JumpSource = BlockScopePosPair;
450 std::unique_ptr<CFG> cfg;
458 JumpTarget ContinueJumpTarget;
459 JumpTarget BreakJumpTarget;
460 JumpTarget SEHLeaveJumpTarget;
461 CFGBlock *SwitchTerminatedBlock =
nullptr;
462 CFGBlock *DefaultCaseBlock =
nullptr;
466 CFGBlock *TryTerminatedBlock =
nullptr;
469 LocalScope::const_iterator ScopePos;
472 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
477 using BackpatchBlocksTy = std::vector<JumpSource>;
478 BackpatchBlocksTy BackpatchBlocks;
482 LabelSetTy AddressTakenLabels;
487 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
488 ConstructionContextMap;
491 DeclsWithEndedScopeSetTy DeclsWithEndedScope;
497 bool switchExclusivelyCovered =
false;
500 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
501 const Stmt *lastLookup =
nullptr;
505 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
506 CachedBoolEvalsTy CachedBoolEvals;
511 : Context(astContext), cfg(
new CFG()),
512 ConstructionContextMap(), BuildOpts(buildOpts) {}
516 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
561 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
588 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
597 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
598 appendScopeBegin(B, VD, S);
629 struct TempDtorContext {
630 TempDtorContext() =
default;
631 TempDtorContext(TryResult KnownExecuted)
632 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
640 bool needsTempDtorBranch()
const {
641 return IsConditional && !TerminatorExpr;
651 const bool IsConditional =
false;
652 const TryResult KnownExecuted =
true;
659 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
660 TempDtorContext &Context);
661 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *E, TempDtorContext &Context);
663 TempDtorContext &Context);
664 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
666 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
668 TempDtorContext &Context);
669 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
694 template <
typename CallLikeExpr,
695 typename =
typename std::enable_if<
696 std::is_same<CallLikeExpr, CallExpr>::value ||
697 std::is_same<CallLikeExpr, CXXConstructExpr>::value ||
698 std::is_same<CallLikeExpr, ObjCMessageExpr>::value>>
699 void findConstructionContextsForArguments(CallLikeExpr *E) {
700 for (
unsigned i = 0, e = E->getNumArgs();
i != e; ++
i) {
701 Expr *Arg = E->getArg(
i);
703 findConstructionContexts(
713 void cleanupConstructionContext(
Expr *E);
715 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
716 CFGBlock *createBlock(
bool add_successor =
true);
720 return Visit(S, AddStmtChoice::AlwaysAdd);
724 void addLoopExit(
const Stmt *LoopStmt);
725 void addAutomaticObjDtors(LocalScope::const_iterator B,
726 LocalScope::const_iterator E,
Stmt *S);
727 void addLifetimeEnds(LocalScope::const_iterator B,
728 LocalScope::const_iterator E,
Stmt *S);
729 void addAutomaticObjHandling(LocalScope::const_iterator B,
730 LocalScope::const_iterator E,
Stmt *S);
732 void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
735 void getDeclsWithEndedScope(LocalScope::const_iterator B,
736 LocalScope::const_iterator E,
Stmt *S);
739 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
741 void addLocalScopeForStmt(
Stmt *S);
742 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
743 LocalScope* Scope =
nullptr);
744 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope* Scope =
nullptr);
746 void addLocalScopeAndDtors(
Stmt *S);
756 cleanupConstructionContext(E);
764 if (alwaysAdd(S) && cachedEntry)
765 cachedEntry->second = B;
768 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
769 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
774 retrieveAndCleanupConstructionContext(CE)) {
780 B->
appendStmt(CE, cfg->getBumpVectorContext());
784 if (alwaysAdd(CE) && cachedEntry)
785 cachedEntry->second = B;
788 retrieveAndCleanupConstructionContext(CE)) {
794 B->
appendStmt(CE, cfg->getBumpVectorContext());
814 if (alwaysAdd(ME) && cachedEntry)
815 cachedEntry->second = B;
818 retrieveAndCleanupConstructionContext(ME)) {
823 B->
appendStmt(const_cast<ObjCMessageExpr *>(ME),
824 cfg->getBumpVectorContext());
839 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
847 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
848 LocalScope::const_iterator B, LocalScope::const_iterator E);
850 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
851 LocalScope::const_iterator B,
852 LocalScope::const_iterator E);
855 prependAutomaticObjScopeEndWithTerminator(
CFGBlock *Blk,
856 LocalScope::const_iterator B,
857 LocalScope::const_iterator E);
861 cfg->getBumpVectorContext());
868 cfg->getBumpVectorContext());
894 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
899 const Expr *BoolExpr = RHSExpr;
900 bool IntFirst =
true;
910 llvm::APInt IntValue = IntLiteral->
getValue();
911 if ((IntValue == 1) || (IntValue == 0))
915 !IntValue.isNegative();
918 if (Bok == BO_GT || Bok == BO_GE) {
921 return TryResult(IntFirst == IntLarger);
925 return TryResult(IntFirst != IntLarger);
933 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
938 const Expr *BoolExpr = RHSExpr;
949 if (BitOp && (BitOp->
getOpcode() == BO_And ||
962 llvm::APInt L1 = IntLiteral->
getValue();
963 llvm::APInt L2 = IntLiteral2->
getValue();
964 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
965 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
971 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
972 llvm::APInt IntValue = IntLiteral->
getValue();
973 if ((IntValue == 1) || (IntValue == 0)) {
976 return TryResult(B->
getOpcode() != BO_EQ);
983 const llvm::APSInt &Value1,
984 const llvm::APSInt &Value2) {
985 assert(Value1.isSigned() == Value2.isSigned());
990 return TryResult(Value1 == Value2);
992 return TryResult(Value1 != Value2);
994 return TryResult(Value1 < Value2);
996 return TryResult(Value1 <= Value2);
998 return TryResult(Value1 > Value2);
1000 return TryResult(Value1 >= Value2);
1017 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1025 if (!Decl1 || !Expr1)
1033 if (!Decl2 || !Expr2)
1050 llvm::APSInt L1 = L1Result.
Val.
getInt();
1051 llvm::APSInt L2 = L2Result.
Val.
getInt();
1054 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1059 const llvm::APSInt Values[] = {
1061 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1065 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1070 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1079 bool AlwaysTrue =
true, AlwaysFalse =
true;
1080 for (
const llvm::APSInt &
Value : Values) {
1081 TryResult Res1, Res2;
1082 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1083 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1085 if (!Res1.isKnown() || !Res2.isKnown())
1089 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1090 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1092 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1093 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1097 if (AlwaysTrue || AlwaysFalse) {
1100 return TryResult(AlwaysTrue);
1116 TryResult tryEvaluateBool(
Expr *S) {
1122 if (Bop->isLogicalOp()) {
1124 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1125 if (I != CachedBoolEvals.end())
1129 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
1130 CachedBoolEvals[S] =
Result;
1134 switch (Bop->getOpcode()) {
1143 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1144 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1145 if (!IntVal.getBoolValue()) {
1146 return TryResult(
false);
1150 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1151 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1152 if (!IntVal.getBoolValue()) {
1153 return TryResult(
false);
1162 return evaluateAsBooleanConditionNoCache(S);
1166 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1168 if (Bop->isLogicalOp()) {
1169 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1170 if (LHS.isKnown()) {
1173 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1174 return LHS.isTrue();
1176 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1177 if (RHS.isKnown()) {
1178 if (Bop->getOpcode() == BO_LOr)
1179 return LHS.isTrue() || RHS.isTrue();
1181 return LHS.isTrue() && RHS.isTrue();
1184 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1185 if (RHS.isKnown()) {
1188 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1189 return RHS.isTrue();
1191 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1192 if (BopRes.isKnown())
1193 return BopRes.isTrue();
1198 }
else if (Bop->isEqualityOp()) {
1199 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1200 if (BopRes.isKnown())
1201 return BopRes.isTrue();
1202 }
else if (Bop->isRelationalOp()) {
1203 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1204 if (BopRes.isKnown())
1205 return BopRes.isTrue();
1216 bool hasTrivialDestructor(
VarDecl *VD);
1221 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1223 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
1226 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
1227 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1229 if (!BuildOpts.forcedBlkExprs)
1232 if (lastLookup == stmt) {
1234 assert(cachedEntry->first == stmt);
1247 assert(!cachedEntry);
1251 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1252 if (itr == fb->end()) {
1253 cachedEntry =
nullptr;
1257 cachedEntry = &*itr;
1264 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1266 if (vat->getSizeExpr())
1269 t = vt->getElementType().getTypePtr();
1275 void CFGBuilder::consumeConstructionContext(
1277 assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1278 isa<ObjCMessageExpr>(E)) &&
"Expression cannot construct an object!");
1280 ConstructionContextMap.lookup(E)) {
1281 (void)PreviouslyStoredLayer;
1284 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1285 "Already within a different construction context!");
1287 ConstructionContextMap[E] = Layer;
1291 void CFGBuilder::findConstructionContexts(
1293 if (!BuildOpts.AddRichCXXConstructors)
1305 case Stmt::CXXConstructExprClass:
1306 case Stmt::CXXTemporaryObjectExprClass: {
1308 auto *CE = cast<CXXConstructExpr>(Child);
1309 if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
1310 findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
1313 consumeConstructionContext(Layer, CE);
1319 case Stmt::CallExprClass:
1320 case Stmt::CXXMemberCallExprClass:
1321 case Stmt::CXXOperatorCallExprClass:
1322 case Stmt::UserDefinedLiteralClass:
1323 case Stmt::ObjCMessageExprClass: {
1324 auto *E = cast<Expr>(Child);
1326 consumeConstructionContext(Layer, E);
1329 case Stmt::ExprWithCleanupsClass: {
1330 auto *Cleanups = cast<ExprWithCleanups>(Child);
1331 findConstructionContexts(Layer, Cleanups->getSubExpr());
1334 case Stmt::CXXFunctionalCastExprClass: {
1335 auto *Cast = cast<CXXFunctionalCastExpr>(Child);
1336 findConstructionContexts(Layer, Cast->getSubExpr());
1339 case Stmt::ImplicitCastExprClass: {
1340 auto *Cast = cast<ImplicitCastExpr>(Child);
1342 switch (Cast->getCastKind()) {
1344 case CK_ConstructorConversion:
1345 findConstructionContexts(Layer, Cast->getSubExpr());
1352 case Stmt::CXXBindTemporaryExprClass: {
1353 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1354 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1357 case Stmt::MaterializeTemporaryExprClass: {
1364 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1365 findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
1369 case Stmt::ConditionalOperatorClass: {
1370 auto *CO = cast<ConditionalOperator>(Child);
1377 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1381 findConstructionContexts(Layer, CO->getLHS());
1382 findConstructionContexts(Layer, CO->getRHS());
1385 case Stmt::InitListExprClass: {
1386 auto *ILE = cast<InitListExpr>(Child);
1387 if (ILE->isTransparent()) {
1388 findConstructionContexts(Layer, ILE->getInit(0));
1399 void CFGBuilder::cleanupConstructionContext(
Expr *E) {
1400 assert(BuildOpts.AddRichCXXConstructors &&
1401 "We should not be managing construction contexts!");
1402 assert(ConstructionContextMap.count(E) &&
1403 "Cannot exit construction context without the context!");
1404 ConstructionContextMap.erase(E);
1413 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1421 Succ = createBlock();
1422 assert(Succ == &cfg->getExit());
1425 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1426 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1428 if (BuildOpts.AddImplicitDtors)
1430 addImplicitDtorsForDestructor(DD);
1450 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1452 for (
auto *I : llvm::reverse(CD->inits())) {
1453 if (BuildOpts.AddVirtualBaseBranches && !VBaseSucc &&
1454 I->isBaseInitializer() && I->isBaseVirtual()) {
1458 VBaseSucc = Succ = B ? B : &cfg->getExit();
1459 Block = createBlock();
1461 B = addInitializer(I);
1471 addSuccessor(B, Block,
true);
1480 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1481 E = BackpatchBlocks.end(); I != E; ++I ) {
1485 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1488 if (LI == LabelMap.end())
1490 JumpTarget JT = LI->second;
1491 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1493 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1495 const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
1496 B, I->scopePosition, JT.scopePosition);
1497 appendScopeBegin(JT.block, VD, G);
1498 addSuccessor(B, JT.block);
1501 CFGBlock *Successor = (I+1)->block;
1502 for (
auto *L : G->labels()) {
1503 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1506 if (LI == LabelMap.end())
1508 JumpTarget JT = LI->second;
1510 if (JT.block == Successor)
1512 addSuccessor(B, JT.block);
1519 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1520 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1521 E = AddressTakenLabels.end(); I != E; ++I ) {
1523 LabelMapTy::iterator LI = LabelMap.find(*I);
1527 if (LI == LabelMap.end())
continue;
1529 addSuccessor(B, LI->second.block);
1533 cfg->setEntry(createBlock());
1535 if (BuildOpts.AddRichCXXConstructors)
1536 assert(ConstructionContextMap.empty() &&
1537 "Not all construction contexts were cleaned up!");
1539 return std::move(cfg);
1544 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1546 if (add_successor && Succ)
1547 addSuccessor(B, Succ);
1554 CFGBlock *CFGBuilder::createNoReturnBlock() {
1557 addSuccessor(B, &cfg->getExit(), Succ);
1563 if (!BuildOpts.AddInitializers)
1566 bool HasTemporaries =
false;
1572 HasTemporaries = isa<ExprWithCleanups>(Init);
1574 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1576 TempDtorContext Context;
1577 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1583 appendInitializer(Block, I);
1586 findConstructionContexts(
1590 if (HasTemporaries) {
1593 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1595 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1617 bool *FoundMTE =
nullptr) {
1624 Init = EWC->getSubExpr();
1630 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1631 Init = MTE->GetTemporaryExpr();
1640 const Expr *SkippedInit =
1642 if (SkippedInit != Init) {
1655 void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1656 if(!BuildOpts.AddLoopExit)
1659 appendLoopExit(Block, LoopStmt);
1662 void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
1663 LocalScope::const_iterator E,
Stmt *S) {
1664 if (!BuildOpts.AddScopes)
1674 LocalScope::const_iterator
P = B.shared_parent(E);
1675 int Dist = B.distance(P);
1679 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1680 if (I.pointsToFirstDeclaredVar())
1681 DeclsWithEndedScope.insert(*I);
1684 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1685 LocalScope::const_iterator E,
1687 getDeclsWithEndedScope(B, E, S);
1688 if (BuildOpts.AddScopes)
1689 addScopesEnd(B, E, S);
1690 if (BuildOpts.AddImplicitDtors)
1691 addAutomaticObjDtors(B, E, S);
1692 if (BuildOpts.AddLifetime)
1693 addLifetimeEnds(B, E, S);
1697 void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1698 LocalScope::const_iterator E,
Stmt *S) {
1699 if (!BuildOpts.AddLifetime)
1709 LocalScope::const_iterator
P = B.shared_parent(E);
1710 int dist = B.distance(P);
1717 DeclsTrivial.reserve(dist);
1718 DeclsNonTrivial.reserve(dist);
1720 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1721 if (hasTrivialDestructor(*I))
1722 DeclsTrivial.push_back(*I);
1724 DeclsNonTrivial.push_back(*I);
1730 E = DeclsTrivial.rend();
1732 appendLifetimeEnds(Block, *I, S);
1735 I = DeclsNonTrivial.rbegin(),
1736 E = DeclsNonTrivial.rend();
1738 appendLifetimeEnds(Block, *I, S);
1742 void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
1743 LocalScope::const_iterator E,
Stmt *S) {
1746 if (BuildOpts.AddImplicitDtors)
1751 for (
auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend();
1753 appendScopeEnd(Block, *I, S);
1761 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1762 LocalScope::const_iterator E,
Stmt *S) {
1763 if (!BuildOpts.AddImplicitDtors)
1774 Decls.reserve(B.distance(E));
1775 for (LocalScope::const_iterator I = B; I != E; ++I)
1776 Decls.push_back(*I);
1781 if (hasTrivialDestructor(*I)) {
1784 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) {
1786 appendScopeEnd(Block, *I, S);
1799 if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
1800 Block = createNoReturnBlock();
1805 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I))
1806 appendScopeEnd(Block, *I, S);
1807 appendAutomaticObjDtor(Block, *I, S);
1814 assert(BuildOpts.AddImplicitDtors &&
1815 "Can be called only when dtors should be added");
1819 for (
const auto &VI : RD->
vbases()) {
1823 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1826 appendBaseDtor(Block, &VI);
1831 for (
const auto &BI : RD->
bases()) {
1832 if (!BI.isVirtual()) {
1833 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1836 appendBaseDtor(Block, &BI);
1842 for (
auto *FI : RD->
fields()) {
1846 if (AT->getSize() == 0)
1848 QT = AT->getElementType();
1852 if (!CD->hasTrivialDestructor()) {
1854 appendMemberDtor(Block, FI);
1861 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1864 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1865 return new (alloc.Allocate<LocalScope>())
1871 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1872 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1873 !BuildOpts.AddScopes)
1876 LocalScope *Scope =
nullptr;
1880 for (
auto *BI : CS->body()) {
1882 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1883 Scope = addLocalScopeForDeclStmt(DS, Scope);
1891 addLocalScopeForDeclStmt(DS);
1896 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1897 LocalScope* Scope) {
1898 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1899 !BuildOpts.AddScopes)
1902 for (
auto *DI : DS->
decls())
1903 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1904 Scope = addLocalScopeForVarDecl(VD, Scope);
1908 bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
1929 bool FoundMTE =
false;
1937 if (AT->getSize() == 0)
1939 QT = AT->getElementType();
1944 return !CD->hasDefinition() || CD->hasTrivialDestructor();
1951 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1952 LocalScope* Scope) {
1953 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1954 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1955 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1956 !BuildOpts.AddScopes)
1965 default:
return Scope;
1968 if (BuildOpts.AddImplicitDtors) {
1969 if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
1971 Scope = createOrReuseLocalScope(Scope);
1973 ScopePos = Scope->begin();
1978 assert(BuildOpts.AddLifetime);
1980 Scope = createOrReuseLocalScope(Scope);
1982 ScopePos = Scope->begin();
1988 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1989 LocalScope::const_iterator scopeBeginPos = ScopePos;
1990 addLocalScopeForStmt(S);
1991 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2001 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
2002 LocalScope::const_iterator B, LocalScope::const_iterator E) {
2003 if (!BuildOpts.AddImplicitDtors)
2008 for (LocalScope::const_iterator I = B; I != E; ++I)
2018 void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
2019 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2020 if (!BuildOpts.AddLifetime)
2025 for (LocalScope::const_iterator I = B; I != E; ++I) {
2037 CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
2038 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2039 if (!BuildOpts.AddScopes)
2044 LocalScope::const_iterator PlaceToInsert = B;
2045 for (LocalScope::const_iterator I = B; I != E; ++I)
2048 return *PlaceToInsert;
2054 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
2060 if (
Expr *E = dyn_cast<Expr>(S))
2064 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2065 return VisitOMPExecutableDirective(D, asc);
2069 return VisitStmt(S, asc);
2071 case Stmt::AddrLabelExprClass:
2072 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2074 case Stmt::BinaryConditionalOperatorClass:
2075 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2077 case Stmt::BinaryOperatorClass:
2078 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2080 case Stmt::BlockExprClass:
2081 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2083 case Stmt::BreakStmtClass:
2084 return VisitBreakStmt(cast<BreakStmt>(S));
2086 case Stmt::CallExprClass:
2087 case Stmt::CXXOperatorCallExprClass:
2088 case Stmt::CXXMemberCallExprClass:
2089 case Stmt::UserDefinedLiteralClass:
2090 return VisitCallExpr(cast<CallExpr>(S), asc);
2092 case Stmt::CaseStmtClass:
2093 return VisitCaseStmt(cast<CaseStmt>(S));
2095 case Stmt::ChooseExprClass:
2096 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2098 case Stmt::CompoundStmtClass:
2099 return VisitCompoundStmt(cast<CompoundStmt>(S));
2101 case Stmt::ConditionalOperatorClass:
2102 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2104 case Stmt::ContinueStmtClass:
2105 return VisitContinueStmt(cast<ContinueStmt>(S));
2107 case Stmt::CXXCatchStmtClass:
2108 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2110 case Stmt::ExprWithCleanupsClass:
2111 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
2113 case Stmt::CXXDefaultArgExprClass:
2114 case Stmt::CXXDefaultInitExprClass:
2124 return VisitStmt(S, asc);
2126 case Stmt::CXXBindTemporaryExprClass:
2127 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2129 case Stmt::CXXConstructExprClass:
2130 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2132 case Stmt::CXXNewExprClass:
2133 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2135 case Stmt::CXXDeleteExprClass:
2136 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2138 case Stmt::CXXFunctionalCastExprClass:
2139 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2141 case Stmt::CXXTemporaryObjectExprClass:
2142 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2144 case Stmt::CXXThrowExprClass:
2145 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2147 case Stmt::CXXTryStmtClass:
2148 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2150 case Stmt::CXXForRangeStmtClass:
2151 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2153 case Stmt::DeclStmtClass:
2154 return VisitDeclStmt(cast<DeclStmt>(S));
2156 case Stmt::DefaultStmtClass:
2157 return VisitDefaultStmt(cast<DefaultStmt>(S));
2159 case Stmt::DoStmtClass:
2160 return VisitDoStmt(cast<DoStmt>(S));
2162 case Stmt::ForStmtClass:
2163 return VisitForStmt(cast<ForStmt>(S));
2165 case Stmt::GotoStmtClass:
2166 return VisitGotoStmt(cast<GotoStmt>(S));
2168 case Stmt::GCCAsmStmtClass:
2169 return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
2171 case Stmt::IfStmtClass:
2172 return VisitIfStmt(cast<IfStmt>(S));
2174 case Stmt::ImplicitCastExprClass:
2175 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2177 case Stmt::ConstantExprClass:
2178 return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2180 case Stmt::IndirectGotoStmtClass:
2181 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2183 case Stmt::LabelStmtClass:
2184 return VisitLabelStmt(cast<LabelStmt>(S));
2186 case Stmt::LambdaExprClass:
2187 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2189 case Stmt::MaterializeTemporaryExprClass:
2190 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2193 case Stmt::MemberExprClass:
2194 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2196 case Stmt::NullStmtClass:
2199 case Stmt::ObjCAtCatchStmtClass:
2200 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2202 case Stmt::ObjCAutoreleasePoolStmtClass:
2203 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2205 case Stmt::ObjCAtSynchronizedStmtClass:
2206 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2208 case Stmt::ObjCAtThrowStmtClass:
2209 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2211 case Stmt::ObjCAtTryStmtClass:
2212 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2214 case Stmt::ObjCForCollectionStmtClass:
2215 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2217 case Stmt::ObjCMessageExprClass:
2218 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2220 case Stmt::OpaqueValueExprClass:
2223 case Stmt::PseudoObjectExprClass:
2224 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2226 case Stmt::ReturnStmtClass:
2227 case Stmt::CoreturnStmtClass:
2228 return VisitReturnStmt(S);
2230 case Stmt::SEHExceptStmtClass:
2231 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2233 case Stmt::SEHFinallyStmtClass:
2234 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2236 case Stmt::SEHLeaveStmtClass:
2237 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2239 case Stmt::SEHTryStmtClass:
2240 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2242 case Stmt::UnaryExprOrTypeTraitExprClass:
2243 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2246 case Stmt::StmtExprClass:
2247 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2249 case Stmt::SwitchStmtClass:
2250 return VisitSwitchStmt(cast<SwitchStmt>(S));
2252 case Stmt::UnaryOperatorClass:
2253 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2255 case Stmt::WhileStmtClass:
2256 return VisitWhileStmt(cast<WhileStmt>(S));
2260 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2261 if (asc.alwaysAdd(*
this, S)) {
2263 appendStmt(Block, S);
2266 return VisitChildren(S);
2275 reverse_children RChildren(S);
2276 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
2278 if (
Stmt *Child = *I)
2286 AddStmtChoice asc) {
2287 AddressTakenLabels.insert(A->
getLabel());
2289 if (asc.alwaysAdd(*
this, A)) {
2291 appendStmt(Block, A);
2298 AddStmtChoice asc) {
2299 if (asc.alwaysAdd(*
this, U)) {
2301 appendStmt(Block, U);
2304 return Visit(U->
getSubExpr(), AddStmtChoice());
2308 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2309 appendStmt(ConfluenceBlock, B);
2314 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2315 ConfluenceBlock).first;
2318 std::pair<CFGBlock*, CFGBlock*>
2331 if (B_RHS->isLogicalOp()) {
2332 std::tie(RHSBlock, ExitBlock) =
2333 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2341 ExitBlock = RHSBlock = createBlock(
false);
2346 TryResult KnownVal = tryEvaluateBool(RHS);
2347 if (!KnownVal.isKnown())
2348 KnownVal = tryEvaluateBool(B);
2351 assert(TrueBlock == FalseBlock);
2352 addSuccessor(RHSBlock, TrueBlock);
2356 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2357 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2361 RHSBlock = addStmt(RHS);
2366 return std::make_pair(
nullptr,
nullptr);
2372 if (B_LHS->isLogicalOp()) {
2374 FalseBlock = RHSBlock;
2376 TrueBlock = RHSBlock;
2381 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2386 CFGBlock *LHSBlock = createBlock(
false);
2390 CFGBlock *EntryLHSBlock = addStmt(LHS);
2393 return std::make_pair(
nullptr,
nullptr);
2396 TryResult KnownVal = tryEvaluateBool(LHS);
2400 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2401 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2404 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2405 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2408 return std::make_pair(EntryLHSBlock, ExitBlock);
2412 AddStmtChoice asc) {
2415 return VisitLogicalOperator(B);
2419 appendStmt(Block, B);
2421 return addStmt(B->
getLHS());
2425 if (asc.alwaysAdd(*
this, B)) {
2427 appendStmt(Block, B);
2430 return Visit(B->
getRHS());
2433 if (asc.alwaysAdd(*
this, B)) {
2435 appendStmt(Block, B);
2443 return (LBlock ? LBlock : RBlock);
2446 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2447 if (asc.alwaysAdd(*
this, E)) {
2449 appendStmt(Block, E);
2461 Block = createBlock(
false);
2462 Block->setTerminator(B);
2466 if (BreakJumpTarget.block) {
2467 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2468 addSuccessor(Block, BreakJumpTarget.block);
2500 if (!boundType.
isNull()) calleeType = boundType;
2506 bool AddEHEdge =
false;
2510 if (BuildOpts.AddEHEdges)
2516 bool OmitArguments =
false;
2523 if (!FD->isVariadic())
2524 findConstructionContextsForArguments(C);
2528 if (FD->hasAttr<NoThrowAttr>())
2530 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2531 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2532 OmitArguments =
true;
2538 if (OmitArguments) {
2539 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2540 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2542 appendStmt(Block, C);
2546 if (!NoReturn && !AddEHEdge) {
2548 appendCall(Block, C);
2550 return VisitChildren(C);
2560 Block = createNoReturnBlock();
2562 Block = createBlock();
2564 appendCall(Block, C);
2568 if (TryTerminatedBlock)
2569 addSuccessor(Block, TryTerminatedBlock);
2571 addSuccessor(Block, &cfg->getExit());
2574 return VisitChildren(C);
2578 AddStmtChoice asc) {
2579 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2580 appendStmt(ConfluenceBlock, C);
2584 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2585 Succ = ConfluenceBlock;
2591 Succ = ConfluenceBlock;
2597 Block = createBlock(
false);
2599 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2600 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2601 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2602 Block->setTerminator(C);
2607 LocalScope::const_iterator scopeBeginPos = ScopePos;
2608 addLocalScopeForStmt(C);
2613 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2622 if (
CFGBlock *newBlock = addStmt(*I))
2623 LastBlock = newBlock;
2633 AddStmtChoice asc) {
2639 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2640 appendStmt(ConfluenceBlock, C);
2644 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2650 Succ = ConfluenceBlock;
2654 if (trueExpr != opaqueValue) {
2661 LHSBlock = ConfluenceBlock;
2664 Succ = ConfluenceBlock;
2672 if (Cond->isLogicalOp())
2673 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2676 Block = createBlock(
false);
2679 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2680 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2681 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2682 Block->setTerminator(C);
2688 if (condExpr != opaqueValue)
2696 return addStmt(condExpr);
2707 return VisitDeclSubExpr(DS);
2721 cfg->addSyntheticDeclStmt(DSNew, DS);
2724 B = VisitDeclSubExpr(DSNew);
2733 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2742 bool HasTemporaries =
false;
2745 CFGBlock *blockAfterStaticInit =
nullptr;
2747 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2756 blockAfterStaticInit = Succ;
2761 Expr *Init = VD->getInit();
2763 HasTemporaries = isa<ExprWithCleanups>(Init);
2765 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2767 TempDtorContext Context;
2768 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2774 appendStmt(Block, DS);
2776 findConstructionContexts(
2786 if (HasTemporaries) {
2791 LastBlock = newBlock;
2794 if (
CFGBlock *newBlock = Visit(Init))
2795 LastBlock = newBlock;
2801 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2802 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2803 LastBlock = newBlock;
2806 maybeAddScopeBeginForVarDecl(Block, VD, DS);
2809 if (ScopePos && VD == *ScopePos)
2813 if (blockAfterStaticInit) {
2815 Block = createBlock(
false);
2816 Block->setTerminator(DS);
2817 addSuccessor(Block, blockAfterStaticInit);
2818 addSuccessor(Block, B);
2839 addLocalScopeForStmt(Init);
2844 addLocalScopeForVarDecl(VD);
2846 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
2868 if (!isa<CompoundStmt>(Else))
2869 addLocalScopeAndDtors(Else);
2871 ElseBlock = addStmt(Else);
2874 ElseBlock = sv.get();
2891 if (!isa<CompoundStmt>(Then))
2892 addLocalScopeAndDtors(Then);
2894 ThenBlock = addStmt(Then);
2900 ThenBlock = createBlock(
false);
2901 addSuccessor(ThenBlock, sv.get());
2921 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2924 Block = createBlock(
false);
2927 Block->setTerminator(I);
2930 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2934 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2935 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2940 LastBlock = addStmt(I->
getCond());
2946 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2953 LastBlock = addStmt(Init);
2966 assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
2969 Block = createBlock(
false);
2971 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
2973 if (
auto *R = dyn_cast<ReturnStmt>(S))
2974 findConstructionContexts(
2980 if (!Block->hasNoReturnElement())
2981 addSuccessor(Block, &cfg->getExit());
2985 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
2998 if (!SEHExceptBlock)
2999 SEHExceptBlock = createBlock();
3001 appendStmt(SEHExceptBlock, ES);
3004 SEHExceptBlock->setLabel(ES);
3013 return SEHExceptBlock;
3017 return VisitCompoundStmt(FS->
getBlock());
3027 Block = createBlock(
false);
3028 Block->setTerminator(LS);
3032 if (SEHLeaveJumpTarget.block) {
3033 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3034 addSuccessor(Block, SEHLeaveJumpTarget.block);
3044 CFGBlock *SEHTrySuccessor =
nullptr;
3049 SEHTrySuccessor = Block;
3050 }
else SEHTrySuccessor = Succ;
3056 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3059 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3066 Succ = SEHTrySuccessor;
3068 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3073 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3075 if (PrevSEHTryTerminatedBlock)
3076 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3078 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3081 Succ = SEHTrySuccessor;
3085 NewTryTerminatedBlock);
3086 cfg->addTryDispatchBlock(TryTerminatedBlock);
3092 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3094 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3105 LabelBlock = createBlock();
3107 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
3108 "label already in map");
3109 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3115 LabelBlock->setLabel(L);
3129 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3131 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3141 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3144 if (
Expr *Init = *it) {
3157 Block = createBlock(
false);
3158 Block->setTerminator(G);
3161 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3163 if (I == LabelMap.end())
3165 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3167 JumpTarget JT = I->second;
3168 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
3169 addSuccessor(Block, JT.block);
3180 return VisitStmt(G, asc);
3187 Block = createBlock();
3188 Block->setTerminator(G);
3190 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3193 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3208 addLocalScopeForStmt(Init);
3209 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3212 addLocalScopeForVarDecl(VD);
3213 LocalScope::const_iterator ContinueScopePos = ScopePos;
3215 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3224 LoopSuccessor = Block;
3226 LoopSuccessor = Succ;
3231 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3233 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3246 Block = Succ = TransitionBlock = createBlock(
false);
3247 TransitionBlock->setLoopTarget(F);
3257 assert(Block == Succ);
3265 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3266 ContinueJumpTarget.block->setLoopTarget(F);
3269 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3273 if (!isa<CompoundStmt>(F->
getBody()))
3274 addLocalScopeAndDtors(F->
getBody());
3278 BodyBlock = addStmt(F->
getBody());
3283 BodyBlock = ContinueJumpTarget.block;
3292 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3301 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
3302 if (Cond->isLogicalOp()) {
3303 std::tie(EntryConditionBlock, ExitConditionBlock) =
3304 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3309 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3310 ExitConditionBlock->setTerminator(F);
3313 TryResult KnownVal(
true);
3319 Block = ExitConditionBlock;
3320 EntryConditionBlock = addStmt(C);
3329 findConstructionContexts(
3332 appendStmt(Block, DS);
3333 EntryConditionBlock = addStmt(Init);
3334 assert(Block == EntryConditionBlock);
3335 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3339 if (Block && badCFG)
3342 KnownVal = tryEvaluateBool(C);
3346 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3349 addSuccessor(ExitConditionBlock,
3350 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3354 addSuccessor(TransitionBlock, EntryConditionBlock);
3357 Succ = EntryConditionBlock;
3363 ScopePos = LoopBeginScopePos;
3364 Block = createBlock();
3371 Succ = EntryConditionBlock;
3372 return EntryConditionBlock;
3377 AddStmtChoice asc) {
3378 findConstructionContexts(
3382 return VisitStmt(MTE, asc);
3386 if (asc.alwaysAdd(*
this, M)) {
3388 appendStmt(Block, M);
3430 LoopSuccessor = Block;
3433 LoopSuccessor = Succ;
3436 CFGBlock *ExitConditionBlock = createBlock(
false);
3444 appendStmt(ExitConditionBlock, S);
3445 Block = ExitConditionBlock;
3451 AddStmtChoice::NotAlwaysAdd);
3460 Succ = EntryConditionBlock;
3467 save_break(BreakJumpTarget);
3473 Succ = LoopBackBlock = createBlock();
3476 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3477 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3482 BodyBlock = ContinueJumpTarget.block;
3489 addSuccessor(ExitConditionBlock, BodyBlock);
3494 addSuccessor(ExitConditionBlock, LoopSuccessor);
3497 Block = createBlock();
3525 appendStmt(Block, S);
3540 appendStmt(Block, E);
3552 Semantic = OVE->getSourceExpr();
3570 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3572 addLocalScopeForVarDecl(VD);
3573 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3582 LoopSuccessor = Block;
3585 LoopSuccessor = Succ;
3588 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3597 save_break(BreakJumpTarget);
3601 Succ = TransitionBlock = createBlock(
false);
3602 TransitionBlock->setLoopTarget(W);
3603 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3606 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3609 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3613 if (!isa<CompoundStmt>(W->
getBody()))
3614 addLocalScopeAndDtors(W->
getBody());
3617 BodyBlock = addStmt(W->
getBody());
3620 BodyBlock = ContinueJumpTarget.block;
3621 else if (Block && badCFG)
3628 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3636 if (Cond->isLogicalOp()) {
3637 std::tie(EntryConditionBlock, ExitConditionBlock) =
3638 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3643 ExitConditionBlock = createBlock(
false);
3644 ExitConditionBlock->setTerminator(W);
3649 Block = ExitConditionBlock;
3650 Block = EntryConditionBlock = addStmt(C);
3659 findConstructionContexts(
3663 appendStmt(Block, DS);
3664 EntryConditionBlock = addStmt(Init);
3665 assert(Block == EntryConditionBlock);
3666 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3670 if (Block && badCFG)
3674 const TryResult& KnownVal = tryEvaluateBool(C);
3677 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3680 addSuccessor(ExitConditionBlock,
3681 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3685 addSuccessor(TransitionBlock, EntryConditionBlock);
3692 Succ = EntryConditionBlock;
3693 return EntryConditionBlock;
3711 Block = createBlock(
false);
3714 addSuccessor(Block, &cfg->getExit());
3718 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
3722 AddStmtChoice asc) {
3723 findConstructionContextsForArguments(ME);
3726 appendObjCMessage(Block, ME);
3728 return VisitChildren(ME);
3737 Block = createBlock(
false);
3739 if (TryTerminatedBlock)
3741 addSuccessor(Block, TryTerminatedBlock);
3744 addSuccessor(Block, &cfg->getExit());
3748 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
3761 LoopSuccessor = Block;
3763 LoopSuccessor = Succ;
3768 CFGBlock *ExitConditionBlock = createBlock(
false);
3769 CFGBlock *EntryConditionBlock = ExitConditionBlock;
3777 Block = ExitConditionBlock;
3778 EntryConditionBlock = addStmt(C);
3786 Succ = EntryConditionBlock;
3789 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
3799 save_break(BreakJumpTarget);
3802 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
3805 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3812 if (!isa<CompoundStmt>(D->
getBody()))
3813 addLocalScopeAndDtors(D->
getBody());
3816 BodyBlock = addStmt(D->
getBody());
3819 BodyBlock = EntryConditionBlock;
3832 CFGBlock *LoopBackBlock = createBlock();
3835 if (!KnownVal.isFalse())
3837 addSuccessor(ExitConditionBlock, LoopBackBlock);
3839 addSuccessor(ExitConditionBlock,
nullptr);
3844 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3862 Block = createBlock(
false);
3863 Block->setTerminator(C);
3867 if (ContinueJumpTarget.block) {
3868 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
3869 addSuccessor(Block, ContinueJumpTarget.block);
3877 AddStmtChoice asc) {
3878 if (asc.alwaysAdd(*
this, E)) {
3880 appendStmt(Block, E);
3888 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3889 lastBlock = addStmt(VA->getSizeExpr());
3897 if (asc.alwaysAdd(*
this, SE)) {
3899 appendStmt(Block, SE);
3907 CFGBlock *SwitchSuccessor =
nullptr;
3915 addLocalScopeForStmt(Init);
3920 addLocalScopeForVarDecl(VD);
3922 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
3927 SwitchSuccessor = Block;
3928 }
else SwitchSuccessor = Succ;
3932 save_default(DefaultCaseBlock);
3938 DefaultCaseBlock = SwitchSuccessor;
3941 SwitchTerminatedBlock = createBlock(
false);
3945 Succ = SwitchSuccessor;
3946 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3951 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3960 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3964 b ? &result :
nullptr);
3968 if (!isa<CompoundStmt>(Terminator->
getBody()))
3969 addLocalScopeAndDtors(Terminator->
getBody());
3971 addStmt(Terminator->
getBody());
3983 bool SwitchAlwaysHasSuccessor =
false;
3984 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3987 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3988 !SwitchAlwaysHasSuccessor);
3991 SwitchTerminatedBlock->setTerminator(Terminator);
3992 Block = SwitchTerminatedBlock;
4001 LastBlock = addStmt(Init);
4002 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
4009 LastBlock = addStmt(Init);
4022 bool addCase =
false;
4024 if (!switchExclusivelyCovered) {
4028 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4030 if (condInt == lhsInt) {
4032 switchExclusivelyCovered =
true;
4034 else if (condInt > lhsInt) {
4037 const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
4038 if (V2 >= condInt) {
4040 switchExclusivelyCovered =
true;
4054 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4060 while (isa<CaseStmt>(Sub)) {
4061 CFGBlock *currentBlock = createBlock(
false);
4065 addSuccessor(LastBlock, currentBlock);
4067 TopBlock = currentBlock;
4069 addSuccessor(SwitchTerminatedBlock,
4072 ? currentBlock :
nullptr);
4074 LastBlock = currentBlock;
4075 CS = cast<CaseStmt>(Sub);
4084 CaseBlock = createBlock();
4095 assert(SwitchTerminatedBlock);
4096 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4104 addSuccessor(LastBlock, CaseBlock);
4118 DefaultCaseBlock = Block;
4120 if (!DefaultCaseBlock)
4121 DefaultCaseBlock = createBlock();
4125 DefaultCaseBlock->setLabel(Terminator);
4140 Succ = DefaultCaseBlock;
4142 return DefaultCaseBlock;
4153 TrySuccessor = Block;
4154 }
else TrySuccessor = Succ;
4156 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4159 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4163 bool HasCatchAll =
false;
4166 Succ = TrySuccessor;
4172 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4177 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4180 if (PrevTryTerminatedBlock)
4181 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4183 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4187 Succ = TrySuccessor;
4191 cfg->addTryDispatchBlock(TryTerminatedBlock);
4193 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4209 LocalScope::const_iterator BeginScopePos = ScopePos;
4210 addLocalScopeForVarDecl(VD);
4211 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4219 CatchBlock = createBlock();
4225 appendStmt(CatchBlock, CS);
4260 addLocalScopeForStmt(Range);
4262 addLocalScopeForStmt(
Begin);
4264 addLocalScopeForStmt(
End);
4265 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4267 LocalScope::const_iterator ContinueScopePos = ScopePos;
4275 LoopSuccessor = Block;
4277 LoopSuccessor = Succ;
4282 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4285 CFGBlock *ConditionBlock = createBlock(
false);
4290 Block = ConditionBlock;
4291 CFGBlock *BeginConditionBlock = addStmt(C);
4294 assert(BeginConditionBlock == ConditionBlock &&
4295 "condition block in for-range was unexpectedly complex");
4296 (void)BeginConditionBlock;
4301 Succ = ConditionBlock;
4304 TryResult KnownVal(
true);
4307 KnownVal = tryEvaluateBool(S->
getCond());
4320 Succ = addStmt(S->
getInc());
4323 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4327 ContinueJumpTarget.block->setLoopTarget(S);
4347 addSuccessor(ConditionBlock,
4348 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
4353 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4356 Block = createBlock();
4366 AddStmtChoice asc) {
4367 if (BuildOpts.AddTemporaryDtors) {
4370 TempDtorContext Context;
4371 VisitForTemporaryDtors(E->
getSubExpr(),
false, Context);
4375 asc = asc.withAlwaysAdd(
true);
4381 AddStmtChoice asc) {
4382 if (asc.alwaysAdd(*
this, E)) {
4384 appendStmt(Block, E);
4386 findConstructionContexts(
4391 asc = asc.withAlwaysAdd(
false);
4397 AddStmtChoice asc) {
4401 findConstructionContextsForArguments(C);
4404 appendConstructor(Block, C);
4406 return VisitChildren(C);
4410 AddStmtChoice asc) {
4412 appendStmt(Block, NE);
4414 findConstructionContexts(
4421 if (BuildOpts.AddCXXNewAllocator)
4422 appendNewAllocator(Block, NE);
4435 AddStmtChoice asc) {
4437 appendStmt(Block, DE);
4444 appendDeleteDtor(Block, RD, DE);
4448 return VisitChildren(DE);
4452 AddStmtChoice asc) {
4453 if (asc.alwaysAdd(*
this, E)) {
4455 appendStmt(Block, E);
4457 asc = asc.withAlwaysAdd(
false);
4463 AddStmtChoice asc) {
4467 findConstructionContextsForArguments(C);
4470 appendConstructor(Block, C);
4471 return VisitChildren(C);
4475 AddStmtChoice asc) {
4476 if (asc.alwaysAdd(*
this, E)) {
4478 appendStmt(Block, E);
4480 return Visit(E->
getSubExpr(), AddStmtChoice());
4484 return Visit(E->
getSubExpr(), AddStmtChoice());
4489 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4492 IBlock = createBlock(
false);
4493 cfg->setIndirectGotoBlock(IBlock);
4501 Block = createBlock(
false);
4502 Block->setTerminator(I);
4503 addSuccessor(Block, IBlock);
4507 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
4508 TempDtorContext &Context) {
4509 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
4518 return VisitChildrenForTemporaryDtors(E, Context);
4520 case Stmt::BinaryOperatorClass:
4521 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4524 case Stmt::CXXBindTemporaryExprClass:
4525 return VisitCXXBindTemporaryExprForTemporaryDtors(
4526 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
4528 case Stmt::BinaryConditionalOperatorClass:
4529 case Stmt::ConditionalOperatorClass:
4530 return VisitConditionalOperatorForTemporaryDtors(
4531 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
4533 case Stmt::ImplicitCastExprClass:
4535 E = cast<CastExpr>(E)->getSubExpr();
4538 case Stmt::CXXFunctionalCastExprClass:
4540 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4543 case Stmt::ConstantExprClass:
4544 E = cast<ConstantExpr>(E)->getSubExpr();
4547 case Stmt::ParenExprClass:
4548 E = cast<ParenExpr>(E)->getSubExpr();
4551 case Stmt::MaterializeTemporaryExprClass: {
4557 E =
const_cast<Expr *
>(
4558 cast<MaterializeTemporaryExpr>(E)
4559 ->GetTemporaryExpr()
4560 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4562 for (
const Expr *CommaLHS : CommaLHSs) {
4563 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
4569 case Stmt::BlockExprClass:
4574 case Stmt::LambdaExprClass: {
4577 auto *LE = cast<LambdaExpr>(E);
4579 for (
Expr *Init : LE->capture_inits()) {
4581 if (
CFGBlock *R = VisitForTemporaryDtors(
4582 Init,
false, Context))
4589 case Stmt::CXXDefaultArgExprClass:
4590 E = cast<CXXDefaultArgExpr>(E)->getExpr();
4593 case Stmt::CXXDefaultInitExprClass:
4594 E = cast<CXXDefaultInitExpr>(E)->getExpr();
4599 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
4600 TempDtorContext &Context) {
4601 if (isa<LambdaExpr>(E)) {
4613 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
4619 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
4622 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4623 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
4624 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
4625 RHSExecuted.negate();
4630 TempDtorContext RHSContext(
4632 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
4633 InsertTempDtorDecisionBlock(RHSContext);
4641 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4642 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4643 return LHSBlock ? LHSBlock : RHSBlock;
4649 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4650 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4651 return RHSBlock ? RHSBlock : LHSBlock;
4654 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
4658 if (!BindToTemporary) {
4670 Block = createNoReturnBlock();
4671 }
else if (Context.needsTempDtorBranch()) {
4675 Block = createBlock();
4679 if (Context.needsTempDtorBranch()) {
4680 Context.setDecisionPoint(Succ, E);
4682 appendTemporaryDtor(Block, E);
4689 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
4691 if (!Context.TerminatorExpr) {
4695 assert(Context.TerminatorExpr);
4696 CFGBlock *Decision = createBlock(
false);
4699 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
4700 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
4701 !Context.KnownExecuted.isTrue());
4705 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
4707 TempDtorContext &Context) {
4708 VisitForTemporaryDtors(E->
getCond(),
false, Context);
4711 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
4712 TryResult NegatedVal = ConditionVal;
4713 if (NegatedVal.isKnown()) NegatedVal.negate();
4715 TempDtorContext TrueContext(
4717 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
4720 Block = ConditionBlock;
4721 Succ = ConditionSucc;
4722 TempDtorContext FalseContext(
4724 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
4726 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
4727 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
4728 }
else if (TrueContext.TerminatorExpr) {
4730 InsertTempDtorDecisionBlock(TrueContext);
4732 InsertTempDtorDecisionBlock(FalseContext);
4738 AddStmtChoice asc) {
4739 if (asc.alwaysAdd(*
this, D)) {
4741 appendStmt(Block, D);
4751 for (
Stmt *S : llvm::reverse(Used)) {
4752 assert(S &&
"Expected non-null used-in-clause child.");
4759 if (!isa<CompoundStmt>(S))
4760 addLocalScopeAndDtors(S);
4772 bool first_block = begin() == end();
4776 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
4777 Blocks.push_back(Mem, BlkBVC);
4781 Entry = Exit = &back();
4790 CFGBuilder Builder(C, BO);
4791 return Builder.buildCFG(D, Statement);
4803 llvm::SmallPtrSet<const CFGBlock *, 4> Visited;
4806 auto IteratorAndFlag = Visited.insert(B);
4807 if (!IteratorAndFlag.second) {
4813 const CFGBlock *FirstReachableB =
nullptr;
4815 if (!AB.isReachable())
4818 if (FirstReachableB ==
nullptr) {
4819 FirstReachableB = &*AB;
4826 if (!FirstReachableB) {
4832 B = FirstReachableB;
4851 llvm_unreachable(
"getDestructorDecl should only be used with " 4854 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
4872 cast<CXXRecordDecl>(recordType->
getDecl());
4876 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
4885 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
4894 llvm_unreachable(
"getKind() returned bogus value");
4908 : ReachableBlock(IsReachable ? B : nullptr),
4909 UnreachableBlock(!IsReachable ? B : nullptr,
4910 B && IsReachable ? AB_Normal : AB_Unreachable) {}
4913 : ReachableBlock(B),
4914 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
4915 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
4923 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
4925 Succs.push_back(Succ, C);
4938 if (S->isAllEnumCasesCovered()) {
4940 if (!L || !isa<CaseStmt>(L))
4956 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
4957 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
4961 signed currentBlock = 0;
4962 unsigned currStmt = 0;
4971 BI != BEnd; ++BI, ++j ) {
4973 const Stmt *stmt= SE->getStmt();
4974 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
4978 case Stmt::DeclStmtClass:
4979 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
4981 case Stmt::IfStmtClass: {
4982 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
4987 case Stmt::ForStmtClass: {
4988 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4993 case Stmt::WhileStmtClass: {
4995 cast<WhileStmt>(
stmt)->getConditionVariable();
5000 case Stmt::SwitchStmtClass: {
5002 cast<SwitchStmt>(
stmt)->getConditionVariable();
5007 case Stmt::CXXCatchStmtClass: {
5009 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
5022 ~StmtPrinterHelper()
override =
default;
5024 const LangOptions &getLangOpts()
const {
return LangOpts; }
5025 void setBlockID(
signed i) { currentBlock =
i; }
5026 void setStmtID(
unsigned i) { currStmt =
i; }
5028 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
5029 StmtMapTy::iterator I = StmtMap.find(S);
5031 if (I == StmtMap.end())
5034 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5035 && I->second.second == currStmt) {
5039 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5043 bool handleDecl(
const Decl *D, raw_ostream &OS) {
5044 DeclMapTy::iterator I = DeclMap.find(D);
5046 if (I == DeclMap.end())
5049 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5050 && I->second.second == currStmt) {
5054 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5059 class CFGBlockTerminatorPrint
5060 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5062 StmtPrinterHelper* Helper;
5066 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5068 : OS(os), Helper(helper), Policy(Policy) {
5072 void VisitIfStmt(
IfStmt *I) {
5079 void VisitStmt(
Stmt *Terminator) {
5085 OS <<
"static init " << VD->
getName();
5088 void VisitForStmt(
ForStmt *F) {
5107 void VisitDoStmt(
DoStmt *D) {
5108 OS <<
"do ... while ";
5113 void VisitSwitchStmt(
SwitchStmt *Terminator) {
5128 Cond->printPretty(OS, Helper, Policy);
5129 OS <<
" ? ... : ...";
5133 OS <<
"__builtin_choose_expr( ";
5135 Cond->printPretty(OS, Helper, Policy);
5162 llvm_unreachable(
"Invalid logical operator.");
5166 void VisitExpr(
Expr *E) {
5177 OS <<
"(Temp Dtor) ";
5181 OS <<
"(See if most derived ctor has already initialized vbases)";
5199 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5203 OS <<
" (Base initializer)";
5205 OS <<
" (Delegating initializer)";
5207 OS <<
" (Member initializer)";
5211 StmtPrinterHelper &Helper,
5217 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5224 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5226 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5230 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5231 Stmts.push_back(SDSCC->getDeclStmt());
5235 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5236 Stmts.push_back(CDSCC->getDeclStmt());
5237 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5241 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5242 Stmts.push_back(NECC->getCXXNewExpr());
5246 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5247 Stmts.push_back(RSCC->getReturnStmt());
5252 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5253 Stmts.push_back(RSCC->getReturnStmt());
5254 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5258 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5259 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5260 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5264 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5265 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5266 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5267 Stmts.push_back(TOCC->getConstructorAfterElision());
5271 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5272 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5274 Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
5277 Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
5278 OS <<
"+" << ACC->getIndex();
5285 Helper.handledStmt(const_cast<Stmt *>(I), OS);
5289 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5292 const Stmt *S = CS->getStmt();
5293 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5296 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5300 if (Children.begin() != Children.end()) {
5309 if (B->getOpcode() == BO_Comma) {
5311 Helper.handledStmt(B->getRHS(),OS);
5319 if (isa<CXXOperatorCallExpr>(S))
5320 OS <<
" (OperatorCall)";
5321 OS <<
" (CXXRecordTypedCall";
5324 }
else if (isa<CXXOperatorCallExpr>(S)) {
5325 OS <<
" (OperatorCall)";
5326 }
else if (isa<CXXBindTemporaryExpr>(S)) {
5327 OS <<
" (BindTemporary)";
5329 OS <<
" (CXXConstructExpr";
5333 OS <<
", " << CCE->getType().getAsString() <<
")";
5334 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5335 OS <<
" (" << CE->getStmtClassName() <<
", " 5336 << CE->getCastKindName()
5337 <<
", " << CE->getType().getAsString()
5349 const VarDecl *VD = DE->getVarDecl();
5350 Helper.handleDecl(VD, OS);
5360 OS <<
" (Implicit destructor)\n";
5362 const VarDecl *VD = DE->getVarDecl();
5363 Helper.handleDecl(VD, OS);
5365 OS <<
" (Lifetime ends)\n";
5367 const Stmt *LoopStmt = LE->getLoopStmt();
5370 OS <<
"CFGScopeBegin(";
5371 if (
const VarDecl *VD = SB->getVarDecl())
5375 OS <<
"CFGScopeEnd(";
5376 if (
const VarDecl *VD = SE->getVarDecl())
5380 OS <<
"CFGNewAllocator(";
5381 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
5382 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
5390 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
5391 OS <<
"->~" << RD->
getName().str() <<
"()";
5392 OS <<
" (Implicit destructor)\n";
5396 OS <<
" (Base object destructor)\n";
5398 const FieldDecl *FD = ME->getFieldDecl();
5400 OS <<
"this->" << FD->
getName();
5402 OS <<
" (Member object destructor)\n";
5407 OS <<
"() (Temporary object destructor)\n";
5413 StmtPrinterHelper &Helper,
bool print_edges,
5419 OS.changeColor(raw_ostream::YELLOW,
true);
5424 OS <<
" (ENTRY)]\n";
5425 else if (&B == &cfg->
getExit())
5428 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
5430 OS <<
" (NORETURN)]\n";
5454 }
else if (isa<DefaultStmt>(
Label))
5470 llvm_unreachable(
"Invalid label statement in CFGBlock.");
5479 I != E ; ++I, ++j ) {
5484 OS << llvm::format(
"%3d", j) <<
": ";
5486 Helper.setStmtID(j);
5494 OS.changeColor(raw_ostream::GREEN);
5498 Helper.setBlockID(-1);
5501 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
5512 const raw_ostream::Colors Color = raw_ostream::BLUE;
5514 OS.changeColor(Color);
5522 OS.changeColor(Color);
5530 bool Reachable =
true;
5533 B = I->getPossiblyUnreachableBlock();
5538 OS <<
"(Unreachable)";
5549 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
5551 OS.changeColor(Color);
5559 OS.changeColor(Color);
5568 bool Reachable =
true;
5571 B = I->getPossiblyUnreachableBlock();
5577 OS <<
"(Unreachable)";
5593 print(llvm::errs(), LO, ShowColors);
5598 StmtPrinterHelper Helper(
this, LO);
5601 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
5604 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
5606 if (&(**I) == &getEntry() || &(**I) == &getExit())
5609 print_block(OS,
this, **I, Helper,
true, ShowColors);
5613 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
5620 bool ShowColors)
const {
5621 print(llvm::errs(), cfg, LO, ShowColors);
5632 StmtPrinterHelper Helper(cfg, LO);
5633 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
5640 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
5646 bool AddQuotes)
const {
5648 llvm::raw_string_ostream TempOut(Buf);
5670 const Stmt *Cond = StmtElem->getStmt();
5671 if (isa<ObjCForCollectionStmt>(Cond))
5676 return cast<Expr>(Cond)->IgnoreParens();
5690 case Stmt::CXXForRangeStmtClass:
5691 E = cast<CXXForRangeStmt>(Terminator)->getCond();
5694 case Stmt::ForStmtClass:
5695 E = cast<ForStmt>(Terminator)->getCond();
5698 case Stmt::WhileStmtClass:
5699 E = cast<WhileStmt>(Terminator)->getCond();
5702 case Stmt::DoStmtClass:
5703 E = cast<DoStmt>(Terminator)->getCond();
5706 case Stmt::IfStmtClass:
5707 E = cast<IfStmt>(Terminator)->getCond();
5710 case Stmt::ChooseExprClass:
5711 E = cast<ChooseExpr>(Terminator)->getCond();
5714 case Stmt::IndirectGotoStmtClass:
5715 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
5718 case Stmt::SwitchStmtClass:
5719 E = cast<SwitchStmt>(Terminator)->getCond();
5722 case Stmt::BinaryConditionalOperatorClass:
5723 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
5726 case Stmt::ConditionalOperatorClass:
5727 E = cast<ConditionalOperator>(Terminator)->getCond();
5730 case Stmt::BinaryOperatorClass:
5731 E = cast<BinaryOperator>(Terminator)->getLHS();
5734 case Stmt::ObjCForCollectionStmtClass:
5754 StmtPrinterHelper H(
this, LO);
5756 llvm::ViewGraph(
this,
"CFG");
5757 GraphHelper =
nullptr;
5769 std::string OutSStr;
5770 llvm::raw_string_ostream Out(OutSStr);
5771 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
5772 std::string& OutStr = Out.str();
5774 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
5777 for (
unsigned i = 0;
i != OutStr.length(); ++
i)
5778 if (OutStr[
i] ==
'\n') {
5780 OutStr.insert(OutStr.begin()+
i+1,
'l');
unsigned getNumSemanticExprs() const
const Expr * getSubExpr() 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
Represents C++ allocator call.
const CXXDestructorDecl * getDestructor() const
This represents a GCC inline-assembly statement extension.
Represents a function declaration or definition.
static llvm::iterator_range< used_clauses_child_iterator > used_clauses_children(ArrayRef< OMPClause *> Clauses)
Expr * getInit() const
Get the initializer.
CompoundStmt * getBlock() const
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
ArrayRef< OMPClause * > clauses()
static SourceLocation GetEndLoc(Decl *D)
AdjacentBlocks::const_iterator const_pred_iterator
iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr *> &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
ElementList::iterator iterator
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
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.
bool isStandaloneDirective() const
Returns whether or not this is a Standalone directive.
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
IfStmt - This represents an if/then/else.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
C Language Family Type Representation.
void prependScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
unsigned getBlockID() const
Decl - This represents one declaration (or definition), e.g.
Stmt * getHandlerBlock() const
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.
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.
Stmt * getTemporary() const
DOTGraphTraits(bool isSimple=false)
unsigned IgnoreDefaultsWithCoveredEnums
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.
A shortcut around virtual base initializers.
void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
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...
Represents 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.
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const
printTerminatorJson - Pretty-prints the terminator in JSON format.
const Stmt * getSubStmt() const
const char * getStmtClassName() const
Represents a function call that returns a C++ object by value.
LabelStmt - Represents a label, which has a substatement.
const AstTypeMatcher< RecordType > recordType
Matches record types (e.g.
static TryResult bothKnownTrue(TryResult R1, TryResult R2)
const Stmt * getStructuredBlock() const
Returns the AST node representing OpenMP structured-block of this OpenMP executable directive...
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
QualType getPointeeType() const
DeclStmt * getConditionVariableDeclStmt()
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
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
Represents a member of a struct/union/class.
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.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
bool isReferenceType() const
const CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
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...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
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.
Optional< Expr * > getArraySize()
std::string JsonFormat(StringRef RawSR, bool AddQuotes)
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...
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) 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.
static QualType getReferenceInitTemporaryType(const Expr *Init, bool *FoundMTE=nullptr)
Retrieve the type of the temporary object whose lifetime was extended by a local reference with the g...
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.
bool isLinear() const
Returns true if the CFG has no branches.
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.
CaseStmt - Represent a case statement.
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()
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
CFGBlockListTy::const_iterator const_iterator
void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, BumpVectorContext &C)
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)
Represents a single basic block in a source-level CFG.
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool isNoReturn(ASTContext &astContext) const
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...
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
const Expr * getLastCondition() const
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.
VarDecl * getExceptionDecl() const
unsigned getNumInits() const
Represents C++ constructor call.
QualType getArgumentType() const
const CompoundStmt * getSynchBody() const
ElementList::const_iterator const_iterator
Represents Objective-C's @synchronized statement.
CXXTryStmt - A C++ try block, including all handlers.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
std::reverse_iterator< body_iterator > reverse_body_iterator
static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXCtorInitializer *I)
LabelDecl * getLabel() const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
An expression that sends a message to the given Objective-C object or class.
SwitchCase * getSwitchCaseList()
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.
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.
reverse_iterator rbegin()
DoStmt - This represents a 'do/while' stmt.
static const ConstructionContext * createFromLayers(BumpVectorContext &C, const ConstructionContextLayer *TopLayer)
Consume the construction context layer, together with its parent layers, and wrap it up into a comple...
std::reverse_iterator< decl_iterator > reverse_decl_iterator
RecordDecl * getDecl() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
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.
Construction context can be seen as a linked list of multiple layers.
Encodes a location in the source.
unsigned getNumHandlers() const
Expr * getSubExpr() const
Represents a C++ temporary.
This is a basic class for representing single OpenMP executable directive.
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)
Builds a CFG from an AST.
ASTContext & getASTContext() const LLVM_READONLY
iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S)
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.
A branch in control flow of destructors of temporaries.
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 bool isCXXRecordTypedCall(Expr *E)
Returns true when call expression CE needs to be represented by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
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.
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
static bool isLogicalOp(Opcode Opc)
static const Expr * tryTransformToIntOrEnumConstant(const Expr *E)
Helper for tryNormalizeBinaryOperator.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
DeclStmt * getConditionVariableDeclStmt()
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
bool isArgumentType() const
Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...
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.
Dataflow Directional Tag Classes.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
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)
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
static const VariableArrayType * FindVA(const Type *t)
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
const Expr * getInit() const
unsigned pred_size() const
A branch that corresponds to a statement in the code, such as an if-statement.
StmtClass getStmtClass() const
static StmtPrinterHelper * GraphHelper
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
const CXXRecordDecl * getParent() const
Return 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)
Stmt * getTerminatorStmt()
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.
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
Represents a single point (AST node) in the program that requires attention during construction of an...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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...
Iterator for iterating over Stmt * arrays that contain only T *.
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()
const ConstructionContextItem & getItem() const
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S)
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
static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC)
static const ConstructionContextLayer * create(BumpVectorContext &C, const ConstructionContextItem &Item, const ConstructionContextLayer *Parent=nullptr)
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).
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\, const ASTContext *Context=nullptr) const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
void viewCFG(const LangOptions &LO) const
Defines the clang::SourceLocation class and associated facilities.
ConstructionContext's subclasses describe different ways of constructing an object in C++...
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.
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.
Represents CFGBlock terminator statement.
CompoundStmt * getTryBlock()
bool AddRichCXXConstructors
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)
bool isBuiltinAssumeFalse(const ASTContext &Ctx) const
Return true if this is a call to __assume() or __builtin_assume() with a non-value-dependent constant...
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getQualifiedNameAsString() const
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.
Represents C++ base or member initializer from constructor's initialization list. ...
Expr * getSemanticExpr(unsigned index)
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
Represents a C array with a specified size that is not an integer-constant-expression.
CFGBlock * createBlock()
Create a new block in the CFG.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
CFGTerminator getTerminator() const
DeclStmt * getBeginStmt()
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
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
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
Skip past any parentheses which might surround this expression until reaching a fixed point...
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt...
QualType getType() const
Retrieves the type of the base class.
Represents the point where a loop ends.