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);
560 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
587 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
594 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
595 appendScopeBegin(B, VD, S);
626 struct TempDtorContext {
627 TempDtorContext() =
default;
628 TempDtorContext(TryResult KnownExecuted)
629 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
637 bool needsTempDtorBranch()
const {
638 return IsConditional && !TerminatorExpr;
648 const bool IsConditional =
false;
649 const TryResult KnownExecuted =
true;
656 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
657 TempDtorContext &Context);
658 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *E, TempDtorContext &Context);
660 TempDtorContext &Context);
661 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
663 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
665 TempDtorContext &Context);
666 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
691 template <
typename CallLikeExpr,
692 typename =
typename std::enable_if<
693 std::is_same<CallLikeExpr, CallExpr>::value ||
694 std::is_same<CallLikeExpr, CXXConstructExpr>::value ||
695 std::is_same<CallLikeExpr, ObjCMessageExpr>::value>>
696 void findConstructionContextsForArguments(CallLikeExpr *E) {
697 for (
unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
698 Expr *Arg = E->getArg(i);
700 findConstructionContexts(
710 void cleanupConstructionContext(
Expr *E);
712 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
713 CFGBlock *createBlock(
bool add_successor =
true);
717 return Visit(S, AddStmtChoice::AlwaysAdd);
721 void addLoopExit(
const Stmt *LoopStmt);
722 void addAutomaticObjDtors(LocalScope::const_iterator B,
723 LocalScope::const_iterator E,
Stmt *S);
724 void addLifetimeEnds(LocalScope::const_iterator B,
725 LocalScope::const_iterator E,
Stmt *S);
726 void addAutomaticObjHandling(LocalScope::const_iterator B,
727 LocalScope::const_iterator E,
Stmt *S);
729 void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
732 void getDeclsWithEndedScope(LocalScope::const_iterator B,
733 LocalScope::const_iterator E,
Stmt *S);
736 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
738 void addLocalScopeForStmt(
Stmt *S);
739 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
740 LocalScope* Scope =
nullptr);
741 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope* Scope =
nullptr);
743 void addLocalScopeAndDtors(
Stmt *S);
753 cleanupConstructionContext(E);
761 if (alwaysAdd(S) && cachedEntry)
762 cachedEntry->second = B;
765 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
766 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
771 retrieveAndCleanupConstructionContext(CE)) {
777 B->
appendStmt(CE, cfg->getBumpVectorContext());
781 if (alwaysAdd(CE) && cachedEntry)
782 cachedEntry->second = B;
785 retrieveAndCleanupConstructionContext(CE)) {
791 B->
appendStmt(CE, cfg->getBumpVectorContext());
811 if (alwaysAdd(ME) && cachedEntry)
812 cachedEntry->second = B;
815 retrieveAndCleanupConstructionContext(ME)) {
820 B->
appendStmt(const_cast<ObjCMessageExpr *>(ME),
821 cfg->getBumpVectorContext());
836 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
844 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
845 LocalScope::const_iterator B, LocalScope::const_iterator E);
847 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
848 LocalScope::const_iterator B,
849 LocalScope::const_iterator E);
852 prependAutomaticObjScopeEndWithTerminator(
CFGBlock *Blk,
853 LocalScope::const_iterator B,
854 LocalScope::const_iterator E);
858 cfg->getBumpVectorContext());
865 cfg->getBumpVectorContext());
891 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
896 const Expr *BoolExpr = RHSExpr;
897 bool IntFirst =
true;
907 llvm::APInt IntValue = IntLiteral->
getValue();
908 if ((IntValue == 1) || (IntValue == 0))
912 !IntValue.isNegative();
915 if (Bok == BO_GT || Bok == BO_GE) {
918 return TryResult(IntFirst == IntLarger);
922 return TryResult(IntFirst != IntLarger);
930 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
935 const Expr *BoolExpr = RHSExpr;
946 if (BitOp && (BitOp->
getOpcode() == BO_And ||
959 llvm::APInt L1 = IntLiteral->
getValue();
960 llvm::APInt L2 = IntLiteral2->
getValue();
961 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
962 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
968 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
969 llvm::APInt IntValue = IntLiteral->
getValue();
970 if ((IntValue == 1) || (IntValue == 0)) {
973 return TryResult(B->
getOpcode() != BO_EQ);
980 const llvm::APSInt &Value1,
981 const llvm::APSInt &Value2) {
982 assert(Value1.isSigned() == Value2.isSigned());
987 return TryResult(Value1 == Value2);
989 return TryResult(Value1 != Value2);
991 return TryResult(Value1 < Value2);
993 return TryResult(Value1 <= Value2);
995 return TryResult(Value1 > Value2);
997 return TryResult(Value1 >= Value2);
1014 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1022 if (!Decl1 || !Expr1)
1030 if (!Decl2 || !Expr2)
1047 llvm::APSInt L1 = L1Result.
Val.
getInt();
1048 llvm::APSInt L2 = L2Result.
Val.
getInt();
1051 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1056 const llvm::APSInt Values[] = {
1058 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1062 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1067 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1076 bool AlwaysTrue =
true, AlwaysFalse =
true;
1077 for (
const llvm::APSInt &
Value : Values) {
1078 TryResult Res1, Res2;
1079 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1080 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1082 if (!Res1.isKnown() || !Res2.isKnown())
1086 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1087 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1089 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1090 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1094 if (AlwaysTrue || AlwaysFalse) {
1097 return TryResult(AlwaysTrue);
1113 TryResult tryEvaluateBool(
Expr *S) {
1119 if (Bop->isLogicalOp()) {
1121 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1122 if (I != CachedBoolEvals.end())
1126 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
1127 CachedBoolEvals[S] =
Result;
1131 switch (Bop->getOpcode()) {
1140 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1141 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1142 if (!IntVal.getBoolValue()) {
1143 return TryResult(
false);
1147 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1148 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1149 if (!IntVal.getBoolValue()) {
1150 return TryResult(
false);
1159 return evaluateAsBooleanConditionNoCache(S);
1163 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1165 if (Bop->isLogicalOp()) {
1166 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1167 if (LHS.isKnown()) {
1170 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1171 return LHS.isTrue();
1173 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1174 if (RHS.isKnown()) {
1175 if (Bop->getOpcode() == BO_LOr)
1176 return LHS.isTrue() || RHS.isTrue();
1178 return LHS.isTrue() && RHS.isTrue();
1181 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1182 if (RHS.isKnown()) {
1185 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1186 return RHS.isTrue();
1188 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1189 if (BopRes.isKnown())
1190 return BopRes.isTrue();
1195 }
else if (Bop->isEqualityOp()) {
1196 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1197 if (BopRes.isKnown())
1198 return BopRes.isTrue();
1199 }
else if (Bop->isRelationalOp()) {
1200 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1201 if (BopRes.isKnown())
1202 return BopRes.isTrue();
1213 bool hasTrivialDestructor(
VarDecl *VD);
1218 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1220 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
1223 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
1224 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1226 if (!BuildOpts.forcedBlkExprs)
1229 if (lastLookup == stmt) {
1231 assert(cachedEntry->first == stmt);
1244 assert(!cachedEntry);
1248 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1249 if (itr == fb->end()) {
1250 cachedEntry =
nullptr;
1254 cachedEntry = &*itr;
1261 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1263 if (vat->getSizeExpr())
1266 t = vt->getElementType().getTypePtr();
1272 void CFGBuilder::consumeConstructionContext(
1274 assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1275 isa<ObjCMessageExpr>(E)) &&
"Expression cannot construct an object!");
1277 ConstructionContextMap.lookup(E)) {
1278 (void)PreviouslyStoredLayer;
1281 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1282 "Already within a different construction context!");
1284 ConstructionContextMap[E] = Layer;
1288 void CFGBuilder::findConstructionContexts(
1290 if (!BuildOpts.AddRichCXXConstructors)
1302 case Stmt::CXXConstructExprClass:
1303 case Stmt::CXXTemporaryObjectExprClass: {
1305 auto *CE = cast<CXXConstructExpr>(Child);
1306 if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
1307 findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
1310 consumeConstructionContext(Layer, CE);
1316 case Stmt::CallExprClass:
1317 case Stmt::CXXMemberCallExprClass:
1318 case Stmt::CXXOperatorCallExprClass:
1319 case Stmt::UserDefinedLiteralClass:
1320 case Stmt::ObjCMessageExprClass: {
1321 auto *E = cast<Expr>(Child);
1323 consumeConstructionContext(Layer, E);
1326 case Stmt::ExprWithCleanupsClass: {
1327 auto *Cleanups = cast<ExprWithCleanups>(Child);
1328 findConstructionContexts(Layer, Cleanups->getSubExpr());
1331 case Stmt::CXXFunctionalCastExprClass: {
1332 auto *Cast = cast<CXXFunctionalCastExpr>(Child);
1333 findConstructionContexts(Layer, Cast->getSubExpr());
1336 case Stmt::ImplicitCastExprClass: {
1337 auto *Cast = cast<ImplicitCastExpr>(Child);
1339 switch (Cast->getCastKind()) {
1341 case CK_ConstructorConversion:
1342 findConstructionContexts(Layer, Cast->getSubExpr());
1349 case Stmt::CXXBindTemporaryExprClass: {
1350 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1351 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1354 case Stmt::MaterializeTemporaryExprClass: {
1361 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1362 findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
1366 case Stmt::ConditionalOperatorClass: {
1367 auto *CO = cast<ConditionalOperator>(Child);
1374 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1378 findConstructionContexts(Layer, CO->getLHS());
1379 findConstructionContexts(Layer, CO->getRHS());
1387 void CFGBuilder::cleanupConstructionContext(
Expr *E) {
1388 assert(BuildOpts.AddRichCXXConstructors &&
1389 "We should not be managing construction contexts!");
1390 assert(ConstructionContextMap.count(E) &&
1391 "Cannot exit construction context without the context!");
1392 ConstructionContextMap.erase(E);
1401 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1409 Succ = createBlock();
1410 assert(Succ == &cfg->getExit());
1413 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1414 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1416 if (BuildOpts.AddImplicitDtors)
1418 addImplicitDtorsForDestructor(DD);
1428 for (
auto *I : llvm::reverse(CD->inits())) {
1429 B = addInitializer(I);
1440 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1441 E = BackpatchBlocks.end(); I != E; ++I ) {
1445 LabelMapTy::iterator LI = LabelMap.find(G->
getLabel());
1449 if (LI == LabelMap.end())
continue;
1451 JumpTarget JT = LI->second;
1452 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1454 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1456 const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
1457 B, I->scopePosition, JT.scopePosition);
1458 appendScopeBegin(JT.block, VD, G);
1459 addSuccessor(B, JT.block);
1463 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1464 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1465 E = AddressTakenLabels.end(); I != E; ++I ) {
1467 LabelMapTy::iterator LI = LabelMap.find(*I);
1471 if (LI == LabelMap.end())
continue;
1473 addSuccessor(B, LI->second.block);
1477 cfg->setEntry(createBlock());
1479 if (BuildOpts.AddRichCXXConstructors)
1480 assert(ConstructionContextMap.empty() &&
1481 "Not all construction contexts were cleaned up!");
1483 return std::move(cfg);
1488 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1490 if (add_successor && Succ)
1491 addSuccessor(B, Succ);
1498 CFGBlock *CFGBuilder::createNoReturnBlock() {
1501 addSuccessor(B, &cfg->getExit(), Succ);
1507 if (!BuildOpts.AddInitializers)
1510 bool HasTemporaries =
false;
1516 HasTemporaries = isa<ExprWithCleanups>(Init);
1518 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1520 TempDtorContext Context;
1521 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1527 appendInitializer(Block, I);
1530 findConstructionContexts(
1534 if (HasTemporaries) {
1537 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1539 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1561 bool *FoundMTE =
nullptr) {
1568 Init = EWC->getSubExpr();
1574 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1575 Init = MTE->GetTemporaryExpr();
1584 const Expr *SkippedInit =
1586 if (SkippedInit != Init) {
1599 void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1600 if(!BuildOpts.AddLoopExit)
1603 appendLoopExit(Block, LoopStmt);
1606 void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
1607 LocalScope::const_iterator E,
Stmt *S) {
1608 if (!BuildOpts.AddScopes)
1618 LocalScope::const_iterator
P = B.shared_parent(E);
1619 int Dist = B.distance(P);
1623 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1624 if (I.pointsToFirstDeclaredVar())
1625 DeclsWithEndedScope.insert(*I);
1628 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1629 LocalScope::const_iterator E,
1631 getDeclsWithEndedScope(B, E, S);
1632 if (BuildOpts.AddScopes)
1633 addScopesEnd(B, E, S);
1634 if (BuildOpts.AddImplicitDtors)
1635 addAutomaticObjDtors(B, E, S);
1636 if (BuildOpts.AddLifetime)
1637 addLifetimeEnds(B, E, S);
1641 void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1642 LocalScope::const_iterator E,
Stmt *S) {
1643 if (!BuildOpts.AddLifetime)
1653 LocalScope::const_iterator
P = B.shared_parent(E);
1654 int dist = B.distance(P);
1661 DeclsTrivial.reserve(dist);
1662 DeclsNonTrivial.reserve(dist);
1664 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1665 if (hasTrivialDestructor(*I))
1666 DeclsTrivial.push_back(*I);
1668 DeclsNonTrivial.push_back(*I);
1674 E = DeclsTrivial.rend();
1676 appendLifetimeEnds(Block, *I, S);
1679 I = DeclsNonTrivial.rbegin(),
1680 E = DeclsNonTrivial.rend();
1682 appendLifetimeEnds(Block, *I, S);
1686 void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
1687 LocalScope::const_iterator E,
Stmt *S) {
1690 if (BuildOpts.AddImplicitDtors)
1695 for (
auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend();
1697 appendScopeEnd(Block, *I, S);
1705 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1706 LocalScope::const_iterator E,
Stmt *S) {
1707 if (!BuildOpts.AddImplicitDtors)
1718 Decls.reserve(B.distance(E));
1719 for (LocalScope::const_iterator I = B; I != E; ++I)
1720 Decls.push_back(*I);
1725 if (hasTrivialDestructor(*I)) {
1728 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) {
1730 appendScopeEnd(Block, *I, S);
1743 if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
1744 Block = createNoReturnBlock();
1749 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I))
1750 appendScopeEnd(Block, *I, S);
1751 appendAutomaticObjDtor(Block, *I, S);
1758 assert(BuildOpts.AddImplicitDtors &&
1759 "Can be called only when dtors should be added");
1763 for (
const auto &VI : RD->
vbases()) {
1764 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1767 appendBaseDtor(Block, &VI);
1772 for (
const auto &BI : RD->
bases()) {
1773 if (!BI.isVirtual()) {
1774 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1777 appendBaseDtor(Block, &BI);
1783 for (
auto *FI : RD->
fields()) {
1787 if (AT->getSize() == 0)
1789 QT = AT->getElementType();
1793 if (!CD->hasTrivialDestructor()) {
1795 appendMemberDtor(Block, FI);
1802 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1805 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1806 return new (alloc.Allocate<LocalScope>())
1812 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1813 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1814 !BuildOpts.AddScopes)
1817 LocalScope *Scope =
nullptr;
1821 for (
auto *BI : CS->body()) {
1823 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1824 Scope = addLocalScopeForDeclStmt(DS, Scope);
1832 addLocalScopeForDeclStmt(DS);
1837 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1838 LocalScope* Scope) {
1839 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1840 !BuildOpts.AddScopes)
1843 for (
auto *DI : DS->
decls())
1844 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1845 Scope = addLocalScopeForVarDecl(VD, Scope);
1849 bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
1870 bool FoundMTE =
false;
1878 if (AT->getSize() == 0)
1880 QT = AT->getElementType();
1885 return !CD->hasDefinition() || CD->hasTrivialDestructor();
1892 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
1893 LocalScope* Scope) {
1894 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1895 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1896 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1897 !BuildOpts.AddScopes)
1906 default:
return Scope;
1909 if (BuildOpts.AddImplicitDtors) {
1910 if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
1912 Scope = createOrReuseLocalScope(Scope);
1914 ScopePos = Scope->begin();
1919 assert(BuildOpts.AddLifetime);
1921 Scope = createOrReuseLocalScope(Scope);
1923 ScopePos = Scope->begin();
1929 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
1930 LocalScope::const_iterator scopeBeginPos = ScopePos;
1931 addLocalScopeForStmt(S);
1932 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
1942 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
1943 LocalScope::const_iterator B, LocalScope::const_iterator E) {
1944 if (!BuildOpts.AddImplicitDtors)
1949 for (LocalScope::const_iterator I = B; I != E; ++I)
1959 void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
1960 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
1961 if (!BuildOpts.AddLifetime)
1966 for (LocalScope::const_iterator I = B; I != E; ++I)
1976 CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
1977 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
1978 if (!BuildOpts.AddScopes)
1983 LocalScope::const_iterator PlaceToInsert = B;
1984 for (LocalScope::const_iterator I = B; I != E; ++I)
1987 return *PlaceToInsert;
1993 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc) {
1999 if (
Expr *E = dyn_cast<Expr>(S))
2004 return VisitStmt(S, asc);
2006 case Stmt::AddrLabelExprClass:
2007 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2009 case Stmt::BinaryConditionalOperatorClass:
2010 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2012 case Stmt::BinaryOperatorClass:
2013 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2015 case Stmt::BlockExprClass:
2016 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2018 case Stmt::BreakStmtClass:
2019 return VisitBreakStmt(cast<BreakStmt>(S));
2021 case Stmt::CallExprClass:
2022 case Stmt::CXXOperatorCallExprClass:
2023 case Stmt::CXXMemberCallExprClass:
2024 case Stmt::UserDefinedLiteralClass:
2025 return VisitCallExpr(cast<CallExpr>(S), asc);
2027 case Stmt::CaseStmtClass:
2028 return VisitCaseStmt(cast<CaseStmt>(S));
2030 case Stmt::ChooseExprClass:
2031 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2033 case Stmt::CompoundStmtClass:
2034 return VisitCompoundStmt(cast<CompoundStmt>(S));
2036 case Stmt::ConditionalOperatorClass:
2037 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2039 case Stmt::ContinueStmtClass:
2040 return VisitContinueStmt(cast<ContinueStmt>(S));
2042 case Stmt::CXXCatchStmtClass:
2043 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2045 case Stmt::ExprWithCleanupsClass:
2046 return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
2048 case Stmt::CXXDefaultArgExprClass:
2049 case Stmt::CXXDefaultInitExprClass:
2059 return VisitStmt(S, asc);
2061 case Stmt::CXXBindTemporaryExprClass:
2062 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2064 case Stmt::CXXConstructExprClass:
2065 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2067 case Stmt::CXXNewExprClass:
2068 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2070 case Stmt::CXXDeleteExprClass:
2071 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2073 case Stmt::CXXFunctionalCastExprClass:
2074 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2076 case Stmt::CXXTemporaryObjectExprClass:
2077 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2079 case Stmt::CXXThrowExprClass:
2080 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2082 case Stmt::CXXTryStmtClass:
2083 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2085 case Stmt::CXXForRangeStmtClass:
2086 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2088 case Stmt::DeclStmtClass:
2089 return VisitDeclStmt(cast<DeclStmt>(S));
2091 case Stmt::DefaultStmtClass:
2092 return VisitDefaultStmt(cast<DefaultStmt>(S));
2094 case Stmt::DoStmtClass:
2095 return VisitDoStmt(cast<DoStmt>(S));
2097 case Stmt::ForStmtClass:
2098 return VisitForStmt(cast<ForStmt>(S));
2100 case Stmt::GotoStmtClass:
2101 return VisitGotoStmt(cast<GotoStmt>(S));
2103 case Stmt::IfStmtClass:
2104 return VisitIfStmt(cast<IfStmt>(S));
2106 case Stmt::ImplicitCastExprClass:
2107 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2109 case Stmt::ConstantExprClass:
2110 return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2112 case Stmt::IndirectGotoStmtClass:
2113 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2115 case Stmt::LabelStmtClass:
2116 return VisitLabelStmt(cast<LabelStmt>(S));
2118 case Stmt::LambdaExprClass:
2119 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2121 case Stmt::MaterializeTemporaryExprClass:
2122 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2125 case Stmt::MemberExprClass:
2126 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2128 case Stmt::NullStmtClass:
2131 case Stmt::ObjCAtCatchStmtClass:
2132 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2134 case Stmt::ObjCAutoreleasePoolStmtClass:
2135 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2137 case Stmt::ObjCAtSynchronizedStmtClass:
2138 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2140 case Stmt::ObjCAtThrowStmtClass:
2141 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2143 case Stmt::ObjCAtTryStmtClass:
2144 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2146 case Stmt::ObjCForCollectionStmtClass:
2147 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2149 case Stmt::ObjCMessageExprClass:
2150 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2152 case Stmt::OpaqueValueExprClass:
2155 case Stmt::PseudoObjectExprClass:
2156 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2158 case Stmt::ReturnStmtClass:
2159 case Stmt::CoreturnStmtClass:
2160 return VisitReturnStmt(S);
2162 case Stmt::SEHExceptStmtClass:
2163 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2165 case Stmt::SEHFinallyStmtClass:
2166 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2168 case Stmt::SEHLeaveStmtClass:
2169 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2171 case Stmt::SEHTryStmtClass:
2172 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2174 case Stmt::UnaryExprOrTypeTraitExprClass:
2175 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2178 case Stmt::StmtExprClass:
2179 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2181 case Stmt::SwitchStmtClass:
2182 return VisitSwitchStmt(cast<SwitchStmt>(S));
2184 case Stmt::UnaryOperatorClass:
2185 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2187 case Stmt::WhileStmtClass:
2188 return VisitWhileStmt(cast<WhileStmt>(S));
2192 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2193 if (asc.alwaysAdd(*
this, S)) {
2195 appendStmt(Block, S);
2198 return VisitChildren(S);
2207 reverse_children RChildren(S);
2208 for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
2210 if (
Stmt *Child = *I)
2218 AddStmtChoice asc) {
2219 AddressTakenLabels.insert(A->
getLabel());
2221 if (asc.alwaysAdd(*
this, A)) {
2223 appendStmt(Block, A);
2230 AddStmtChoice asc) {
2231 if (asc.alwaysAdd(*
this, U)) {
2233 appendStmt(Block, U);
2236 return Visit(U->
getSubExpr(), AddStmtChoice());
2240 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2241 appendStmt(ConfluenceBlock, B);
2246 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2247 ConfluenceBlock).first;
2250 std::pair<CFGBlock*, CFGBlock*>
2263 if (B_RHS->isLogicalOp()) {
2264 std::tie(RHSBlock, ExitBlock) =
2265 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2273 ExitBlock = RHSBlock = createBlock(
false);
2278 TryResult KnownVal = tryEvaluateBool(RHS);
2279 if (!KnownVal.isKnown())
2280 KnownVal = tryEvaluateBool(B);
2283 assert(TrueBlock == FalseBlock);
2284 addSuccessor(RHSBlock, TrueBlock);
2288 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2289 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2293 RHSBlock = addStmt(RHS);
2298 return std::make_pair(
nullptr,
nullptr);
2304 if (B_LHS->isLogicalOp()) {
2306 FalseBlock = RHSBlock;
2308 TrueBlock = RHSBlock;
2313 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2318 CFGBlock *LHSBlock = createBlock(
false);
2322 CFGBlock *EntryLHSBlock = addStmt(LHS);
2325 return std::make_pair(
nullptr,
nullptr);
2328 TryResult KnownVal = tryEvaluateBool(LHS);
2332 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2333 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2336 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2337 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2340 return std::make_pair(EntryLHSBlock, ExitBlock);
2344 AddStmtChoice asc) {
2347 return VisitLogicalOperator(B);
2351 appendStmt(Block, B);
2353 return addStmt(B->
getLHS());
2357 if (asc.alwaysAdd(*
this, B)) {
2359 appendStmt(Block, B);
2362 return Visit(B->
getRHS());
2365 if (asc.alwaysAdd(*
this, B)) {
2367 appendStmt(Block, B);
2375 return (LBlock ? LBlock : RBlock);
2378 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2379 if (asc.alwaysAdd(*
this, E)) {
2381 appendStmt(Block, E);
2393 Block = createBlock(
false);
2394 Block->setTerminator(B);
2398 if (BreakJumpTarget.block) {
2399 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2400 addSuccessor(Block, BreakJumpTarget.block);
2432 if (!boundType.
isNull()) calleeType = boundType;
2438 bool AddEHEdge =
false;
2442 if (BuildOpts.AddEHEdges)
2448 bool OmitArguments =
false;
2455 if (!FD->isVariadic())
2456 findConstructionContextsForArguments(C);
2460 if (FD->hasAttr<NoThrowAttr>())
2462 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
2463 OmitArguments =
true;
2469 if (OmitArguments) {
2470 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2471 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2473 appendStmt(Block, C);
2477 if (!NoReturn && !AddEHEdge) {
2479 appendCall(Block, C);
2481 return VisitChildren(C);
2491 Block = createNoReturnBlock();
2493 Block = createBlock();
2495 appendCall(Block, C);
2499 if (TryTerminatedBlock)
2500 addSuccessor(Block, TryTerminatedBlock);
2502 addSuccessor(Block, &cfg->getExit());
2505 return VisitChildren(C);
2509 AddStmtChoice asc) {
2510 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2511 appendStmt(ConfluenceBlock, C);
2515 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2516 Succ = ConfluenceBlock;
2522 Succ = ConfluenceBlock;
2528 Block = createBlock(
false);
2530 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2531 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2532 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2533 Block->setTerminator(C);
2538 LocalScope::const_iterator scopeBeginPos = ScopePos;
2539 addLocalScopeForStmt(C);
2544 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2553 if (
CFGBlock *newBlock = addStmt(*I))
2554 LastBlock = newBlock;
2564 AddStmtChoice asc) {
2570 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2571 appendStmt(ConfluenceBlock, C);
2575 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2581 Succ = ConfluenceBlock;
2585 if (trueExpr != opaqueValue) {
2592 LHSBlock = ConfluenceBlock;
2595 Succ = ConfluenceBlock;
2603 if (Cond->isLogicalOp())
2604 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2607 Block = createBlock(
false);
2610 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2611 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2612 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2613 Block->setTerminator(C);
2619 if (condExpr != opaqueValue)
2627 return addStmt(condExpr);
2638 return VisitDeclSubExpr(DS);
2652 cfg->addSyntheticDeclStmt(DSNew, DS);
2655 B = VisitDeclSubExpr(DSNew);
2664 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2673 bool HasTemporaries =
false;
2676 CFGBlock *blockAfterStaticInit =
nullptr;
2678 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2687 blockAfterStaticInit = Succ;
2692 Expr *Init = VD->getInit();
2694 HasTemporaries = isa<ExprWithCleanups>(Init);
2696 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2698 TempDtorContext Context;
2699 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2705 appendStmt(Block, DS);
2707 findConstructionContexts(
2717 if (HasTemporaries) {
2722 LastBlock = newBlock;
2725 if (
CFGBlock *newBlock = Visit(Init))
2726 LastBlock = newBlock;
2732 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2733 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2734 LastBlock = newBlock;
2737 maybeAddScopeBeginForVarDecl(Block, VD, DS);
2740 if (ScopePos && VD == *ScopePos)
2744 if (blockAfterStaticInit) {
2746 Block = createBlock(
false);
2747 Block->setTerminator(DS);
2748 addSuccessor(Block, blockAfterStaticInit);
2749 addSuccessor(Block, B);
2770 addLocalScopeForStmt(Init);
2775 addLocalScopeForVarDecl(VD);
2777 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
2799 if (!isa<CompoundStmt>(Else))
2800 addLocalScopeAndDtors(Else);
2802 ElseBlock = addStmt(Else);
2805 ElseBlock = sv.get();
2822 if (!isa<CompoundStmt>(Then))
2823 addLocalScopeAndDtors(Then);
2825 ThenBlock = addStmt(Then);
2831 ThenBlock = createBlock(
false);
2832 addSuccessor(ThenBlock, sv.get());
2852 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2855 Block = createBlock(
false);
2858 Block->setTerminator(I);
2861 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
2865 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
2866 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
2871 LastBlock = addStmt(I->
getCond());
2877 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2884 LastBlock = addStmt(Init);
2897 assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
2900 Block = createBlock(
false);
2902 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
2904 if (
auto *R = dyn_cast<ReturnStmt>(S))
2905 findConstructionContexts(
2911 if (!Block->hasNoReturnElement())
2912 addSuccessor(Block, &cfg->getExit());
2916 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
2929 if (!SEHExceptBlock)
2930 SEHExceptBlock = createBlock();
2932 appendStmt(SEHExceptBlock, ES);
2935 SEHExceptBlock->setLabel(ES);
2944 return SEHExceptBlock;
2948 return VisitCompoundStmt(FS->
getBlock());
2958 Block = createBlock(
false);
2959 Block->setTerminator(LS);
2963 if (SEHLeaveJumpTarget.block) {
2964 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
2965 addSuccessor(Block, SEHLeaveJumpTarget.block);
2975 CFGBlock *SEHTrySuccessor =
nullptr;
2980 SEHTrySuccessor = Block;
2981 }
else SEHTrySuccessor = Succ;
2987 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
2990 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
2997 Succ = SEHTrySuccessor;
2999 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3004 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3006 if (PrevSEHTryTerminatedBlock)
3007 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3009 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3012 Succ = SEHTrySuccessor;
3016 NewTryTerminatedBlock);
3017 cfg->addTryDispatchBlock(TryTerminatedBlock);
3023 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3025 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3036 LabelBlock = createBlock();
3038 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
3039 "label already in map");
3040 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3046 LabelBlock->setLabel(L);
3060 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3062 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3072 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3075 if (
Expr *Init = *it) {
3088 Block = createBlock(
false);
3089 Block->setTerminator(G);
3092 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3094 if (I == LabelMap.end())
3096 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3098 JumpTarget JT = I->second;
3099 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
3100 addSuccessor(Block, JT.block);
3117 addLocalScopeForStmt(Init);
3118 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3121 addLocalScopeForVarDecl(VD);
3122 LocalScope::const_iterator ContinueScopePos = ScopePos;
3124 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3133 LoopSuccessor = Block;
3135 LoopSuccessor = Succ;
3140 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3142 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3155 Block = Succ = TransitionBlock = createBlock(
false);
3156 TransitionBlock->setLoopTarget(F);
3166 assert(Block == Succ);
3174 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3175 ContinueJumpTarget.block->setLoopTarget(F);
3178 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3182 if (!isa<CompoundStmt>(F->
getBody()))
3183 addLocalScopeAndDtors(F->
getBody());
3187 BodyBlock = addStmt(F->
getBody());
3192 BodyBlock = ContinueJumpTarget.block;
3201 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3210 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
3211 if (Cond->isLogicalOp()) {
3212 std::tie(EntryConditionBlock, ExitConditionBlock) =
3213 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3218 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3219 ExitConditionBlock->setTerminator(F);
3222 TryResult KnownVal(
true);
3228 Block = ExitConditionBlock;
3229 EntryConditionBlock = addStmt(C);
3238 findConstructionContexts(
3241 appendStmt(Block, DS);
3242 EntryConditionBlock = addStmt(Init);
3243 assert(Block == EntryConditionBlock);
3244 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3248 if (Block && badCFG)
3251 KnownVal = tryEvaluateBool(C);
3255 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3258 addSuccessor(ExitConditionBlock,
3259 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3263 addSuccessor(TransitionBlock, EntryConditionBlock);
3266 Succ = EntryConditionBlock;
3272 ScopePos = LoopBeginScopePos;
3273 Block = createBlock();
3280 Succ = EntryConditionBlock;
3281 return EntryConditionBlock;
3286 AddStmtChoice asc) {
3287 findConstructionContexts(
3291 return VisitStmt(MTE, asc);
3295 if (asc.alwaysAdd(*
this, M)) {
3297 appendStmt(Block, M);
3339 LoopSuccessor = Block;
3342 LoopSuccessor = Succ;
3345 CFGBlock *ExitConditionBlock = createBlock(
false);
3353 appendStmt(ExitConditionBlock, S);
3354 Block = ExitConditionBlock;
3360 AddStmtChoice::NotAlwaysAdd);
3369 Succ = EntryConditionBlock;
3376 save_break(BreakJumpTarget);
3382 Succ = LoopBackBlock = createBlock();
3385 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3386 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3391 BodyBlock = ContinueJumpTarget.block;
3398 addSuccessor(ExitConditionBlock, BodyBlock);
3403 addSuccessor(ExitConditionBlock, LoopSuccessor);
3406 Block = createBlock();
3434 appendStmt(Block, S);
3449 appendStmt(Block, E);
3461 Semantic = OVE->getSourceExpr();
3479 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3481 addLocalScopeForVarDecl(VD);
3482 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3491 LoopSuccessor = Block;
3494 LoopSuccessor = Succ;
3497 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3506 save_break(BreakJumpTarget);
3510 Succ = TransitionBlock = createBlock(
false);
3511 TransitionBlock->setLoopTarget(W);
3512 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3515 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3518 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3522 if (!isa<CompoundStmt>(W->
getBody()))
3523 addLocalScopeAndDtors(W->
getBody());
3526 BodyBlock = addStmt(W->
getBody());
3529 BodyBlock = ContinueJumpTarget.block;
3530 else if (Block && badCFG)
3537 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3545 if (Cond->isLogicalOp()) {
3546 std::tie(EntryConditionBlock, ExitConditionBlock) =
3547 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3552 ExitConditionBlock = createBlock(
false);
3553 ExitConditionBlock->setTerminator(W);
3558 Block = ExitConditionBlock;
3559 Block = EntryConditionBlock = addStmt(C);
3568 findConstructionContexts(
3572 appendStmt(Block, DS);
3573 EntryConditionBlock = addStmt(Init);
3574 assert(Block == EntryConditionBlock);
3575 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3579 if (Block && badCFG)
3583 const TryResult& KnownVal = tryEvaluateBool(C);
3586 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3589 addSuccessor(ExitConditionBlock,
3590 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3594 addSuccessor(TransitionBlock, EntryConditionBlock);
3601 Succ = EntryConditionBlock;
3602 return EntryConditionBlock;
3620 Block = createBlock(
false);
3623 addSuccessor(Block, &cfg->getExit());
3627 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
3631 AddStmtChoice asc) {
3632 findConstructionContextsForArguments(ME);
3635 appendObjCMessage(Block, ME);
3637 return VisitChildren(ME);
3646 Block = createBlock(
false);
3648 if (TryTerminatedBlock)
3650 addSuccessor(Block, TryTerminatedBlock);
3653 addSuccessor(Block, &cfg->getExit());
3657 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
3670 LoopSuccessor = Block;
3672 LoopSuccessor = Succ;
3677 CFGBlock *ExitConditionBlock = createBlock(
false);
3678 CFGBlock *EntryConditionBlock = ExitConditionBlock;
3686 Block = ExitConditionBlock;
3687 EntryConditionBlock = addStmt(C);
3695 Succ = EntryConditionBlock;
3698 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
3708 save_break(BreakJumpTarget);
3711 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
3714 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3721 if (!isa<CompoundStmt>(D->
getBody()))
3722 addLocalScopeAndDtors(D->
getBody());
3725 BodyBlock = addStmt(D->
getBody());
3728 BodyBlock = EntryConditionBlock;
3741 CFGBlock *LoopBackBlock = createBlock();
3744 if (!KnownVal.isFalse())
3746 addSuccessor(ExitConditionBlock, LoopBackBlock);
3748 addSuccessor(ExitConditionBlock,
nullptr);
3753 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3771 Block = createBlock(
false);
3772 Block->setTerminator(C);
3776 if (ContinueJumpTarget.block) {
3777 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
3778 addSuccessor(Block, ContinueJumpTarget.block);
3786 AddStmtChoice asc) {
3787 if (asc.alwaysAdd(*
this, E)) {
3789 appendStmt(Block, E);
3797 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
3798 lastBlock = addStmt(VA->getSizeExpr());
3806 if (asc.alwaysAdd(*
this, SE)) {
3808 appendStmt(Block, SE);
3816 CFGBlock *SwitchSuccessor =
nullptr;
3824 addLocalScopeForStmt(Init);
3829 addLocalScopeForVarDecl(VD);
3831 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
3836 SwitchSuccessor = Block;
3837 }
else SwitchSuccessor = Succ;
3841 save_default(DefaultCaseBlock);
3847 DefaultCaseBlock = SwitchSuccessor;
3850 SwitchTerminatedBlock = createBlock(
false);
3854 Succ = SwitchSuccessor;
3855 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3860 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
3869 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
3871 bool b = tryEvaluate(Terminator->
getCond(), result);
3873 b ? &result :
nullptr);
3877 if (!isa<CompoundStmt>(Terminator->
getBody()))
3878 addLocalScopeAndDtors(Terminator->
getBody());
3880 addStmt(Terminator->
getBody());
3892 bool SwitchAlwaysHasSuccessor =
false;
3893 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3896 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3897 !SwitchAlwaysHasSuccessor);
3900 SwitchTerminatedBlock->setTerminator(Terminator);
3901 Block = SwitchTerminatedBlock;
3910 LastBlock = addStmt(Init);
3911 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
3918 LastBlock = addStmt(Init);
3931 bool addCase =
false;
3933 if (!switchExclusivelyCovered) {
3937 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
3939 if (condInt == lhsInt) {
3941 switchExclusivelyCovered =
true;
3943 else if (condInt > lhsInt) {
3946 const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
3947 if (V2 >= condInt) {
3949 switchExclusivelyCovered =
true;
3963 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
3969 while (isa<CaseStmt>(Sub)) {
3970 CFGBlock *currentBlock = createBlock(
false);
3974 addSuccessor(LastBlock, currentBlock);
3976 TopBlock = currentBlock;
3978 addSuccessor(SwitchTerminatedBlock,
3981 ? currentBlock :
nullptr);
3983 LastBlock = currentBlock;
3984 CS = cast<CaseStmt>(Sub);
3993 CaseBlock = createBlock();
4004 assert(SwitchTerminatedBlock);
4005 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4013 addSuccessor(LastBlock, CaseBlock);
4027 DefaultCaseBlock = Block;
4029 if (!DefaultCaseBlock)
4030 DefaultCaseBlock = createBlock();
4034 DefaultCaseBlock->setLabel(Terminator);
4049 Succ = DefaultCaseBlock;
4051 return DefaultCaseBlock;
4062 TrySuccessor = Block;
4063 }
else TrySuccessor = Succ;
4065 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4068 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4072 bool HasCatchAll =
false;
4075 Succ = TrySuccessor;
4081 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4086 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4089 if (PrevTryTerminatedBlock)
4090 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4092 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4096 Succ = TrySuccessor;
4100 cfg->addTryDispatchBlock(TryTerminatedBlock);
4102 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4118 LocalScope::const_iterator BeginScopePos = ScopePos;
4119 addLocalScopeForVarDecl(VD);
4120 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4128 CatchBlock = createBlock();
4134 appendStmt(CatchBlock, CS);
4169 addLocalScopeForStmt(Range);
4171 addLocalScopeForStmt(
Begin);
4173 addLocalScopeForStmt(
End);
4174 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4176 LocalScope::const_iterator ContinueScopePos = ScopePos;
4184 LoopSuccessor = Block;
4186 LoopSuccessor = Succ;
4191 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4194 CFGBlock *ConditionBlock = createBlock(
false);
4199 Block = ConditionBlock;
4200 CFGBlock *BeginConditionBlock = addStmt(C);
4203 assert(BeginConditionBlock == ConditionBlock &&
4204 "condition block in for-range was unexpectedly complex");
4205 (void)BeginConditionBlock;
4210 Succ = ConditionBlock;
4213 TryResult KnownVal(
true);
4216 KnownVal = tryEvaluateBool(S->
getCond());
4229 Succ = addStmt(S->
getInc());
4232 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4236 ContinueJumpTarget.block->setLoopTarget(S);
4256 addSuccessor(ConditionBlock,
4257 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
4262 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4265 Block = createBlock();
4275 AddStmtChoice asc) {
4276 if (BuildOpts.AddTemporaryDtors) {
4279 TempDtorContext Context;
4280 VisitForTemporaryDtors(E->
getSubExpr(),
false, Context);
4284 asc = asc.withAlwaysAdd(
true);
4290 AddStmtChoice asc) {
4291 if (asc.alwaysAdd(*
this, E)) {
4293 appendStmt(Block, E);
4295 findConstructionContexts(
4300 asc = asc.withAlwaysAdd(
false);
4306 AddStmtChoice asc) {
4310 findConstructionContextsForArguments(C);
4313 appendConstructor(Block, C);
4315 return VisitChildren(C);
4319 AddStmtChoice asc) {
4321 appendStmt(Block, NE);
4323 findConstructionContexts(
4330 if (BuildOpts.AddCXXNewAllocator)
4331 appendNewAllocator(Block, NE);
4344 AddStmtChoice asc) {
4346 appendStmt(Block, DE);
4353 appendDeleteDtor(Block, RD, DE);
4357 return VisitChildren(DE);
4361 AddStmtChoice asc) {
4362 if (asc.alwaysAdd(*
this, E)) {
4364 appendStmt(Block, E);
4366 asc = asc.withAlwaysAdd(
false);
4372 AddStmtChoice asc) {
4376 findConstructionContextsForArguments(C);
4379 appendConstructor(Block, C);
4380 return VisitChildren(C);
4384 AddStmtChoice asc) {
4385 if (asc.alwaysAdd(*
this, E)) {
4387 appendStmt(Block, E);
4389 return Visit(E->
getSubExpr(), AddStmtChoice());
4393 return Visit(E->
getSubExpr(), AddStmtChoice());
4398 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4401 IBlock = createBlock(
false);
4402 cfg->setIndirectGotoBlock(IBlock);
4410 Block = createBlock(
false);
4411 Block->setTerminator(I);
4412 addSuccessor(Block, IBlock);
4416 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool BindToTemporary,
4417 TempDtorContext &Context) {
4418 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
4427 return VisitChildrenForTemporaryDtors(E, Context);
4429 case Stmt::BinaryOperatorClass:
4430 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4433 case Stmt::CXXBindTemporaryExprClass:
4434 return VisitCXXBindTemporaryExprForTemporaryDtors(
4435 cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
4437 case Stmt::BinaryConditionalOperatorClass:
4438 case Stmt::ConditionalOperatorClass:
4439 return VisitConditionalOperatorForTemporaryDtors(
4440 cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
4442 case Stmt::ImplicitCastExprClass:
4444 E = cast<CastExpr>(E)->getSubExpr();
4447 case Stmt::CXXFunctionalCastExprClass:
4449 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4452 case Stmt::ConstantExprClass:
4453 E = cast<ConstantExpr>(E)->getSubExpr();
4456 case Stmt::ParenExprClass:
4457 E = cast<ParenExpr>(E)->getSubExpr();
4460 case Stmt::MaterializeTemporaryExprClass: {
4466 E =
const_cast<Expr *
>(
4467 cast<MaterializeTemporaryExpr>(E)
4468 ->GetTemporaryExpr()
4469 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4471 for (
const Expr *CommaLHS : CommaLHSs) {
4472 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
4478 case Stmt::BlockExprClass:
4483 case Stmt::LambdaExprClass: {
4486 auto *LE = cast<LambdaExpr>(E);
4488 for (
Expr *Init : LE->capture_inits()) {
4490 if (
CFGBlock *R = VisitForTemporaryDtors(
4491 Init,
false, Context))
4498 case Stmt::CXXDefaultArgExprClass:
4499 E = cast<CXXDefaultArgExpr>(E)->getExpr();
4502 case Stmt::CXXDefaultInitExprClass:
4503 E = cast<CXXDefaultInitExpr>(E)->getExpr();
4508 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
4509 TempDtorContext &Context) {
4510 if (isa<LambdaExpr>(E)) {
4522 if (
CFGBlock *R = VisitForTemporaryDtors(Child,
false, Context))
4528 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
4531 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4532 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
4533 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
4534 RHSExecuted.negate();
4539 TempDtorContext RHSContext(
4541 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
4542 InsertTempDtorDecisionBlock(RHSContext);
4550 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4551 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4552 return LHSBlock ? LHSBlock : RHSBlock;
4558 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4559 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4560 return RHSBlock ? RHSBlock : LHSBlock;
4563 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
4567 if (!BindToTemporary) {
4579 Block = createNoReturnBlock();
4580 }
else if (Context.needsTempDtorBranch()) {
4584 Block = createBlock();
4588 if (Context.needsTempDtorBranch()) {
4589 Context.setDecisionPoint(Succ, E);
4591 appendTemporaryDtor(Block, E);
4598 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
4600 if (!Context.TerminatorExpr) {
4604 assert(Context.TerminatorExpr);
4605 CFGBlock *Decision = createBlock(
false);
4607 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
4608 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
4609 !Context.KnownExecuted.isTrue());
4613 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
4615 TempDtorContext &Context) {
4616 VisitForTemporaryDtors(E->
getCond(),
false, Context);
4619 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
4620 TryResult NegatedVal = ConditionVal;
4621 if (NegatedVal.isKnown()) NegatedVal.negate();
4623 TempDtorContext TrueContext(
4625 VisitForTemporaryDtors(E->
getTrueExpr(), BindToTemporary, TrueContext);
4628 Block = ConditionBlock;
4629 Succ = ConditionSucc;
4630 TempDtorContext FalseContext(
4632 VisitForTemporaryDtors(E->
getFalseExpr(), BindToTemporary, FalseContext);
4634 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
4635 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
4636 }
else if (TrueContext.TerminatorExpr) {
4638 InsertTempDtorDecisionBlock(TrueContext);
4640 InsertTempDtorDecisionBlock(FalseContext);
4649 bool first_block = begin() == end();
4653 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
4654 Blocks.push_back(Mem, BlkBVC);
4658 Entry = Exit = &back();
4667 CFGBuilder Builder(C, BO);
4668 return Builder.buildCFG(D, Statement);
4683 llvm_unreachable(
"getDestructorDecl should only be used with " 4686 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
4704 cast<CXXRecordDecl>(recordType->
getDecl());
4708 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
4717 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
4726 llvm_unreachable(
"getKind() returned bogus value");
4740 : ReachableBlock(IsReachable ? B : nullptr),
4741 UnreachableBlock(!IsReachable ? B : nullptr,
4742 B && IsReachable ? AB_Normal : AB_Unreachable) {}
4745 : ReachableBlock(B),
4746 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
4747 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
4755 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
4757 Succs.push_back(Succ, C);
4770 if (S->isAllEnumCasesCovered()) {
4772 if (!L || !isa<CaseStmt>(L))
4788 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
4789 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
4793 signed currentBlock = 0;
4794 unsigned currStmt = 0;
4803 BI != BEnd; ++BI, ++j ) {
4805 const Stmt *stmt= SE->getStmt();
4806 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
4810 case Stmt::DeclStmtClass:
4811 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
4813 case Stmt::IfStmtClass: {
4814 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
4819 case Stmt::ForStmtClass: {
4820 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
4825 case Stmt::WhileStmtClass: {
4827 cast<WhileStmt>(
stmt)->getConditionVariable();
4832 case Stmt::SwitchStmtClass: {
4834 cast<SwitchStmt>(
stmt)->getConditionVariable();
4839 case Stmt::CXXCatchStmtClass: {
4841 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
4854 ~StmtPrinterHelper()
override =
default;
4856 const LangOptions &getLangOpts()
const {
return LangOpts; }
4857 void setBlockID(
signed i) { currentBlock = i; }
4858 void setStmtID(
unsigned i) { currStmt = i; }
4860 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
4861 StmtMapTy::iterator I = StmtMap.find(S);
4863 if (I == StmtMap.end())
4866 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4867 && I->second.second == currStmt) {
4871 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4875 bool handleDecl(
const Decl *D, raw_ostream &OS) {
4876 DeclMapTy::iterator I = DeclMap.find(D);
4878 if (I == DeclMap.end())
4881 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
4882 && I->second.second == currStmt) {
4886 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
4891 class CFGBlockTerminatorPrint
4892 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
4894 StmtPrinterHelper* Helper;
4898 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4900 : OS(os), Helper(helper), Policy(Policy) {
4904 void VisitIfStmt(
IfStmt *I) {
4911 void VisitStmt(
Stmt *Terminator) {
4917 OS <<
"static init " << VD->
getName();
4920 void VisitForStmt(
ForStmt *F) {
4939 void VisitDoStmt(
DoStmt *D) {
4940 OS <<
"do ... while ";
4945 void VisitSwitchStmt(
SwitchStmt *Terminator) {
4960 Cond->printPretty(OS, Helper, Policy);
4961 OS <<
" ? ... : ...";
4965 OS <<
"__builtin_choose_expr( ";
4967 Cond->printPretty(OS, Helper, Policy);
4994 llvm_unreachable(
"Invalid logical operator.");
4998 void VisitExpr(
Expr *E) {
5005 OS <<
"(Temp Dtor) ";
5022 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5026 OS <<
" (Base initializer)";
5028 OS <<
" (Delegating initializer)";
5030 OS <<
" (Member initializer)";
5034 StmtPrinterHelper &Helper,
5040 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5047 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5049 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5053 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5054 Stmts.push_back(SDSCC->getDeclStmt());
5058 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5059 Stmts.push_back(CDSCC->getDeclStmt());
5060 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5064 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5065 Stmts.push_back(NECC->getCXXNewExpr());
5069 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5070 Stmts.push_back(RSCC->getReturnStmt());
5075 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5076 Stmts.push_back(RSCC->getReturnStmt());
5077 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5081 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5082 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5083 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5087 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5088 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5089 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5090 Stmts.push_back(TOCC->getConstructorAfterElision());
5094 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5095 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5097 Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
5100 Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
5101 OS <<
"+" << ACC->getIndex();
5108 Helper.handledStmt(const_cast<Stmt *>(I), OS);
5112 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5115 const Stmt *S = CS->getStmt();
5116 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5119 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5123 if (Children.begin() != Children.end()) {
5132 if (B->getOpcode() == BO_Comma) {
5134 Helper.handledStmt(B->getRHS(),OS);
5142 if (isa<CXXOperatorCallExpr>(S))
5143 OS <<
" (OperatorCall)";
5144 OS <<
" (CXXRecordTypedCall";
5147 }
else if (isa<CXXOperatorCallExpr>(S)) {
5148 OS <<
" (OperatorCall)";
5149 }
else if (isa<CXXBindTemporaryExpr>(S)) {
5150 OS <<
" (BindTemporary)";
5152 OS <<
" (CXXConstructExpr";
5156 OS <<
", " << CCE->getType().getAsString() <<
")";
5157 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5158 OS <<
" (" << CE->getStmtClassName() <<
", " 5159 << CE->getCastKindName()
5160 <<
", " << CE->getType().getAsString()
5172 const VarDecl *VD = DE->getVarDecl();
5173 Helper.handleDecl(VD, OS);
5183 OS <<
" (Implicit destructor)\n";
5185 const VarDecl *VD = DE->getVarDecl();
5186 Helper.handleDecl(VD, OS);
5188 OS <<
" (Lifetime ends)\n";
5190 const Stmt *LoopStmt = LE->getLoopStmt();
5193 OS <<
"CFGScopeBegin(";
5194 if (
const VarDecl *VD = SB->getVarDecl())
5198 OS <<
"CFGScopeEnd(";
5199 if (
const VarDecl *VD = SE->getVarDecl())
5203 OS <<
"CFGNewAllocator(";
5204 if (
const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
5205 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
5213 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
5214 OS <<
"->~" << RD->
getName().str() <<
"()";
5215 OS <<
" (Implicit destructor)\n";
5219 OS <<
" (Base object destructor)\n";
5221 const FieldDecl *FD = ME->getFieldDecl();
5223 OS <<
"this->" << FD->
getName();
5225 OS <<
" (Member object destructor)\n";
5230 OS <<
"() (Temporary object destructor)\n";
5236 StmtPrinterHelper &Helper,
bool print_edges,
5242 OS.changeColor(raw_ostream::YELLOW,
true);
5247 OS <<
" (ENTRY)]\n";
5248 else if (&B == &cfg->
getExit())
5251 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
5253 OS <<
" (NORETURN)]\n";
5277 }
else if (isa<DefaultStmt>(
Label))
5293 llvm_unreachable(
"Invalid label statement in CFGBlock.");
5302 I != E ; ++I, ++j ) {
5307 OS << llvm::format(
"%3d", j) <<
": ";
5309 Helper.setStmtID(j);
5317 OS.changeColor(raw_ostream::GREEN);
5321 Helper.setBlockID(-1);
5324 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
5335 const raw_ostream::Colors Color = raw_ostream::BLUE;
5337 OS.changeColor(Color);
5345 OS.changeColor(Color);
5353 bool Reachable =
true;
5356 B = I->getPossiblyUnreachableBlock();
5361 OS <<
"(Unreachable)";
5372 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
5374 OS.changeColor(Color);
5382 OS.changeColor(Color);
5391 bool Reachable =
true;
5394 B = I->getPossiblyUnreachableBlock();
5400 OS <<
"(Unreachable)";
5416 print(llvm::errs(), LO, ShowColors);
5421 StmtPrinterHelper Helper(
this, LO);
5424 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
5427 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
5429 if (&(**I) == &getEntry() || &(**I) == &getExit())
5432 print_block(OS,
this, **I, Helper,
true, ShowColors);
5436 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
5443 bool ShowColors)
const {
5444 print(llvm::errs(), cfg, LO, ShowColors);
5455 StmtPrinterHelper Helper(cfg, LO);
5456 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
5463 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
5468 Stmt *Terminator = this->Terminator;
5478 case Stmt::CXXForRangeStmtClass:
5479 E = cast<CXXForRangeStmt>(Terminator)->getCond();
5482 case Stmt::ForStmtClass:
5483 E = cast<ForStmt>(Terminator)->getCond();
5486 case Stmt::WhileStmtClass:
5487 E = cast<WhileStmt>(Terminator)->getCond();
5490 case Stmt::DoStmtClass:
5491 E = cast<DoStmt>(Terminator)->getCond();
5494 case Stmt::IfStmtClass:
5495 E = cast<IfStmt>(Terminator)->getCond();
5498 case Stmt::ChooseExprClass:
5499 E = cast<ChooseExpr>(Terminator)->getCond();
5502 case Stmt::IndirectGotoStmtClass:
5503 E = cast<IndirectGotoStmt>(Terminator)->getTarget();
5506 case Stmt::SwitchStmtClass:
5507 E = cast<SwitchStmt>(Terminator)->getCond();
5510 case Stmt::BinaryConditionalOperatorClass:
5511 E = cast<BinaryConditionalOperator>(Terminator)->getCond();
5514 case Stmt::ConditionalOperatorClass:
5515 E = cast<ConditionalOperator>(Terminator)->getCond();
5518 case Stmt::BinaryOperatorClass:
5519 E = cast<BinaryOperator>(Terminator)->getLHS();
5522 case Stmt::ObjCForCollectionStmtClass:
5542 StmtPrinterHelper H(
this, LO);
5544 llvm::ViewGraph(
this,
"CFG");
5545 GraphHelper =
nullptr;
5557 std::string OutSStr;
5558 llvm::raw_string_ostream Out(OutSStr);
5559 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
5560 std::string& OutStr = Out.str();
5562 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
5565 for (
unsigned i = 0; i != OutStr.length(); ++i)
5566 if (OutStr[i] ==
'\n') {
5568 OutStr.insert(OutStr.begin()+i+1,
'l');
unsigned getNumSemanticExprs() const
const Expr * getSubExpr() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Defines the clang::ASTContext interface.
const BlockDecl * getBlockDecl() const
Represents C++ allocator call.
const CXXDestructorDecl * getDestructor() const
Represents a function declaration or definition.
Expr * getInit() const
Get the initializer.
CompoundStmt * getBlock() const
A class which contains all the information about a particular captured value.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
static SourceLocation GetEndLoc(Decl *D)
AdjacentBlocks::const_iterator const_pred_iterator
iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr *> &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
ElementList::iterator iterator
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
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...
bool EvaluateAsInt(EvalResult &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...
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.
unsigned succ_size() const
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
const char * getName() const
Describes how types, statements, expressions, and declarations should be printed. ...
Defines the Objective-C statement AST node classes.
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E)
A C++ throw-expression (C++ [except.throw]).
Represents an expression – generally a full-expression – that introduces cleanups to be run at the ...
static bool isAssignmentOp(Opcode Opc)
Defines the clang::Expr interface and subclasses for C++ expressions.
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
DeclStmt * getConditionVariableDeclStmt()
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void setLoopTarget(const Stmt *loopTarget)
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)
field_range fields() const
Represents a member of a struct/union/class.
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
Defines the ExceptionSpecificationType enumeration and various utility functions. ...
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
bool isReferenceType() const
const CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
void setTerminator(CFGTerminator Term)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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...
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Expr * getInitializer()
The initializer of this new-expression.
static QualType getReferenceInitTemporaryType(const Expr *Init, bool *FoundMTE=nullptr)
Retrieve the type of the temporary object whose lifetime was extended by a local reference with the g...
A builtin binary operation expression such as "x + y" or "x <= y".
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
static bool areExprTypesCompatible(const Expr *E1, const Expr *E2)
For an expression x == Foo && x == Bar, this determines whether the Foo and Bar are either of the sam...
void print(raw_ostream &OS, const CFG *cfg, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFGBlock that outputs to an ostream.
Scope - A scope is a transient data structure that is used while parsing the program.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
CaseStmt - Represent a case statement.
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
FieldDecl * getAnyMember() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
arg_iterator placement_arg_end()
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.
ConstantExpr - An expression that occurs in a constant context.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool isNoReturn(ASTContext &astContext) const
This represents one expression.
Defines the clang::LangOptions interface.
Stmt * getTerminatorCondition(bool StripParens=true)
static std::tuple< const DeclRefExpr *, BinaryOperatorKind, const Expr * > tryNormalizeBinaryOperator(const BinaryOperator *B)
Tries to interpret a binary operator into Decl Op Expr form, if Expr is an integer literal or an enum...
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
Represents a C++ functional cast expression that builds a temporary object.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
VarDecl * getExceptionDecl() const
unsigned getNumInits() const
Represents C++ constructor call.
QualType getArgumentType() const
const CompoundStmt * getSynchBody() const
ElementList::const_iterator const_iterator
bool isTemporaryDtorsBranch() const
Represents Objective-C's @synchronized statement.
DOTGraphTraits(bool isSimple=false)
CXXTryStmt - A C++ try block, including all handlers.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
std::reverse_iterator< body_iterator > reverse_body_iterator
static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXCtorInitializer *I)
LabelDecl * getLabel() const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
An expression that sends a message to the given Objective-C object or class.
SwitchCase * getSwitchCaseList()
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
static bool CanThrow(Expr *E, ASTContext &Ctx)
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Represents C++ object destructor implicitly generated for base object in destructor.
Expr * getTrueExpr() const
The result type of a method or function.
QualType getDestroyedType() const
Retrieve the type being destroyed.
const Expr * getSubExpr() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
DoStmt - This represents a 'do/while' stmt.
static const ConstructionContext * createFromLayers(BumpVectorContext &C, const ConstructionContextLayer *TopLayer)
Consume the construction context layer, together with its parent layers, and wrap it up into a comple...
std::reverse_iterator< decl_iterator > reverse_decl_iterator
RecordDecl * getDecl() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
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.
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.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
DeclStmt * getConditionVariableDeclStmt()
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
bool isArgumentType() const
Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Defines various enumerations that describe declaration and type specifiers.
AddrLabelExpr - The GNU address of label extension, representing &&label.
ast_type_traits::DynTypedNode Node
pred_iterator pred_begin()
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Dataflow Directional Tag Classes.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
EvalResult is a struct with detailed info about an evaluated expression.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
ArrayRef< Capture > captures() const
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
static const VariableArrayType * FindVA(const Type *t)
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
const Expr * getInit() const
unsigned pred_size() const
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.
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
Represents a single point (AST node) in the program that requires attention during construction of an...
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
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).
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\, const ASTContext *Context=nullptr) const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
void viewCFG(const LangOptions &LO) const
Defines the clang::SourceLocation class and associated facilities.
ConstructionContext's subclasses describe different ways of constructing an object in C++...
Represents a C++ struct/union/class.
ContinueStmt - This represents a continue.
reverse_body_iterator body_rbegin()
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Expr * getFilterExpr() const
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
CXXCatchStmt - This represents a C++ catch block.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr.type.conv]).
bool operator!=(CanQual< T > x, CanQual< U > y)
WhileStmt - This represents a 'while' stmt.
Represents a top-level expression in a basic block.
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Represents CFGBlock terminator statement.
CompoundStmt * getTryBlock()
bool AddRichCXXConstructors
Represents C++ object destructor implicitly generated for member object in destructor.
Represents Objective-C's @try ... @catch ... @finally statement.
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Full-expression storage duration (for temporaries).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
bool isBuiltinAssumeFalse(const ASTContext &Ctx) const
Return true if this is a call to __assume() or __builtin_assume() with a non-value-dependent constant...
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getQualifiedNameAsString() const
static Decl::Kind getKind(const Decl *D)
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument for this lambda expression...
A reference to a declared variable, function, enum, etc.
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
BreakStmt - This represents a break.
Represents C++ base or member initializer from constructor's initialization list. ...
Expr * getSemanticExpr(unsigned index)
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
Represents a C array with a specified size that is not an integer-constant-expression.
CFGBlock * createBlock()
Create a new block in the CFG.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
DeclStmt * getBeginStmt()
bool isFunctionPointerType() const
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const LangOptions & getLangOpts() const
Represents Objective-C's @autoreleasepool Statement.
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
CompoundStmt * getTryBlock() const
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Defines enum values for all the target-independent builtin functions.
CompoundStmt * getBlock() const
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt...
QualType getType() const
Retrieves the type of the base class.
Represents the point where a loop ends.