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);
559 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
586 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
593 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
594 appendScopeBegin(B, VD, S);
625 struct TempDtorContext {
626 TempDtorContext() =
default;
627 TempDtorContext(TryResult KnownExecuted)
628 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
636 bool needsTempDtorBranch()
const {
637 return IsConditional && !TerminatorExpr;
647 const bool IsConditional =
false;
648 const TryResult KnownExecuted =
true;
655 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
656 TempDtorContext &Context);
657 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *E, TempDtorContext &Context);
659 TempDtorContext &Context);
660 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
662 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
664 TempDtorContext &Context);
665 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
690 template <
typename CallLikeExpr,
691 typename =
typename std::enable_if<
692 std::is_same<CallLikeExpr, CallExpr>::value ||
693 std::is_same<CallLikeExpr, CXXConstructExpr>::value ||
694 std::is_same<CallLikeExpr, ObjCMessageExpr>::value>>
695 void findConstructionContextsForArguments(CallLikeExpr *E) {
696 for (
unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
697 Expr *Arg = E->getArg(i);
699 findConstructionContexts(
709 void cleanupConstructionContext(
Expr *E);
711 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
712 CFGBlock *createBlock(
bool add_successor =
true);
716 return Visit(S, AddStmtChoice::AlwaysAdd);
720 void addLoopExit(
const Stmt *LoopStmt);
721 void addAutomaticObjDtors(LocalScope::const_iterator B,
722 LocalScope::const_iterator E,
Stmt *S);
723 void addLifetimeEnds(LocalScope::const_iterator B,
724 LocalScope::const_iterator E,
Stmt *S);
725 void addAutomaticObjHandling(LocalScope::const_iterator B,
726 LocalScope::const_iterator E,
Stmt *S);
728 void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
731 void getDeclsWithEndedScope(LocalScope::const_iterator B,
732 LocalScope::const_iterator E,
Stmt *S);
735 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
737 void addLocalScopeForStmt(
Stmt *S);
738 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
739 LocalScope* Scope =
nullptr);
740 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope* Scope =
nullptr);
742 void addLocalScopeAndDtors(
Stmt *S);
752 cleanupConstructionContext(E);
760 if (alwaysAdd(S) && cachedEntry)
761 cachedEntry->second = B;
764 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
765 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
770 retrieveAndCleanupConstructionContext(CE)) {
776 B->
appendStmt(CE, cfg->getBumpVectorContext());
780 if (alwaysAdd(CE) && cachedEntry)
781 cachedEntry->second = B;
784 retrieveAndCleanupConstructionContext(CE)) {
790 B->
appendStmt(CE, cfg->getBumpVectorContext());
810 if (alwaysAdd(ME) && cachedEntry)
811 cachedEntry->second = B;
814 retrieveAndCleanupConstructionContext(ME)) {
819 B->
appendStmt(const_cast<ObjCMessageExpr *>(ME),
820 cfg->getBumpVectorContext());
835 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
843 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
844 LocalScope::const_iterator B, LocalScope::const_iterator E);
846 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
847 LocalScope::const_iterator B,
848 LocalScope::const_iterator E);
851 prependAutomaticObjScopeEndWithTerminator(
CFGBlock *Blk,
852 LocalScope::const_iterator B,
853 LocalScope::const_iterator E);
857 cfg->getBumpVectorContext());
864 cfg->getBumpVectorContext());
890 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
895 const Expr *BoolExpr = RHSExpr;
896 bool IntFirst =
true;
906 llvm::APInt IntValue = IntLiteral->
getValue();
907 if ((IntValue == 1) || (IntValue == 0))
911 !IntValue.isNegative();
914 if (Bok == BO_GT || Bok == BO_GE) {
917 return TryResult(IntFirst == IntLarger);
921 return TryResult(IntFirst != IntLarger);
929 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
934 const Expr *BoolExpr = RHSExpr;
945 if (BitOp && (BitOp->
getOpcode() == BO_And ||
958 llvm::APInt L1 = IntLiteral->
getValue();
959 llvm::APInt L2 = IntLiteral2->
getValue();
960 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
961 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
967 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
968 llvm::APInt IntValue = IntLiteral->
getValue();
969 if ((IntValue == 1) || (IntValue == 0)) {
972 return TryResult(B->
getOpcode() != BO_EQ);
979 const llvm::APSInt &Value1,
980 const llvm::APSInt &Value2) {
981 assert(Value1.isSigned() == Value2.isSigned());
986 return TryResult(Value1 == Value2);
988 return TryResult(Value1 != Value2);
990 return TryResult(Value1 < Value2);
992 return TryResult(Value1 <= Value2);
994 return TryResult(Value1 > Value2);
996 return TryResult(Value1 >= Value2);
1013 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1021 if (!Decl1 || !Expr1)
1029 if (!Decl2 || !Expr2)
1041 llvm::APSInt L1, L2;
1048 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1053 const llvm::APSInt Values[] = {
1055 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1059 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1064 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1073 bool AlwaysTrue =
true, AlwaysFalse =
true;
1074 for (
const llvm::APSInt &
Value : Values) {
1075 TryResult Res1, Res2;
1076 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1077 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1079 if (!Res1.isKnown() || !Res2.isKnown())
1083 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1084 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1086 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1087 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1091 if (AlwaysTrue || AlwaysFalse) {
1094 return TryResult(AlwaysTrue);
1110 TryResult tryEvaluateBool(
Expr *S) {
1116 if (Bop->isLogicalOp()) {
1118 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1119 if (I != CachedBoolEvals.end())
1123 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
1124 CachedBoolEvals[S] =
Result;
1128 switch (Bop->getOpcode()) {
1136 llvm::APSInt IntVal;
1137 if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) {
1138 if (!IntVal.getBoolValue()) {
1139 return TryResult(
false);
1142 if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) {
1143 if (!IntVal.getBoolValue()) {
1144 return TryResult(
false);
1153 return evaluateAsBooleanConditionNoCache(S);
1157 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1159 if (Bop->isLogicalOp()) {
1160 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1161 if (LHS.isKnown()) {
1164 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1165 return LHS.isTrue();
1167 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1168 if (RHS.isKnown()) {
1169 if (Bop->getOpcode() == BO_LOr)
1170 return LHS.isTrue() || RHS.isTrue();
1172 return LHS.isTrue() && RHS.isTrue();
1175 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1176 if (RHS.isKnown()) {
1179 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1180 return RHS.isTrue();
1182 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1183 if (BopRes.isKnown())
1184 return BopRes.isTrue();
1189 }
else if (Bop->isEqualityOp()) {
1190 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1191 if (BopRes.isKnown())
1192 return BopRes.isTrue();
1193 }
else if (Bop->isRelationalOp()) {
1194 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1195 if (BopRes.isKnown())
1196 return BopRes.isTrue();
1207 bool hasTrivialDestructor(
VarDecl *VD);
1212 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1214 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
1217 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
1218 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1220 if (!BuildOpts.forcedBlkExprs)
1223 if (lastLookup == stmt) {
1225 assert(cachedEntry->first == stmt);
1238 assert(!cachedEntry);
1242 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1243 if (itr == fb->end()) {
1244 cachedEntry =
nullptr;
1248 cachedEntry = &*itr;
1255 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1257 if (vat->getSizeExpr())
1260 t = vt->getElementType().getTypePtr();
1266 void CFGBuilder::consumeConstructionContext(
1268 assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1269 isa<ObjCMessageExpr>(E)) &&
"Expression cannot construct an object!");
1271 ConstructionContextMap.lookup(E)) {
1272 (void)PreviouslyStoredLayer;
1275 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1276 "Already within a different construction context!");
1278 ConstructionContextMap[E] = Layer;
1282 void CFGBuilder::findConstructionContexts(
1284 if (!BuildOpts.AddRichCXXConstructors)
1296 case Stmt::CXXConstructExprClass:
1297 case Stmt::CXXTemporaryObjectExprClass: {
1299 auto *CE = cast<CXXConstructExpr>(Child);
1300 if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
1301 findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
1304 consumeConstructionContext(Layer, CE);
1310 case Stmt::CallExprClass:
1311 case Stmt::CXXMemberCallExprClass:
1312 case Stmt::CXXOperatorCallExprClass:
1313 case Stmt::UserDefinedLiteralClass:
1314 case Stmt::ObjCMessageExprClass: {
1315 auto *E = cast<Expr>(Child);
1317 consumeConstructionContext(Layer, E);
1320 case Stmt::ExprWithCleanupsClass: {
1321 auto *Cleanups = cast<ExprWithCleanups>(Child);
1322 findConstructionContexts(Layer, Cleanups->getSubExpr());
1325 case Stmt::CXXFunctionalCastExprClass: {
1326 auto *Cast = cast<CXXFunctionalCastExpr>(Child);
1327 findConstructionContexts(Layer, Cast->getSubExpr());
1330 case Stmt::ImplicitCastExprClass: {
1331 auto *Cast = cast<ImplicitCastExpr>(Child);
1333 switch (Cast->getCastKind()) {
1335 case CK_ConstructorConversion:
1336 findConstructionContexts(Layer, Cast->getSubExpr());
1342 case Stmt::CXXBindTemporaryExprClass: {
1343 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1344 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1347 case Stmt::MaterializeTemporaryExprClass: {
1354 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1355 findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
1359 case Stmt::ConditionalOperatorClass: {
1360 auto *CO = cast<ConditionalOperator>(Child);
1367 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1371 findConstructionContexts(Layer, CO->getLHS());
1372 findConstructionContexts(Layer, CO->getRHS());
1380 void CFGBuilder::cleanupConstructionContext(
Expr *E) {
1381 assert(BuildOpts.AddRichCXXConstructors &&
1382 "We should not be managing construction contexts!");
1383 assert(ConstructionContextMap.count(E) &&
1384 "Cannot exit construction context without the context!");
1385 ConstructionContextMap.erase(E);
1394 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1402 Succ = createBlock();
1403 assert(Succ == &cfg->getExit());
1406 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1407 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1409 if (BuildOpts.AddImplicitDtors)
1411 addImplicitDtorsForDestructor(DD);
1421 for (
auto *I : llvm::reverse(CD->inits())) {
1422 B = addInitializer(I);
1433 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1434 E = BackpatchBlocks.end(); I != E; ++I ) {
1438 LabelMapTy::iterator LI = LabelMap.find(G->
getLabel());
1442 if (LI == LabelMap.end())
continue;
1444 JumpTarget JT = LI->second;
1445 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1447 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1449 const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
1450 B, I->scopePosition, JT.scopePosition);
1451 appendScopeBegin(JT.block, VD, G);
1452 addSuccessor(B, JT.block);
1456 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1457 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1458 E = AddressTakenLabels.end(); I != E; ++I ) {
1460 LabelMapTy::iterator LI = LabelMap.find(*I);
1464 if (LI == LabelMap.end())
continue;
1466 addSuccessor(B, LI->second.block);
1470 cfg->setEntry(createBlock());
1472 if (BuildOpts.AddRichCXXConstructors)
1473 assert(ConstructionContextMap.empty() &&
1474 "Not all construction contexts were cleaned up!");
1476 return std::move(cfg);
1481 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1483 if (add_successor && Succ)
1484 addSuccessor(B, Succ);
1491 CFGBlock *CFGBuilder::createNoReturnBlock() {
1494 addSuccessor(B, &cfg->getExit(), Succ);
1500 if (!BuildOpts.AddInitializers)
1503 bool HasTemporaries =
false;
1509 HasTemporaries = isa<ExprWithCleanups>(Init);
1511 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1513 TempDtorContext Context;
1514 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1520 appendInitializer(Block, I);
1523 findConstructionContexts(
1527 if (HasTemporaries) {
1530 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1532 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1554 bool *FoundMTE =
nullptr) {
1561 Init = EWC->getSubExpr();
1567 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1568 Init = MTE->GetTemporaryExpr();
1577 const Expr *SkippedInit =
1579 if (SkippedInit != Init) {
1592 void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1593 if(!BuildOpts.AddLoopExit)
1596 appendLoopExit(Block, LoopStmt);
1599 void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
1600 LocalScope::const_iterator E,
Stmt *S) {
1601 if (!BuildOpts.AddScopes)
1611 LocalScope::const_iterator
P = B.shared_parent(E);
1612 int Dist = B.distance(P);
1616 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1617 if (I.pointsToFirstDeclaredVar())
1618 DeclsWithEndedScope.insert(*I);
1621 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1622 LocalScope::const_iterator E,
1624 getDeclsWithEndedScope(B, E, S);
1625 if (BuildOpts.AddScopes)
1626 addScopesEnd(B, E, S);
1627 if (BuildOpts.AddImplicitDtors)
1628 addAutomaticObjDtors(B, E, S);
1629 if (BuildOpts.AddLifetime)
1630 addLifetimeEnds(B, E, S);
1634 void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1635 LocalScope::const_iterator E,
Stmt *S) {
1636 if (!BuildOpts.AddLifetime)
1646 LocalScope::const_iterator
P = B.shared_parent(E);
1647 int dist = B.distance(P);
1654 DeclsTrivial.reserve(dist);
1655 DeclsNonTrivial.reserve(dist);
1657 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1658 if (hasTrivialDestructor(*I))
1659 DeclsTrivial.push_back(*I);
1661 DeclsNonTrivial.push_back(*I);
1667 E = DeclsTrivial.rend();
1669 appendLifetimeEnds(Block, *I, S);
1672 I = DeclsNonTrivial.rbegin(),
1673 E = DeclsNonTrivial.rend();
1675 appendLifetimeEnds(Block, *I, S);
1679 void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
1680 LocalScope::const_iterator E,
Stmt *S) {
1683 if (BuildOpts.AddImplicitDtors)
1688 for (
auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend();
1690 appendScopeEnd(Block, *I, S);
1698 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1699 LocalScope::const_iterator E,
Stmt *S) {
1700 if (!BuildOpts.AddImplicitDtors)
1711 Decls.reserve(B.distance(E));
1712 for (LocalScope::const_iterator I = B; I != E; ++I)
1713 Decls.push_back(*I);
1718 if (hasTrivialDestructor(*I)) {
1721 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) {
1723 appendScopeEnd(Block, *I, S);
1736 if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
1737 Block = createNoReturnBlock();
1742 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I))
1743 appendScopeEnd(Block, *I, S);
1744 appendAutomaticObjDtor(Block, *I, S);
1751 assert(BuildOpts.AddImplicitDtors &&
1752 "Can be called only when dtors should be added");
1756 for (
const auto &VI : RD->
vbases()) {
1757 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1760 appendBaseDtor(Block, &VI);
1765 for (
const auto &BI : RD->
bases()) {
1766 if (!BI.isVirtual()) {
1767 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1770 appendBaseDtor(Block, &BI);
1776 for (
auto *FI : RD->
fields()) {
1780 if (AT->getSize() == 0)
1782 QT = AT->getElementType();
1786 if (!CD->hasTrivialDestructor()) {
1788 appendMemberDtor(Block, FI);
1795 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1798 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1799 return new (alloc.Allocate<LocalScope>())
1805 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1806 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1807 !BuildOpts.AddScopes)
1810 LocalScope *Scope =
nullptr;
1814 for (
auto *BI : CS->body()) {
1816 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1817 Scope = addLocalScopeForDeclStmt(DS, Scope);
1825 addLocalScopeForDeclStmt(DS);
1830 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1831 LocalScope* Scope) {
1832 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1833 !BuildOpts.AddScopes)
1836 for (
auto *DI : DS->
decls())
1837 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1838 Scope = addLocalScopeForVarDecl(VD, Scope);
1842 bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
1863 bool FoundMTE =
false;
1871 if (AT->getSize() == 0)
1873 QT = AT->getElementType();
1878 return !CD->hasDefinition() || CD->hasTrivialDestructor();
1885 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1886 LocalScope* Scope) {
1887 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1888 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1889 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1890 !BuildOpts.AddScopes)
1899 default:
return Scope;
1902 if (BuildOpts.AddImplicitDtors) {
1903 if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
1905 Scope = createOrReuseLocalScope(Scope);
1907 ScopePos = Scope->begin();
1912 assert(BuildOpts.AddLifetime);
1914 Scope = createOrReuseLocalScope(Scope);
1916 ScopePos = Scope->begin();
1922 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1923 LocalScope::const_iterator scopeBeginPos = ScopePos;
1924 addLocalScopeForStmt(S);
1925 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
1935 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1936 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1937 if (!BuildOpts.AddImplicitDtors)
1942 for (LocalScope::const_iterator I = B; I != E; ++I)
1952 void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
1953 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
1954 if (!BuildOpts.AddLifetime)
1959 for (LocalScope::const_iterator I = B; I != E; ++I)
1969 CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
1970 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
1971 if (!BuildOpts.AddScopes)
1976 LocalScope::const_iterator PlaceToInsert = B;
1977 for (LocalScope::const_iterator I = B; I != E; ++I)
1980 return *PlaceToInsert;
1986 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1992 if (
Expr *E = dyn_cast<Expr>(S))
1997 return VisitStmt(S, asc);
1999 case Stmt::AddrLabelExprClass:
2000 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2002 case Stmt::BinaryConditionalOperatorClass:
2003 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2005 case Stmt::BinaryOperatorClass:
2006 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2008 case Stmt::BlockExprClass:
2009 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2011 case Stmt::BreakStmtClass:
2012 return VisitBreakStmt(cast<BreakStmt>(S));
2014 case Stmt::CallExprClass:
2015 case Stmt::CXXOperatorCallExprClass:
2016 case Stmt::CXXMemberCallExprClass:
2017 case Stmt::UserDefinedLiteralClass:
2018 return VisitCallExpr(cast<CallExpr>(S), asc);
2020 case Stmt::CaseStmtClass:
2021 return VisitCaseStmt(cast<CaseStmt>(S));
2023 case Stmt::ChooseExprClass:
2024 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2026 case Stmt::CompoundStmtClass:
2027 return VisitCompoundStmt(cast<CompoundStmt>(S));
2029 case Stmt::ConditionalOperatorClass:
2030 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2032 case Stmt::ContinueStmtClass:
2033 return VisitContinueStmt(cast<ContinueStmt>(S));
2035 case Stmt::CXXCatchStmtClass:
2036 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2038 case Stmt::ExprWithCleanupsClass:
2039 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
2041 case Stmt::CXXDefaultArgExprClass:
2042 case Stmt::CXXDefaultInitExprClass:
2052 return VisitStmt(S, asc);
2054 case Stmt::CXXBindTemporaryExprClass:
2055 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2057 case Stmt::CXXConstructExprClass:
2058 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2060 case Stmt::CXXNewExprClass:
2061 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2063 case Stmt::CXXDeleteExprClass:
2064 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2066 case Stmt::CXXFunctionalCastExprClass:
2067 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2069 case Stmt::CXXTemporaryObjectExprClass:
2070 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2072 case Stmt::CXXThrowExprClass:
2073 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2075 case Stmt::CXXTryStmtClass:
2076 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2078 case Stmt::CXXForRangeStmtClass:
2079 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2081 case Stmt::DeclStmtClass:
2082 return VisitDeclStmt(cast<DeclStmt>(S));
2084 case Stmt::DefaultStmtClass:
2085 return VisitDefaultStmt(cast<DefaultStmt>(S));
2087 case Stmt::DoStmtClass:
2088 return VisitDoStmt(cast<DoStmt>(S));
2090 case Stmt::ForStmtClass:
2091 return VisitForStmt(cast<ForStmt>(S));
2093 case Stmt::GotoStmtClass:
2094 return VisitGotoStmt(cast<GotoStmt>(S));
2096 case Stmt::IfStmtClass:
2097 return VisitIfStmt(cast<IfStmt>(S));
2099 case Stmt::ImplicitCastExprClass:
2100 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2102 case Stmt::IndirectGotoStmtClass:
2103 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2105 case Stmt::LabelStmtClass:
2106 return VisitLabelStmt(cast<LabelStmt>(S));
2108 case Stmt::LambdaExprClass:
2109 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2111 case Stmt::MaterializeTemporaryExprClass:
2112 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2115 case Stmt::MemberExprClass:
2116 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2118 case Stmt::NullStmtClass:
2121 case Stmt::ObjCAtCatchStmtClass:
2122 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2124 case Stmt::ObjCAutoreleasePoolStmtClass:
2125 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2127 case Stmt::ObjCAtSynchronizedStmtClass:
2128 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2130 case Stmt::ObjCAtThrowStmtClass:
2131 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2133 case Stmt::ObjCAtTryStmtClass:
2134 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2136 case Stmt::ObjCForCollectionStmtClass:
2137 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2139 case Stmt::ObjCMessageExprClass:
2140 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2142 case Stmt::OpaqueValueExprClass:
2145 case Stmt::PseudoObjectExprClass:
2146 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2148 case Stmt::ReturnStmtClass:
2149 return VisitReturnStmt(cast<ReturnStmt>(S));
2151 case Stmt::SEHExceptStmtClass:
2152 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2154 case Stmt::SEHFinallyStmtClass:
2155 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2157 case Stmt::SEHLeaveStmtClass:
2158 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2160 case Stmt::SEHTryStmtClass:
2161 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2163 case Stmt::UnaryExprOrTypeTraitExprClass:
2164 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2167 case Stmt::StmtExprClass:
2168 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2170 case Stmt::SwitchStmtClass:
2171 return VisitSwitchStmt(cast<SwitchStmt>(S));
2173 case Stmt::UnaryOperatorClass:
2174 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2176 case Stmt::WhileStmtClass:
2177 return VisitWhileStmt(cast<WhileStmt>(S));
2181 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2182 if (asc.alwaysAdd(*
this, S)) {
2184 appendStmt(Block, S);
2187 return VisitChildren(S);
2196 reverse_children RChildren(S);
2197 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
2199 if (
Stmt *Child = *I)
2207 AddStmtChoice asc) {
2208 AddressTakenLabels.insert(A->
getLabel());
2210 if (asc.alwaysAdd(*
this, A)) {
2212 appendStmt(Block, A);
2219 AddStmtChoice asc) {
2220 if (asc.alwaysAdd(*
this, U)) {
2222 appendStmt(Block, U);
2225 return Visit(U->
getSubExpr(), AddStmtChoice());
2229 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2230 appendStmt(ConfluenceBlock, B);
2235 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2236 ConfluenceBlock).first;
2239 std::pair<CFGBlock*, CFGBlock*>
2252 if (B_RHS->isLogicalOp()) {
2253 std::tie(RHSBlock, ExitBlock) =
2254 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2262 ExitBlock = RHSBlock = createBlock(
false);
2267 TryResult KnownVal = tryEvaluateBool(RHS);
2268 if (!KnownVal.isKnown())
2269 KnownVal = tryEvaluateBool(B);
2272 assert(TrueBlock == FalseBlock);
2273 addSuccessor(RHSBlock, TrueBlock);
2277 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2278 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2282 RHSBlock = addStmt(RHS);
2287 return std::make_pair(
nullptr,
nullptr);
2293 if (B_LHS->isLogicalOp()) {
2295 FalseBlock = RHSBlock;
2297 TrueBlock = RHSBlock;
2302 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2307 CFGBlock *LHSBlock = createBlock(
false);
2311 CFGBlock *EntryLHSBlock = addStmt(LHS);
2314 return std::make_pair(
nullptr,
nullptr);
2317 TryResult KnownVal = tryEvaluateBool(LHS);
2321 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2322 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2325 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2326 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2329 return std::make_pair(EntryLHSBlock, ExitBlock);
2333 AddStmtChoice asc) {
2336 return VisitLogicalOperator(B);
2340 appendStmt(Block, B);
2342 return addStmt(B->
getLHS());
2346 if (asc.alwaysAdd(*
this, B)) {
2348 appendStmt(Block, B);
2351 return Visit(B->
getRHS());
2354 if (asc.alwaysAdd(*
this, B)) {
2356 appendStmt(Block, B);
2364 return (LBlock ? LBlock : RBlock);
2367 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2368 if (asc.alwaysAdd(*
this, E)) {
2370 appendStmt(Block, E);
2382 Block = createBlock(
false);
2383 Block->setTerminator(B);
2387 if (BreakJumpTarget.block) {
2388 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2389 addSuccessor(Block, BreakJumpTarget.block);
2421 if (!boundType.
isNull()) calleeType = boundType;
2424 findConstructionContextsForArguments(C);
2429 bool AddEHEdge =
false;
2433 if (BuildOpts.AddEHEdges)
2439 bool OmitArguments =
false;
2444 if (FD->hasAttr<NoThrowAttr>())
2446 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
2447 OmitArguments =
true;
2453 if (OmitArguments) {
2454 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2455 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2457 appendStmt(Block, C);
2461 if (!NoReturn && !AddEHEdge) {
2463 appendCall(Block, C);
2465 return VisitChildren(C);
2475 Block = createNoReturnBlock();
2477 Block = createBlock();
2479 appendCall(Block, C);
2483 if (TryTerminatedBlock)
2484 addSuccessor(Block, TryTerminatedBlock);
2486 addSuccessor(Block, &cfg->getExit());
2489 return VisitChildren(C);
2493 AddStmtChoice asc) {
2494 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2495 appendStmt(ConfluenceBlock, C);
2499 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2500 Succ = ConfluenceBlock;
2506 Succ = ConfluenceBlock;
2512 Block = createBlock(
false);
2514 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2515 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2516 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2517 Block->setTerminator(C);
2522 LocalScope::const_iterator scopeBeginPos = ScopePos;
2523 addLocalScopeForStmt(C);
2528 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2537 if (
CFGBlock *newBlock = addStmt(*I))
2538 LastBlock = newBlock;
2548 AddStmtChoice asc) {
2554 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2555 appendStmt(ConfluenceBlock, C);
2559 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2565 Succ = ConfluenceBlock;
2569 if (trueExpr != opaqueValue) {
2576 LHSBlock = ConfluenceBlock;
2579 Succ = ConfluenceBlock;
2587 if (Cond->isLogicalOp())
2588 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2591 Block = createBlock(
false);
2594 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2595 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2596 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2597 Block->setTerminator(C);
2603 if (condExpr != opaqueValue)
2611 return addStmt(condExpr);
2622 return VisitDeclSubExpr(DS);
2637 void *Mem = cfg->getAllocator().Allocate(
sizeof(
DeclStmt), A);
2639 cfg->addSyntheticDeclStmt(DSNew, DS);
2642 B = VisitDeclSubExpr(DSNew);
2651 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2660 bool HasTemporaries =
false;
2663 CFGBlock *blockAfterStaticInit =
nullptr;
2665 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2674 blockAfterStaticInit = Succ;
2679 Expr *Init = VD->getInit();
2681 HasTemporaries = isa<ExprWithCleanups>(Init);
2683 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2685 TempDtorContext Context;
2686 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2692 appendStmt(Block, DS);
2694 findConstructionContexts(
2704 if (HasTemporaries) {
2709 LastBlock = newBlock;
2712 if (
CFGBlock *newBlock = Visit(Init))
2713 LastBlock = newBlock;
2719 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2720 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2721 LastBlock = newBlock;
2724 maybeAddScopeBeginForVarDecl(Block, VD, DS);
2727 if (ScopePos && VD == *ScopePos)
2731 if (blockAfterStaticInit) {
2733 Block = createBlock(
false);
2734 Block->setTerminator(DS);
2735 addSuccessor(Block, blockAfterStaticInit);
2736 addSuccessor(Block, B);
2757 addLocalScopeForStmt(Init);
2762 addLocalScopeForVarDecl(VD);
2764 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
2786 if (!isa<CompoundStmt>(Else))
2787 addLocalScopeAndDtors(Else);
2789 ElseBlock = addStmt(Else);
2792 ElseBlock = sv.get();
2809 if (!isa<CompoundStmt>(Then))
2810 addLocalScopeAndDtors(Then);
2812 ThenBlock = addStmt(Then);
2818 ThenBlock = createBlock(
false);
2819 addSuccessor(ThenBlock, sv.get());
2839 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2842 Block = createBlock(
false);
2845 Block->setTerminator(I);
2848 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2852 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2853 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2858 LastBlock = addStmt(I->
getCond());
2864 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2871 LastBlock = addStmt(Init);
2886 Block = createBlock(
false);
2888 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), R);
2890 findConstructionContexts(
2896 if (!Block->hasNoReturnElement())
2897 addSuccessor(Block, &cfg->getExit());
2901 return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2914 if (!SEHExceptBlock)
2915 SEHExceptBlock = createBlock();
2917 appendStmt(SEHExceptBlock, ES);
2920 SEHExceptBlock->setLabel(ES);
2929 return SEHExceptBlock;
2933 return VisitCompoundStmt(FS->
getBlock());
2943 Block = createBlock(
false);
2944 Block->setTerminator(LS);
2948 if (SEHLeaveJumpTarget.block) {
2949 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
2950 addSuccessor(Block, SEHLeaveJumpTarget.block);
2960 CFGBlock *SEHTrySuccessor =
nullptr;
2965 SEHTrySuccessor = Block;
2966 }
else SEHTrySuccessor = Succ;
2972 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
2975 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
2982 Succ = SEHTrySuccessor;
2984 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
2989 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
2991 if (PrevSEHTryTerminatedBlock)
2992 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
2994 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
2997 Succ = SEHTrySuccessor;
3001 NewTryTerminatedBlock);
3002 cfg->addTryDispatchBlock(TryTerminatedBlock);
3008 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3010 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3021 LabelBlock = createBlock();
3023 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
3024 "label already in map");
3025 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3031 LabelBlock->setLabel(L);
3045 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3047 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3057 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3060 if (
Expr *Init = *it) {
3073 Block = createBlock(
false);
3074 Block->setTerminator(G);
3077 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3079 if (I == LabelMap.end())
3081 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3083 JumpTarget JT = I->second;
3084 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
3085 addSuccessor(Block, JT.block);
3102 addLocalScopeForStmt(Init);
3103 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3106 addLocalScopeForVarDecl(VD);
3107 LocalScope::const_iterator ContinueScopePos = ScopePos;
3109 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3118 LoopSuccessor = Block;
3120 LoopSuccessor = Succ;
3125 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3127 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3140 Block = Succ = TransitionBlock = createBlock(
false);
3141 TransitionBlock->setLoopTarget(F);
3151 assert(Block == Succ);
3159 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3160 ContinueJumpTarget.block->setLoopTarget(F);
3163 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3167 if (!isa<CompoundStmt>(F->
getBody()))
3168 addLocalScopeAndDtors(F->
getBody());
3172 BodyBlock = addStmt(F->
getBody());
3177 BodyBlock = ContinueJumpTarget.block;
3186 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3195 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
3196 if (Cond->isLogicalOp()) {
3197 std::tie(EntryConditionBlock, ExitConditionBlock) =
3198 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3203 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3204 ExitConditionBlock->setTerminator(F);
3207 TryResult KnownVal(
true);
3213 Block = ExitConditionBlock;
3214 EntryConditionBlock = addStmt(C);
3223 findConstructionContexts(
3226 appendStmt(Block, DS);
3227 EntryConditionBlock = addStmt(Init);
3228 assert(Block == EntryConditionBlock);
3229 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3233 if (Block && badCFG)
3236 KnownVal = tryEvaluateBool(C);
3240 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3243 addSuccessor(ExitConditionBlock,
3244 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3248 addSuccessor(TransitionBlock, EntryConditionBlock);
3251 Succ = EntryConditionBlock;
3257 ScopePos = LoopBeginScopePos;
3258 Block = createBlock();
3265 Succ = EntryConditionBlock;
3266 return EntryConditionBlock;
3271 AddStmtChoice asc) {
3272 findConstructionContexts(
3276 return VisitStmt(MTE, asc);
3280 if (asc.alwaysAdd(*
this, M)) {
3282 appendStmt(Block, M);
3324 LoopSuccessor = Block;
3327 LoopSuccessor = Succ;
3330 CFGBlock *ExitConditionBlock = createBlock(
false);
3338 appendStmt(ExitConditionBlock, S);
3339 Block = ExitConditionBlock;
3345 AddStmtChoice::NotAlwaysAdd);
3354 Succ = EntryConditionBlock;
3361 save_break(BreakJumpTarget);
3367 Succ = LoopBackBlock = createBlock();
3370 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3371 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3376 BodyBlock = ContinueJumpTarget.block;
3383 addSuccessor(ExitConditionBlock, BodyBlock);
3388 addSuccessor(ExitConditionBlock, LoopSuccessor);
3391 Block = createBlock();
3419 appendStmt(Block, S);
3434 appendStmt(Block, E);
3446 Semantic = OVE->getSourceExpr();
3464 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3466 addLocalScopeForVarDecl(VD);
3467 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3476 LoopSuccessor = Block;
3479 LoopSuccessor = Succ;
3482 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3491 save_break(BreakJumpTarget);
3495 Succ = TransitionBlock = createBlock(
false);
3496 TransitionBlock->setLoopTarget(W);
3497 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3500 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3503 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3507 if (!isa<CompoundStmt>(W->
getBody()))
3508 addLocalScopeAndDtors(W->
getBody());
3511 BodyBlock = addStmt(W->
getBody());
3514 BodyBlock = ContinueJumpTarget.block;
3515 else if (Block && badCFG)
3522 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3530 if (Cond->isLogicalOp()) {
3531 std::tie(EntryConditionBlock, ExitConditionBlock) =
3532 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3537 ExitConditionBlock = createBlock(
false);
3538 ExitConditionBlock->setTerminator(W);
3543 Block = ExitConditionBlock;
3544 Block = EntryConditionBlock = addStmt(C);
3553 findConstructionContexts(
3557 appendStmt(Block, DS);
3558 EntryConditionBlock = addStmt(Init);
3559 assert(Block == EntryConditionBlock);
3560 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3564 if (Block && badCFG)
3568 const TryResult& KnownVal = tryEvaluateBool(C);
3571 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3574 addSuccessor(ExitConditionBlock,
3575 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3579 addSuccessor(TransitionBlock, EntryConditionBlock);
3586 Succ = EntryConditionBlock;
3587 return EntryConditionBlock;
3605 Block = createBlock(
false);
3608 addSuccessor(Block, &cfg->getExit());
3612 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
3616 AddStmtChoice asc) {
3617 findConstructionContextsForArguments(ME);
3620 appendObjCMessage(Block, ME);
3622 return VisitChildren(ME);
3631 Block = createBlock(
false);
3633 if (TryTerminatedBlock)
3635 addSuccessor(Block, TryTerminatedBlock);
3638 addSuccessor(Block, &cfg->getExit());
3642 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
3655 LoopSuccessor = Block;
3657 LoopSuccessor = Succ;
3662 CFGBlock *ExitConditionBlock = createBlock(
false);
3663 CFGBlock *EntryConditionBlock = ExitConditionBlock;
3671 Block = ExitConditionBlock;
3672 EntryConditionBlock = addStmt(C);
3680 Succ = EntryConditionBlock;
3683 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
3693 save_break(BreakJumpTarget);
3696 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
3699 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3706 if (!isa<CompoundStmt>(D->
getBody()))
3707 addLocalScopeAndDtors(D->
getBody());
3710 BodyBlock = addStmt(D->
getBody());
3713 BodyBlock = EntryConditionBlock;
3726 CFGBlock *LoopBackBlock = createBlock();
3729 if (!KnownVal.isFalse())
3731 addSuccessor(ExitConditionBlock, LoopBackBlock);
3733 addSuccessor(ExitConditionBlock,
nullptr);
3738 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3756 Block = createBlock(
false);
3757 Block->setTerminator(C);
3761 if (ContinueJumpTarget.block) {
3762 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
3763 addSuccessor(Block, ContinueJumpTarget.block);
3771 AddStmtChoice asc) {
3772 if (asc.alwaysAdd(*
this, E)) {
3774 appendStmt(Block, E);
3782 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3783 lastBlock = addStmt(VA->getSizeExpr());
3791 if (asc.alwaysAdd(*
this, SE)) {
3793 appendStmt(Block, SE);
3801 CFGBlock *SwitchSuccessor =
nullptr;
3809 addLocalScopeForStmt(Init);
3814 addLocalScopeForVarDecl(VD);
3816 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
3821 SwitchSuccessor = Block;
3822 }
else SwitchSuccessor = Succ;
3826 save_default(DefaultCaseBlock);
3832 DefaultCaseBlock = SwitchSuccessor;
3835 SwitchTerminatedBlock = createBlock(
false);
3839 Succ = SwitchSuccessor;
3840 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3845 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3854 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3856 bool b = tryEvaluate(Terminator->
getCond(), result);
3858 b ? &result :
nullptr);
3862 if (!isa<CompoundStmt>(Terminator->
getBody()))
3863 addLocalScopeAndDtors(Terminator->
getBody());
3865 addStmt(Terminator->
getBody());
3877 bool SwitchAlwaysHasSuccessor =
false;
3878 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3881 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3882 !SwitchAlwaysHasSuccessor);
3885 SwitchTerminatedBlock->setTerminator(Terminator);
3886 Block = SwitchTerminatedBlock;
3895 LastBlock = addStmt(Init);
3896 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
3903 LastBlock = addStmt(Init);
3916 bool addCase =
false;
3918 if (!switchExclusivelyCovered) {
3922 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3924 if (condInt == lhsInt) {
3926 switchExclusivelyCovered =
true;
3928 else if (condInt > lhsInt) {
3931 const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
3932 if (V2 >= condInt) {
3934 switchExclusivelyCovered =
true;
3948 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3954 while (isa<CaseStmt>(Sub)) {
3955 CFGBlock *currentBlock = createBlock(
false);
3959 addSuccessor(LastBlock, currentBlock);
3961 TopBlock = currentBlock;
3963 addSuccessor(SwitchTerminatedBlock,
3966 ? currentBlock :
nullptr);
3968 LastBlock = currentBlock;
3969 CS = cast<CaseStmt>(Sub);
3978 CaseBlock = createBlock();
3989 assert(SwitchTerminatedBlock);
3990 addSuccessor(SwitchTerminatedBlock, CaseBlock,
3998 addSuccessor(LastBlock, CaseBlock);
4012 DefaultCaseBlock = Block;
4014 if (!DefaultCaseBlock)
4015 DefaultCaseBlock = createBlock();
4019 DefaultCaseBlock->setLabel(Terminator);
4034 Succ = DefaultCaseBlock;
4036 return DefaultCaseBlock;
4047 TrySuccessor = Block;
4048 }
else TrySuccessor = Succ;
4050 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4053 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4057 bool HasCatchAll =
false;
4060 Succ = TrySuccessor;
4066 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4071 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4074 if (PrevTryTerminatedBlock)
4075 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4077 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4081 Succ = TrySuccessor;
4085 cfg->addTryDispatchBlock(TryTerminatedBlock);
4087 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4103 LocalScope::const_iterator BeginScopePos = ScopePos;
4104 addLocalScopeForVarDecl(VD);
4105 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4113 CatchBlock = createBlock();
4119 appendStmt(CatchBlock, CS);
4154 addLocalScopeForStmt(Range);
4156 addLocalScopeForStmt(
Begin);
4158 addLocalScopeForStmt(
End);
4159 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4161 LocalScope::const_iterator ContinueScopePos = ScopePos;
4169 LoopSuccessor = Block;
4171 LoopSuccessor = Succ;
4176 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4179 CFGBlock *ConditionBlock = createBlock(
false);
4184 Block = ConditionBlock;
4185 CFGBlock *BeginConditionBlock = addStmt(C);
4188 assert(BeginConditionBlock == ConditionBlock &&
4189 "condition block in for-range was unexpectedly complex");
4190 (void)BeginConditionBlock;
4195 Succ = ConditionBlock;
4198 TryResult KnownVal(
true);
4201 KnownVal = tryEvaluateBool(S->
getCond());
4214 Succ = addStmt(S->
getInc());
4217 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4221 ContinueJumpTarget.block->setLoopTarget(S);
4241 addSuccessor(ConditionBlock,
4242 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
4247 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4250 Block = createBlock();
4257 AddStmtChoice asc) {
4258 if (BuildOpts.AddTemporaryDtors) {
4261 TempDtorContext Context;
4262 VisitForTemporaryDtors(E->
getSubExpr(),
false, Context);
4266 asc = asc.withAlwaysAdd(
true);
4272 AddStmtChoice asc) {
4273 if (asc.alwaysAdd(*
this, E)) {
4275 appendStmt(Block, E);
4277 findConstructionContexts(
4282 asc = asc.withAlwaysAdd(
false);
4288 AddStmtChoice asc) {
4292 findConstructionContextsForArguments(C);
4295 appendConstructor(Block, C);
4297 return VisitChildren(C);
4301 AddStmtChoice asc) {
4303 appendStmt(Block, NE);
4305 findConstructionContexts(
4312 if (BuildOpts.AddCXXNewAllocator)
4313 appendNewAllocator(Block, NE);
4326 AddStmtChoice asc) {
4328 appendStmt(Block, DE);
4335 appendDeleteDtor(Block, RD, DE);
4339 return VisitChildren(DE);
4343 AddStmtChoice asc) {
4344 if (asc.alwaysAdd(*
this, E)) {
4346 appendStmt(Block, E);
4348 asc = asc.withAlwaysAdd(
false);
4354 AddStmtChoice asc) {
4356 appendConstructor(Block, C);
4357 return VisitChildren(C);
4361 AddStmtChoice asc) {
4362 if (asc.alwaysAdd(*
this, E)) {
4364 appendStmt(Block, E);
4366 return Visit(E->
getSubExpr(), AddStmtChoice());
4371 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4374 IBlock = createBlock(
false);
4375 cfg->setIndirectGotoBlock(IBlock);
4383 Block = createBlock(
false);
4384 Block->setTerminator(I);
4385 addSuccessor(Block, IBlock);
4389 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
4390 TempDtorContext &Context) {
4391 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
4400 return VisitChildrenForTemporaryDtors(E, Context);
4402 case Stmt::BinaryOperatorClass:
4403 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4406 case Stmt::CXXBindTemporaryExprClass:
4407 return VisitCXXBindTemporaryExprForTemporaryDtors(
4408 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
4410 case Stmt::BinaryConditionalOperatorClass:
4411 case Stmt::ConditionalOperatorClass:
4412 return VisitConditionalOperatorForTemporaryDtors(
4413 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
4415 case Stmt::ImplicitCastExprClass:
4417 E = cast<CastExpr>(E)->getSubExpr();
4420 case Stmt::CXXFunctionalCastExprClass:
4422 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4425 case Stmt::ParenExprClass:
4426 E = cast<ParenExpr>(E)->getSubExpr();
4429 case Stmt::MaterializeTemporaryExprClass: {
4435 E =
const_cast<Expr *
>(
4436 cast<MaterializeTemporaryExpr>(E)
4437 ->GetTemporaryExpr()
4438 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4440 for (
const Expr *CommaLHS : CommaLHSs) {
4441 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
4447 case Stmt::BlockExprClass:
4452 case Stmt::LambdaExprClass: {
4455 auto *LE = cast<LambdaExpr>(E);
4457 for (
Expr *Init : LE->capture_inits()) {
4459 if (
CFGBlock *R = VisitForTemporaryDtors(
4460 Init,
false, Context))
4467 case Stmt::CXXDefaultArgExprClass:
4468 E = cast<CXXDefaultArgExpr>(E)->getExpr();
4471 case Stmt::CXXDefaultInitExprClass:
4472 E = cast<CXXDefaultInitExpr>(E)->getExpr();
4477 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
4478 TempDtorContext &Context) {
4479 if (isa<LambdaExpr>(E)) {
4491 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
4497 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
4500 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4501 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
4502 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
4503 RHSExecuted.negate();
4508 TempDtorContext RHSContext(
4510 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
4511 InsertTempDtorDecisionBlock(RHSContext);
4519 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4520 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4521 return LHSBlock ? LHSBlock : RHSBlock;
4527 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4528 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4529 return RHSBlock ? RHSBlock : LHSBlock;
4532 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
4536 if (!BindToTemporary) {
4548 Block = createNoReturnBlock();
4549 }
else if (Context.needsTempDtorBranch()) {
4553 Block = createBlock();
4557 if (Context.needsTempDtorBranch()) {
4558 Context.setDecisionPoint(Succ, E);
4560 appendTemporaryDtor(Block, E);
4567 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
4569 if (!Context.TerminatorExpr) {
4573 assert(Context.TerminatorExpr);
4574 CFGBlock *Decision = createBlock(
false);
4576 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
4577 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
4578 !Context.KnownExecuted.isTrue());
4582 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
4584 TempDtorContext &Context) {
4585 VisitForTemporaryDtors(E->
getCond(),
false, Context);
4588 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
4589 TryResult NegatedVal = ConditionVal;
4590 if (NegatedVal.isKnown()) NegatedVal.negate();
4592 TempDtorContext TrueContext(
4594 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
4597 Block = ConditionBlock;
4598 Succ = ConditionSucc;
4599 TempDtorContext FalseContext(
4601 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
4603 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
4604 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
4605 }
else if (TrueContext.TerminatorExpr) {
4607 InsertTempDtorDecisionBlock(TrueContext);
4609 InsertTempDtorDecisionBlock(FalseContext);
4618 bool first_block = begin() == end();
4622 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
4623 Blocks.push_back(Mem, BlkBVC);
4627 Entry = Exit = &back();
4636 CFGBuilder Builder(C, BO);
4637 return Builder.buildCFG(D, Statement);
4652 llvm_unreachable(
"getDestructorDecl should only be used with " 4655 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
4673 cast<CXXRecordDecl>(recordType->
getDecl());
4677 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
4686 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
4695 llvm_unreachable(
"getKind() returned bogus value");
4709 : ReachableBlock(IsReachable ? B : nullptr),
4710 UnreachableBlock(!IsReachable ? B : nullptr,
4711 B && IsReachable ? AB_Normal : AB_Unreachable) {}
4714 : ReachableBlock(B),
4715 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
4716 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
4724 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
4726 Succs.push_back(Succ, C);
4739 if (S->isAllEnumCasesCovered()) {
4741 if (!L || !isa<CaseStmt>(L))
4757 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
4758 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
4762 signed currentBlock = 0;
4763 unsigned currStmt = 0;
4772 BI != BEnd; ++BI, ++j ) {
4774 const Stmt *stmt= SE->getStmt();
4775 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
4779 case Stmt::DeclStmtClass:
4780 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
4782 case Stmt::IfStmtClass: {
4783 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
4788 case Stmt::ForStmtClass: {
4789 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4794 case Stmt::WhileStmtClass: {
4796 cast<WhileStmt>(
stmt)->getConditionVariable();
4801 case Stmt::SwitchStmtClass: {
4803 cast<SwitchStmt>(
stmt)->getConditionVariable();
4808 case Stmt::CXXCatchStmtClass: {
4810 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
4823 ~StmtPrinterHelper()
override =
default;
4825 const LangOptions &getLangOpts()
const {
return LangOpts; }
4826 void setBlockID(
signed i) { currentBlock = i; }
4827 void setStmtID(
unsigned i) { currStmt = i; }
4829 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
4830 StmtMapTy::iterator I = StmtMap.find(S);
4832 if (I == StmtMap.end())
4835 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4836 && I->second.second == currStmt) {
4840 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4844 bool handleDecl(
const Decl *D, raw_ostream &OS) {
4845 DeclMapTy::iterator I = DeclMap.find(D);
4847 if (I == DeclMap.end())
4850 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4851 && I->second.second == currStmt) {
4855 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4860 class CFGBlockTerminatorPrint
4861 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4863 StmtPrinterHelper* Helper;
4867 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4869 : OS(os), Helper(helper), Policy(Policy) {
4873 void VisitIfStmt(
IfStmt *I) {
4880 void VisitStmt(
Stmt *Terminator) {
4886 OS <<
"static init " << VD->
getName();
4889 void VisitForStmt(
ForStmt *F) {
4908 void VisitDoStmt(
DoStmt *D) {
4909 OS <<
"do ... while ";
4914 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4929 Cond->printPretty(OS, Helper, Policy);
4930 OS <<
" ? ... : ...";
4934 OS <<
"__builtin_choose_expr( ";
4936 Cond->printPretty(OS, Helper, Policy);
4963 llvm_unreachable(
"Invalid logical operator.");
4967 void VisitExpr(
Expr *E) {
4974 OS <<
"(Temp Dtor) ";
4991 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
4995 OS <<
" (Base initializer)";
4997 OS <<
" (Delegating initializer)";
4999 OS <<
" (Member initializer)";
5003 StmtPrinterHelper &Helper,
5009 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5016 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5018 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5022 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5023 Stmts.push_back(SDSCC->getDeclStmt());
5027 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5028 Stmts.push_back(CDSCC->getDeclStmt());
5029 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5033 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5034 Stmts.push_back(NECC->getCXXNewExpr());
5038 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5039 Stmts.push_back(RSCC->getReturnStmt());
5044 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5045 Stmts.push_back(RSCC->getReturnStmt());
5046 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5050 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5051 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5052 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5056 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5057 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5058 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5059 Stmts.push_back(TOCC->getConstructorAfterElision());
5063 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5064 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5066 Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
5069 Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
5070 OS <<
"+" << ACC->getIndex();
5077 Helper.handledStmt(const_cast<Stmt *>(I), OS);
5081 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5084 const Stmt *S = CS->getStmt();
5085 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5088 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5092 if (Children.begin() != Children.end()) {
5101 if (B->getOpcode() == BO_Comma) {
5103 Helper.handledStmt(B->getRHS(),OS);
5111 if (isa<CXXOperatorCallExpr>(S))
5112 OS <<
" (OperatorCall)";
5113 OS <<
" (CXXRecordTypedCall";
5116 }
else if (isa<CXXOperatorCallExpr>(S)) {
5117 OS <<
" (OperatorCall)";
5118 }
else if (isa<CXXBindTemporaryExpr>(S)) {
5119 OS <<
" (BindTemporary)";
5121 OS <<
" (CXXConstructExpr";
5125 OS <<
", " << CCE->getType().getAsString() <<
")";
5126 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5127 OS <<
" (" << CE->getStmtClassName() <<
", " 5128 << CE->getCastKindName()
5129 <<
", " << CE->getType().getAsString()
5141 const VarDecl *VD = DE->getVarDecl();
5142 Helper.handleDecl(VD, OS);
5152 OS <<
" (Implicit destructor)\n";
5154 const VarDecl *VD = DE->getVarDecl();
5155 Helper.handleDecl(VD, OS);
5157 OS <<
" (Lifetime ends)\n";
5159 const Stmt *LoopStmt = LE->getLoopStmt();
5162 OS <<
"CFGScopeBegin(";
5163 if (
const VarDecl *VD = SB->getVarDecl())
5167 OS <<
"CFGScopeEnd(";
5168 if (
const VarDecl *VD = SE->getVarDecl())
5172 OS <<
"CFGNewAllocator(";
5173 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
5174 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
5182 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
5183 OS <<
"->~" << RD->
getName().str() <<
"()";
5184 OS <<
" (Implicit destructor)\n";
5188 OS <<
" (Base object destructor)\n";
5190 const FieldDecl *FD = ME->getFieldDecl();
5192 OS <<
"this->" << FD->
getName();
5194 OS <<
" (Member object destructor)\n";
5199 OS <<
"() (Temporary object destructor)\n";
5205 StmtPrinterHelper &Helper,
bool print_edges,
5211 OS.changeColor(raw_ostream::YELLOW,
true);
5216 OS <<
" (ENTRY)]\n";
5217 else if (&B == &cfg->
getExit())
5220 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
5222 OS <<
" (NORETURN)]\n";
5246 }
else if (isa<DefaultStmt>(
Label))
5262 llvm_unreachable(
"Invalid label statement in CFGBlock.");
5271 I != E ; ++I, ++j ) {
5276 OS << llvm::format(
"%3d", j) <<
": ";
5278 Helper.setStmtID(j);
5286 OS.changeColor(raw_ostream::GREEN);
5290 Helper.setBlockID(-1);
5293 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
5304 const raw_ostream::Colors Color = raw_ostream::BLUE;
5306 OS.changeColor(Color);
5314 OS.changeColor(Color);
5322 bool Reachable =
true;
5325 B = I->getPossiblyUnreachableBlock();
5330 OS <<
"(Unreachable)";
5341 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
5343 OS.changeColor(Color);
5351 OS.changeColor(Color);
5360 bool Reachable =
true;
5363 B = I->getPossiblyUnreachableBlock();
5369 OS <<
"(Unreachable)";
5385 print(llvm::errs(), LO, ShowColors);
5390 StmtPrinterHelper Helper(
this, LO);
5393 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
5396 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
5398 if (&(**I) == &getEntry() || &(**I) == &getExit())
5401 print_block(OS,
this, **I, Helper,
true, ShowColors);
5405 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
5412 bool ShowColors)
const {
5413 print(llvm::errs(), cfg, LO, ShowColors);
5424 StmtPrinterHelper Helper(cfg, LO);
5425 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
5432 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
5437 Stmt *Terminator = this->Terminator;
5447 case Stmt::CXXForRangeStmtClass:
5448 E = cast<CXXForRangeStmt>(Terminator)->getCond();
5451 case Stmt::ForStmtClass:
5452 E = cast<ForStmt>(Terminator)->getCond();
5455 case Stmt::WhileStmtClass:
5456 E = cast<WhileStmt>(Terminator)->getCond();
5459 case Stmt::DoStmtClass:
5460 E = cast<DoStmt>(Terminator)->getCond();
5463 case Stmt::IfStmtClass:
5464 E = cast<IfStmt>(Terminator)->getCond();
5467 case Stmt::ChooseExprClass:
5468 E = cast<ChooseExpr>(Terminator)->getCond();
5471 case Stmt::IndirectGotoStmtClass:
5472 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
5475 case Stmt::SwitchStmtClass:
5476 E = cast<SwitchStmt>(Terminator)->getCond();
5479 case Stmt::BinaryConditionalOperatorClass:
5480 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
5483 case Stmt::ConditionalOperatorClass:
5484 E = cast<ConditionalOperator>(Terminator)->getCond();
5487 case Stmt::BinaryOperatorClass:
5488 E = cast<BinaryOperator>(Terminator)->getLHS();
5491 case Stmt::ObjCForCollectionStmtClass:
5511 StmtPrinterHelper H(
this, LO);
5513 llvm::ViewGraph(
this,
"CFG");
5514 GraphHelper =
nullptr;
5526 std::string OutSStr;
5527 llvm::raw_string_ostream Out(OutSStr);
5528 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
5529 std::string& OutStr = Out.str();
5531 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
5534 for (
unsigned i = 0; i != OutStr.length(); ++i)
5535 if (OutStr[i] ==
'\n') {
5537 OutStr.insert(OutStr.begin()+i+1,
'l');
unsigned getNumSemanticExprs() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Defines the clang::ASTContext interface.
const BlockDecl * getBlockDecl() const
Represents C++ allocator call.
const CXXDestructorDecl * getDestructor() const
Represents a function declaration or definition.
Expr * getInit() const
Get the initializer.
const Stmt * getElse() const
CompoundStmt * getBlock() const
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
A class which contains all the information about a particular captured value.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
static SourceLocation GetEndLoc(Decl *D)
AdjacentBlocks::const_iterator const_pred_iterator
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...
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
ElementList::iterator iterator
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
const DeclStmt * getConditionVariableDeclStmt() const
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
Stmt - This represents one statement.
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
IfStmt - This represents an if/then/else.
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
unsigned IgnoreDefaultsWithCoveredEnums
Represents a C++ constructor within a class.
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "while" statement, if any.
unsigned succ_size() const
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
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.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "switch" statement, if any.
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)
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
QualType getPointeeType() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void setLoopTarget(const Stmt *loopTarget)
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)
field_range fields() const
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...
const Expr * getRetValue() const
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...
Represents Objective-C's @catch statement.
AdjacentBlocks::const_iterator const_succ_iterator
IndirectGotoStmt - This represents an indirect goto.
Describes an C or C++ initializer list.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
ForStmt - This represents a 'for (init;cond;inc)' stmt.
APValue Val
Val - This is the value the expression can be folded to.
LabelDecl * getDecl() const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Expr * getInitializer()
The initializer of this new-expression.
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.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, const ASTContext *Context=nullptr) const
Scope - A scope is a transient data structure that is used while parsing the program.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
FieldDecl * getAnyMember() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
arg_iterator placement_arg_end()
Iterator for iterating over Stmt * arrays that contain only Expr *.
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
CFGBlockListTy::const_iterator const_iterator
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.
const DeclStmt * getConditionVariableDeclStmt() const
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool isNoReturn(ASTContext &astContext) const
Expr - This represents one expression.
Defines the clang::LangOptions interface.
Stmt * getTerminatorCondition(bool StripParens=true)
static std::tuple< const DeclRefExpr *, BinaryOperatorKind, const Expr * > tryNormalizeBinaryOperator(const BinaryOperator *B)
Tries to interpret a binary operator into Decl Op Expr form, if Expr is an integer literal or an enum...
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
Represents a C++ functional cast expression that builds a temporary object.
const Stmt * getThen() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
VarDecl * getExceptionDecl() const
unsigned getNumInits() const
const Expr * getCallee() const
Represents C++ constructor call.
QualType getArgumentType() const
const CompoundStmt * getSynchBody() const
ElementList::const_iterator const_iterator
bool isTemporaryDtorsBranch() const
Represents Objective-C's @synchronized statement.
CXXTryStmt - A C++ try block, including all handlers.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
std::reverse_iterator< body_iterator > reverse_body_iterator
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.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
An expression that sends a message to the given Objective-C object or class.
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.
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)
CFGTerminator getTerminator()
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
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.
const SwitchCase * getSwitchCaseList() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
void setLabel(Stmt *Statement)
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
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.
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.
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'...
const DeclStmt * getConditionVariableDeclStmt() const
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Defines various enumerations that describe declaration and type specifiers.
AddrLabelExpr - The GNU address of label extension, representing &&label.
ast_type_traits::DynTypedNode Node
pred_iterator pred_begin()
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "if" statement, if any.
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
EvalResult is a struct with detailed info about an evaluated expression.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
ArrayRef< Capture > captures() const
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
static const VariableArrayType * FindVA(const Type *t)
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
const Expr * getInit() const
unsigned pred_size() const
StmtClass getStmtClass() const
static StmtPrinterHelper * GraphHelper
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
bool isAnyDestructorNoReturn() const
Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn...
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
SEHExceptStmt * getExceptHandler() const
Returns 0 if not defined.
const Decl * getSingleDecl() const
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
const Expr * getSynchExpr() const
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
This class represents a potential adjacent block in the CFG.
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
Represents the point where the lifetime of an automatic object ends.
Represents a single point (AST node) in the program that requires attention during construction of an...
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
const Stmt * getBody() const
llvm::APInt getValue() const
Represents a __leave statement.
LabelDecl * getLabel() const
SwitchStmt - This represents a 'switch' stmt.
CFGBlock * getIndirectGotoBlock()
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Represents Objective-C's collection statement.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Represents a C++ base or member initializer.
reverse_decl_iterator decl_rend()
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).
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)
const Expr * getCond() const
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.
DeclStmt * getBeginStmt()
const Expr * getCond() const
bool isFunctionPointerType() const
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const LangOptions & getLangOpts() const
Represents Objective-C's @autoreleasepool Statement.
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
CompoundStmt * getTryBlock() const
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
IgnoreParens - Ignore parentheses.
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt...
const DeclStmt * getConditionVariableDeclStmt() const
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
QualType getType() const
Retrieves the type of the base class.
Represents the point where a loop ends.