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/STLExtras.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallPtrSet.h"
46#include "llvm/ADT/SmallVector.h"
47#include "llvm/Support/Allocator.h"
48#include "llvm/Support/Casting.h"
49#include "llvm/Support/Compiler.h"
50#include "llvm/Support/DOTGraphTraits.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/Format.h"
53#include "llvm/Support/GraphWriter.h"
54#include "llvm/Support/SaveAndRestore.h"
55#include "llvm/Support/raw_ostream.h"
67 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
68 if (
Expr *Ex = VD->getInit())
69 return Ex->getSourceRange().getEnd();
84 if (
const auto *CE = dyn_cast<CastExpr>(E)) {
85 if (CE->getCastKind() != CK_IntegralCast)
91 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
92 if (UO->getOpcode() != UO_Minus)
97 return isa<IntegerLiteral>(E);
108 return isa<EnumConstantDecl>(DR->getDecl()) ? DR :
nullptr;
117static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
124 if (Constant ==
nullptr) {
128 else if (Op == BO_GE)
130 else if (Op == BO_LT)
132 else if (Op == BO_LE)
139 return std::make_tuple(MaybeDecl, Op, Constant);
151 if (isa<DeclRefExpr>(E1) != isa<DeclRefExpr>(E2))
155 if (!isa<DeclRefExpr>(E1))
160 assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
161 auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
162 auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
164 assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
168 assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
190 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
192 AddStmtChoice(Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
194 bool alwaysAdd(CFGBuilder &builder,
199 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
200 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
234 class const_iterator {
235 const LocalScope*
Scope =
nullptr;
239 unsigned VarIter = 0;
245 const_iterator() =
default;
249 const_iterator(
const LocalScope& S,
unsigned I)
250 :
Scope(&S), VarIter(I) {
253 if (VarIter == 0 &&
Scope)
257 VarDecl *
const* operator->()
const {
258 assert(
Scope &&
"Dereferencing invalid iterator is not allowed");
259 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
260 return &
Scope->Vars[VarIter - 1];
263 const VarDecl *getFirstVarInScope()
const {
264 assert(
Scope &&
"Dereferencing invalid iterator is not allowed");
265 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
266 return Scope->Vars[0];
270 return *this->operator->();
273 const_iterator &operator++() {
277 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
283 const_iterator operator++(
int) {
284 const_iterator
P = *
this;
289 bool operator==(
const const_iterator &rhs)
const {
290 return Scope == rhs.
Scope && VarIter == rhs.VarIter;
292 bool operator!=(
const const_iterator &rhs)
const {
293 return !(*
this == rhs);
296 explicit operator bool()
const {
297 return *
this != const_iterator();
301 const_iterator shared_parent(const_iterator L);
302 bool pointsToFirstDeclaredVar() {
return VarIter == 1; }
309 AutomaticVarsTy Vars;
318 : ctx(
std::move(ctx)), Vars(this->ctx, 4), Prev(
P) {}
321 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
324 Vars.push_back(VD, ctx);
333int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
335 const_iterator F = *
this;
336 while (F.Scope != L.Scope) {
337 assert(F != const_iterator() &&
338 "L iterator is not reachable from F iterator.");
342 D += F.VarIter - L.VarIter;
350LocalScope::const_iterator
351LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
354 ScopesOfL.insert(L.Scope);
355 if (L == const_iterator())
360 const_iterator F = *
this;
362 if (ScopesOfL.count(F.Scope))
364 assert(F != const_iterator() &&
365 "L iterator is not reachable from F iterator.");
375struct BlockScopePosPair {
377 LocalScope::const_iterator scopePosition;
379 BlockScopePosPair() =
default;
380 BlockScopePosPair(
CFGBlock *
b, LocalScope::const_iterator scopePos)
381 : block(
b), scopePosition(scopePos) {}
392 TryResult() =
default;
393 TryResult(
bool b) : X(
b ? 1 : 0) {}
395 bool isTrue()
const {
return X == 1; }
396 bool isFalse()
const {
return X == 0; }
397 bool isKnown()
const {
return X >= 0; }
408 if (!R1.isKnown() || !R2.isKnown())
410 return TryResult(R1.isTrue() && R2.isTrue());
415class reverse_children {
420 reverse_children(
Stmt *S);
424 iterator begin()
const {
return children.rbegin(); }
425 iterator end()
const {
return children.rend(); }
430reverse_children::reverse_children(
Stmt *S) {
431 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
432 children = CE->getRawSubExprs();
435 switch (S->getStmtClass()) {
437 case Stmt::InitListExprClass: {
448 llvm::append_range(childrenBuf, S->children());
451 children = childrenBuf;
470 using JumpTarget = BlockScopePosPair;
471 using JumpSource = BlockScopePosPair;
474 std::unique_ptr<CFG> cfg;
482 JumpTarget ContinueJumpTarget;
483 JumpTarget BreakJumpTarget;
484 JumpTarget SEHLeaveJumpTarget;
485 CFGBlock *SwitchTerminatedBlock =
nullptr;
486 CFGBlock *DefaultCaseBlock =
nullptr;
492 CFGBlock *TryTerminatedBlock =
nullptr;
495 LocalScope::const_iterator ScopePos;
498 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
503 using BackpatchBlocksTy = std::vector<JumpSource>;
504 BackpatchBlocksTy BackpatchBlocks;
508 LabelSetTy AddressTakenLabels;
513 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
514 ConstructionContextMap;
517 DeclsWithEndedScopeSetTy DeclsWithEndedScope;
523 bool switchExclusivelyCovered =
false;
526 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
527 const Stmt *lastLookup =
nullptr;
531 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
532 CachedBoolEvalsTy CachedBoolEvals;
537 : Context(astContext), cfg(new
CFG()), BuildOpts(buildOpts) {}
540 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
577 AddStmtChoice asc,
bool ExternallyDestructed);
589 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
619 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
620 bool ExternallyDestructed =
false);
629 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
630 appendScopeBegin(B, VD, S);
661 struct TempDtorContext {
662 TempDtorContext() =
default;
663 TempDtorContext(TryResult KnownExecuted)
664 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
672 bool needsTempDtorBranch()
const {
673 return IsConditional && !TerminatorExpr;
683 const bool IsConditional =
false;
684 const TryResult KnownExecuted =
true;
691 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
692 TempDtorContext &Context);
693 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
694 TempDtorContext &Context);
696 bool ExternallyDestructed,
697 TempDtorContext &Context);
698 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
700 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
702 TempDtorContext &Context);
703 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
728 template <
typename CallLikeExpr,
729 typename = std::enable_if_t<
730 std::is_base_of_v<CallExpr, CallLikeExpr> ||
731 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
732 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
733 void findConstructionContextsForArguments(CallLikeExpr *E) {
734 for (
unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
735 Expr *Arg = E->getArg(i);
737 findConstructionContexts(
747 void cleanupConstructionContext(
Expr *E);
749 void autoCreateBlock() {
if (!Block)
Block = createBlock(); }
750 CFGBlock *createBlock(
bool add_successor =
true);
754 return Visit(S, AddStmtChoice::AlwaysAdd);
758 void addLoopExit(
const Stmt *LoopStmt);
759 void addAutomaticObjDtors(LocalScope::const_iterator B,
760 LocalScope::const_iterator E,
Stmt *S);
761 void addLifetimeEnds(LocalScope::const_iterator B,
762 LocalScope::const_iterator E,
Stmt *S);
763 void addAutomaticObjHandling(LocalScope::const_iterator B,
764 LocalScope::const_iterator E,
Stmt *S);
766 void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
769 void getDeclsWithEndedScope(LocalScope::const_iterator B,
770 LocalScope::const_iterator E,
Stmt *S);
773 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
775 void addLocalScopeForStmt(
Stmt *S);
776 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
777 LocalScope*
Scope =
nullptr);
778 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
780 void addLocalScopeAndDtors(
Stmt *S);
790 cleanupConstructionContext(E);
798 if (alwaysAdd(S) && cachedEntry)
799 cachedEntry->second = B;
802 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
808 retrieveAndCleanupConstructionContext(CE)) {
814 B->
appendStmt(CE, cfg->getBumpVectorContext());
818 if (alwaysAdd(CE) && cachedEntry)
819 cachedEntry->second = B;
822 retrieveAndCleanupConstructionContext(CE)) {
828 B->
appendStmt(CE, cfg->getBumpVectorContext());
848 if (alwaysAdd(ME) && cachedEntry)
849 cachedEntry->second = B;
852 retrieveAndCleanupConstructionContext(ME)) {
858 cfg->getBumpVectorContext());
873 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
881 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
882 LocalScope::const_iterator B, LocalScope::const_iterator E);
884 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
885 LocalScope::const_iterator B,
886 LocalScope::const_iterator E);
889 prependAutomaticObjScopeEndWithTerminator(
CFGBlock *Blk,
890 LocalScope::const_iterator B,
891 LocalScope::const_iterator E);
895 cfg->getBumpVectorContext());
902 cfg->getBumpVectorContext());
928 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
932 const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
933 const Expr *BoolExpr = RHSExpr;
934 bool IntFirst =
true;
936 IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
944 llvm::APInt IntValue = IntLiteral->
getValue();
945 if ((IntValue == 1) || (IntValue == 0))
949 !IntValue.isNegative();
952 if (Bok == BO_GT || Bok == BO_GE) {
955 return TryResult(IntFirst == IntLarger);
959 return TryResult(IntFirst != IntLarger);
967 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
971 std::optional<llvm::APInt> IntLiteral1 =
972 getIntegerLiteralSubexpressionValue(LHSExpr);
973 const Expr *BoolExpr = RHSExpr;
976 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
984 if (BitOp && (BitOp->
getOpcode() == BO_And ||
989 std::optional<llvm::APInt> IntLiteral2 =
990 getIntegerLiteralSubexpressionValue(LHSExpr2);
993 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
999 (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
1001 (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1005 return TryResult(B->
getOpcode() != BO_EQ);
1008 if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1011 return TryResult(B->
getOpcode() != BO_EQ);
1023 std::optional<llvm::APInt>
1024 getIntegerLiteralSubexpressionValue(
const Expr *E) {
1027 if (
const auto *UnOp = dyn_cast<UnaryOperator>(E->
IgnoreParens())) {
1032 if (
const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1037 switch (UnOp->getOpcode()) {
1047 assert(
false &&
"Unexpected unary operator!");
1048 return std::nullopt;
1051 }
else if (
const auto *IntLiteral =
1055 return std::nullopt;
1059 const llvm::APSInt &Value1,
1060 const llvm::APSInt &Value2) {
1061 assert(Value1.isSigned() == Value2.isSigned());
1066 return TryResult(Value1 == Value2);
1068 return TryResult(Value1 != Value2);
1070 return TryResult(Value1 < Value2);
1072 return TryResult(Value1 <= Value2);
1074 return TryResult(Value1 > Value2);
1076 return TryResult(Value1 >= Value2);
1096 const Expr *DeclExpr1;
1097 const Expr *NumExpr1;
1101 if (!DeclExpr1 || !NumExpr1)
1104 const Expr *DeclExpr2;
1105 const Expr *NumExpr2;
1109 if (!DeclExpr2 || !NumExpr2)
1126 llvm::APSInt L1 = L1Result.
Val.
getInt();
1127 llvm::APSInt L2 = L2Result.
Val.
getInt();
1130 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1135 const llvm::APSInt Values[] = {
1137 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1141 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1146 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1155 bool AlwaysTrue =
true, AlwaysFalse =
true;
1158 bool LHSAlwaysTrue =
true, LHSAlwaysFalse =
true;
1159 bool RHSAlwaysTrue =
true, RHSAlwaysFalse =
true;
1160 for (
const llvm::APSInt &
Value : Values) {
1161 TryResult Res1, Res2;
1162 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1163 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1165 if (!Res1.isKnown() || !Res2.isKnown())
1169 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1170 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1172 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1173 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1176 LHSAlwaysTrue &= Res1.isTrue();
1177 LHSAlwaysFalse &= Res1.isFalse();
1178 RHSAlwaysTrue &= Res2.isTrue();
1179 RHSAlwaysFalse &= Res2.isFalse();
1182 if (AlwaysTrue || AlwaysFalse) {
1183 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1184 !RHSAlwaysFalse && BuildOpts.
Observer)
1186 return TryResult(AlwaysTrue);
1192 TryResult checkIncorrectBitwiseOrOperator(
const BinaryOperator *B) {
1193 const Expr *LHSConstant =
1195 const Expr *RHSConstant =
1198 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1201 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1207 if (Result.Val.getInt() == 0)
1213 return TryResult(
true);
1220 return !S->isTypeDependent() &&
1221 !S->isValueDependent() &&
1222 S->EvaluateAsRValue(outResult, *Context);
1227 TryResult tryEvaluateBool(
Expr *S) {
1229 S->isTypeDependent() || S->isValueDependent())
1233 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1235 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1236 if (I != CachedBoolEvals.end())
1240 TryResult Result = evaluateAsBooleanConditionNoCache(S);
1241 CachedBoolEvals[S] = Result;
1245 switch (Bop->getOpcode()) {
1254 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1255 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1256 if (!IntVal.getBoolValue()) {
1257 return TryResult(
false);
1261 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1262 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1263 if (!IntVal.getBoolValue()) {
1264 return TryResult(
false);
1273 return evaluateAsBooleanConditionNoCache(S);
1277 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1279 if (Bop->isLogicalOp()) {
1280 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1281 if (LHS.isKnown()) {
1284 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1285 return LHS.isTrue();
1287 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1288 if (RHS.isKnown()) {
1289 if (Bop->getOpcode() == BO_LOr)
1290 return LHS.isTrue() || RHS.isTrue();
1292 return LHS.isTrue() && RHS.isTrue();
1295 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1296 if (RHS.isKnown()) {
1299 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1300 return RHS.isTrue();
1302 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1303 if (BopRes.isKnown())
1304 return BopRes.isTrue();
1309 }
else if (Bop->isEqualityOp()) {
1310 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1311 if (BopRes.isKnown())
1312 return BopRes.isTrue();
1313 }
else if (Bop->isRelationalOp()) {
1314 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1315 if (BopRes.isKnown())
1316 return BopRes.isTrue();
1317 }
else if (Bop->getOpcode() == BO_Or) {
1318 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1319 if (BopRes.isKnown())
1320 return BopRes.isTrue();
1331 bool hasTrivialDestructor(
VarDecl *VD);
1342 while (
const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1343 AILEInit = E->getSubExpr();
1348inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1350 return builder.alwaysAdd(
stmt) || kind == AlwaysAdd;
1353bool CFGBuilder::alwaysAdd(
const Stmt *
stmt) {
1359 if (lastLookup ==
stmt) {
1361 assert(cachedEntry->first ==
stmt);
1374 assert(!cachedEntry);
1378 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(
stmt);
1379 if (itr == fb->end()) {
1380 cachedEntry =
nullptr;
1384 cachedEntry = &*itr;
1391 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1393 if (vat->getSizeExpr())
1396 t = vt->getElementType().getTypePtr();
1402void CFGBuilder::consumeConstructionContext(
1404 assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1405 isa<ObjCMessageExpr>(E)) &&
"Expression cannot construct an object!");
1407 ConstructionContextMap.lookup(E)) {
1408 (void)PreviouslyStoredLayer;
1411 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1412 "Already within a different construction context!");
1414 ConstructionContextMap[E] = Layer;
1418void CFGBuilder::findConstructionContexts(
1431 switch(Child->getStmtClass()) {
1432 case Stmt::CXXConstructExprClass:
1433 case Stmt::CXXTemporaryObjectExprClass: {
1435 auto *CE = cast<CXXConstructExpr>(Child);
1437 findConstructionContexts(withExtraLayer(CE), CE->
getArg(0));
1440 consumeConstructionContext(Layer, CE);
1446 case Stmt::CallExprClass:
1447 case Stmt::CXXMemberCallExprClass:
1448 case Stmt::CXXOperatorCallExprClass:
1449 case Stmt::UserDefinedLiteralClass:
1450 case Stmt::ObjCMessageExprClass: {
1451 auto *E = cast<Expr>(Child);
1453 consumeConstructionContext(Layer, E);
1456 case Stmt::ExprWithCleanupsClass: {
1457 auto *Cleanups = cast<ExprWithCleanups>(Child);
1458 findConstructionContexts(Layer, Cleanups->getSubExpr());
1461 case Stmt::CXXFunctionalCastExprClass: {
1462 auto *
Cast = cast<CXXFunctionalCastExpr>(Child);
1463 findConstructionContexts(Layer,
Cast->getSubExpr());
1466 case Stmt::ImplicitCastExprClass: {
1467 auto *
Cast = cast<ImplicitCastExpr>(Child);
1469 switch (
Cast->getCastKind()) {
1471 case CK_ConstructorConversion:
1472 findConstructionContexts(Layer,
Cast->getSubExpr());
1479 case Stmt::CXXBindTemporaryExprClass: {
1480 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1481 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1484 case Stmt::MaterializeTemporaryExprClass: {
1491 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1492 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1496 case Stmt::ConditionalOperatorClass: {
1497 auto *CO = cast<ConditionalOperator>(Child);
1504 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1508 findConstructionContexts(Layer, CO->getLHS());
1509 findConstructionContexts(Layer, CO->getRHS());
1512 case Stmt::InitListExprClass: {
1513 auto *ILE = cast<InitListExpr>(Child);
1514 if (ILE->isTransparent()) {
1515 findConstructionContexts(Layer, ILE->getInit(0));
1521 case Stmt::ParenExprClass: {
1524 auto *PE = cast<ParenExpr>(Child);
1525 findConstructionContexts(Layer, PE->getSubExpr());
1533void CFGBuilder::cleanupConstructionContext(
Expr *E) {
1535 "We should not be managing construction contexts!");
1536 assert(ConstructionContextMap.count(E) &&
1537 "Cannot exit construction context without the context!");
1538 ConstructionContextMap.erase(E);
1547std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1555 Succ = createBlock();
1556 assert(Succ == &cfg->getExit());
1560 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1564 addImplicitDtorsForDestructor(DD);
1584 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1586 for (
auto *I : llvm::reverse(CD->inits())) {
1588 I->isBaseInitializer() && I->isBaseVirtual()) {
1592 VBaseSucc = Succ = B ? B : &cfg->getExit();
1593 Block = createBlock();
1595 B = addInitializer(I);
1605 addSuccessor(B,
Block,
true);
1614 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1615 E = BackpatchBlocks.end(); I != E; ++I ) {
1619 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1622 if (LI == LabelMap.end())
1624 JumpTarget JT = LI->second;
1625 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1627 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1629 const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
1630 B, I->scopePosition, JT.scopePosition);
1631 appendScopeBegin(JT.block, VD, G);
1632 addSuccessor(B, JT.block);
1635 CFGBlock *Successor = (I+1)->block;
1636 for (
auto *L : G->labels()) {
1637 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1640 if (LI == LabelMap.end())
1642 JumpTarget JT = LI->second;
1644 if (JT.block == Successor)
1646 addSuccessor(B, JT.block);
1653 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1654 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1655 E = AddressTakenLabels.end(); I != E; ++I ) {
1657 LabelMapTy::iterator LI = LabelMap.find(*I);
1661 if (LI == LabelMap.end())
continue;
1663 addSuccessor(B, LI->second.block);
1667 cfg->setEntry(createBlock());
1670 assert(ConstructionContextMap.empty() &&
1671 "Not all construction contexts were cleaned up!");
1673 return std::move(cfg);
1678CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1680 if (add_successor && Succ)
1681 addSuccessor(B, Succ);
1688CFGBlock *CFGBuilder::createNoReturnBlock() {
1691 addSuccessor(B, &cfg->getExit(), Succ);
1700 bool HasTemporaries =
false;
1706 HasTemporaries = isa<ExprWithCleanups>(Init);
1710 TempDtorContext Context;
1711 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1717 appendInitializer(
Block, I);
1723 dyn_cast<ArrayInitLoopExpr>(Init));
1725 findConstructionContexts(
1727 AILEInit ? AILEInit : Init);
1729 if (HasTemporaries) {
1732 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1756 bool *FoundMTE =
nullptr) {
1759 Init = Init->IgnoreParens();
1763 Init = EWC->getSubExpr();
1769 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1770 Init = MTE->getSubExpr();
1779 const Expr *SkippedInit =
1780 Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
1781 if (SkippedInit != Init) {
1789 return Init->getType();
1794void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1798 appendLoopExit(
Block, LoopStmt);
1801void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
1802 LocalScope::const_iterator E,
Stmt *S) {
1813 LocalScope::const_iterator
P = B.shared_parent(E);
1814 int Dist = B.distance(
P);
1818 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1819 if (I.pointsToFirstDeclaredVar())
1820 DeclsWithEndedScope.insert(*I);
1823void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1824 LocalScope::const_iterator E,
1826 getDeclsWithEndedScope(B, E, S);
1828 addScopesEnd(B, E, S);
1830 addAutomaticObjDtors(B, E, S);
1832 addLifetimeEnds(B, E, S);
1836void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1837 LocalScope::const_iterator E,
Stmt *S) {
1848 LocalScope::const_iterator
P = B.shared_parent(E);
1849 int dist = B.distance(
P);
1856 DeclsTrivial.reserve(dist);
1857 DeclsNonTrivial.reserve(dist);
1859 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1860 if (hasTrivialDestructor(*I))
1861 DeclsTrivial.push_back(*I);
1863 DeclsNonTrivial.push_back(*I);
1868 for (
VarDecl *VD : llvm::reverse(DeclsTrivial))
1869 appendLifetimeEnds(
Block, VD, S);
1871 for (
VarDecl *VD : llvm::reverse(DeclsNonTrivial))
1872 appendLifetimeEnds(
Block, VD, S);
1876void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
1877 LocalScope::const_iterator E,
Stmt *S) {
1885 for (
VarDecl *VD : llvm::reverse(DeclsWithEndedScope))
1886 appendScopeEnd(
Block, VD, S);
1892void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1893 LocalScope::const_iterator E,
Stmt *S) {
1905 Decls.reserve(B.distance(E));
1906 for (LocalScope::const_iterator I = B; I != E; ++I)
1907 Decls.push_back(*I);
1909 for (
VarDecl *VD : llvm::reverse(Decls)) {
1910 if (hasTrivialDestructor(VD)) {
1913 if (BuildOpts.
AddScopes && DeclsWithEndedScope.count(VD)) {
1915 appendScopeEnd(
Block, VD, S);
1929 Block = createNoReturnBlock();
1934 if (BuildOpts.
AddScopes && DeclsWithEndedScope.count(VD))
1935 appendScopeEnd(
Block, VD, S);
1936 appendAutomaticObjDtor(
Block, VD, S);
1944 "Can be called only when dtors should be added");
1948 for (
const auto &VI : RD->
vbases()) {
1952 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1955 appendBaseDtor(
Block, &VI);
1960 for (
const auto &BI : RD->
bases()) {
1961 if (!BI.isVirtual()) {
1962 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1965 appendBaseDtor(
Block, &BI);
1971 for (
auto *FI : RD->
fields()) {
1976 if (AT->getSize() == 0)
1978 QT = AT->getElementType();
1984 appendMemberDtor(
Block, FI);
1991LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1994 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1995 return new (alloc.Allocate<LocalScope>())
2001void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
2006 LocalScope *
Scope =
nullptr;
2010 for (
auto *BI : CS->body()) {
2012 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2020 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
2021 addLocalScopeForDeclStmt(DS);
2026LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
2027 LocalScope*
Scope) {
2032 for (
auto *DI : DS->
decls())
2033 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
2038bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
2059 bool FoundMTE =
false;
2067 if (AT->getSize() == 0)
2069 QT = AT->getElementType();
2081LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
2082 LocalScope*
Scope) {
2084 "AddImplicitDtors and AddLifetime cannot be used at the same time");
2094 if (!hasTrivialDestructor(VD) || BuildOpts.
AddScopes) {
2098 ScopePos =
Scope->begin();
2107 ScopePos =
Scope->begin();
2113void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
2114 LocalScope::const_iterator scopeBeginPos = ScopePos;
2115 addLocalScopeForStmt(S);
2116 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2126void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
2127 LocalScope::const_iterator B, LocalScope::const_iterator E) {
2133 for (LocalScope::const_iterator I = B; I != E; ++I)
2143void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
2144 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2150 for (LocalScope::const_iterator I = B; I != E; ++I) {
2162CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
2163 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2169 LocalScope::const_iterator PlaceToInsert = B;
2170 for (LocalScope::const_iterator I = B; I != E; ++I)
2173 return *PlaceToInsert;
2179CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc,
2180 bool ExternallyDestructed) {
2186 if (
Expr *E = dyn_cast<Expr>(S))
2187 S = E->IgnoreParens();
2190 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2191 return VisitOMPExecutableDirective(D, asc);
2193 switch (S->getStmtClass()) {
2195 return VisitStmt(S, asc);
2197 case Stmt::ImplicitValueInitExprClass:
2200 return VisitStmt(S, asc);
2202 case Stmt::InitListExprClass:
2203 return VisitInitListExpr(cast<InitListExpr>(S), asc);
2205 case Stmt::AttributedStmtClass:
2206 return VisitAttributedStmt(cast<AttributedStmt>(S), asc);
2208 case Stmt::AddrLabelExprClass:
2209 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2211 case Stmt::BinaryConditionalOperatorClass:
2212 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2214 case Stmt::BinaryOperatorClass:
2215 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2217 case Stmt::BlockExprClass:
2218 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2220 case Stmt::BreakStmtClass:
2221 return VisitBreakStmt(cast<BreakStmt>(S));
2223 case Stmt::CallExprClass:
2224 case Stmt::CXXOperatorCallExprClass:
2225 case Stmt::CXXMemberCallExprClass:
2226 case Stmt::UserDefinedLiteralClass:
2227 return VisitCallExpr(cast<CallExpr>(S), asc);
2229 case Stmt::CaseStmtClass:
2230 return VisitCaseStmt(cast<CaseStmt>(S));
2232 case Stmt::ChooseExprClass:
2233 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2235 case Stmt::CompoundStmtClass:
2236 return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);
2238 case Stmt::ConditionalOperatorClass:
2239 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2241 case Stmt::ContinueStmtClass:
2242 return VisitContinueStmt(cast<ContinueStmt>(S));
2244 case Stmt::CXXCatchStmtClass:
2245 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2247 case Stmt::ExprWithCleanupsClass:
2248 return VisitExprWithCleanups(cast<ExprWithCleanups>(S),
2249 asc, ExternallyDestructed);
2251 case Stmt::CXXDefaultArgExprClass:
2252 case Stmt::CXXDefaultInitExprClass:
2262 return VisitStmt(S, asc);
2264 case Stmt::CXXBindTemporaryExprClass:
2265 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2267 case Stmt::CXXConstructExprClass:
2268 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2270 case Stmt::CXXNewExprClass:
2271 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2273 case Stmt::CXXDeleteExprClass:
2274 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2276 case Stmt::CXXFunctionalCastExprClass:
2277 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2279 case Stmt::CXXTemporaryObjectExprClass:
2280 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2282 case Stmt::CXXThrowExprClass:
2283 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2285 case Stmt::CXXTryStmtClass:
2286 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2288 case Stmt::CXXTypeidExprClass:
2289 return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);
2291 case Stmt::CXXForRangeStmtClass:
2292 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2294 case Stmt::DeclStmtClass:
2295 return VisitDeclStmt(cast<DeclStmt>(S));
2297 case Stmt::DefaultStmtClass:
2298 return VisitDefaultStmt(cast<DefaultStmt>(S));
2300 case Stmt::DoStmtClass:
2301 return VisitDoStmt(cast<DoStmt>(S));
2303 case Stmt::ForStmtClass:
2304 return VisitForStmt(cast<ForStmt>(S));
2306 case Stmt::GotoStmtClass:
2307 return VisitGotoStmt(cast<GotoStmt>(S));
2309 case Stmt::GCCAsmStmtClass:
2310 return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
2312 case Stmt::IfStmtClass:
2313 return VisitIfStmt(cast<IfStmt>(S));
2315 case Stmt::ImplicitCastExprClass:
2316 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2318 case Stmt::ConstantExprClass:
2319 return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2321 case Stmt::IndirectGotoStmtClass:
2322 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2324 case Stmt::LabelStmtClass:
2325 return VisitLabelStmt(cast<LabelStmt>(S));
2327 case Stmt::LambdaExprClass:
2328 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2330 case Stmt::MaterializeTemporaryExprClass:
2331 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2334 case Stmt::MemberExprClass:
2335 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2337 case Stmt::NullStmtClass:
2340 case Stmt::ObjCAtCatchStmtClass:
2341 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2343 case Stmt::ObjCAutoreleasePoolStmtClass:
2344 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2346 case Stmt::ObjCAtSynchronizedStmtClass:
2347 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2349 case Stmt::ObjCAtThrowStmtClass:
2350 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2352 case Stmt::ObjCAtTryStmtClass:
2353 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2355 case Stmt::ObjCForCollectionStmtClass:
2356 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2358 case Stmt::ObjCMessageExprClass:
2359 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2361 case Stmt::OpaqueValueExprClass:
2364 case Stmt::PseudoObjectExprClass:
2365 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2367 case Stmt::ReturnStmtClass:
2368 case Stmt::CoreturnStmtClass:
2369 return VisitReturnStmt(S);
2371 case Stmt::CoyieldExprClass:
2372 case Stmt::CoawaitExprClass:
2373 return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);
2375 case Stmt::SEHExceptStmtClass:
2376 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2378 case Stmt::SEHFinallyStmtClass:
2379 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2381 case Stmt::SEHLeaveStmtClass:
2382 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2384 case Stmt::SEHTryStmtClass:
2385 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2387 case Stmt::UnaryExprOrTypeTraitExprClass:
2388 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2391 case Stmt::StmtExprClass:
2392 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2394 case Stmt::SwitchStmtClass:
2395 return VisitSwitchStmt(cast<SwitchStmt>(S));
2397 case Stmt::UnaryOperatorClass:
2398 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2400 case Stmt::WhileStmtClass:
2401 return VisitWhileStmt(cast<WhileStmt>(S));
2403 case Stmt::ArrayInitLoopExprClass:
2404 return VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);
2408CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2409 if (asc.alwaysAdd(*
this, S)) {
2411 appendStmt(
Block, S);
2414 return VisitChildren(S);
2423 reverse_children RChildren(S);
2424 for (
Stmt *Child : RChildren) {
2433 if (asc.alwaysAdd(*
this, ILE)) {
2435 appendStmt(
Block, ILE);
2439 reverse_children RChildren(ILE);
2440 for (
Stmt *Child : RChildren) {
2446 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2447 if (
Stmt *Child = DIE->getExpr())
2456 AddStmtChoice asc) {
2457 AddressTakenLabels.insert(A->
getLabel());
2459 if (asc.alwaysAdd(*
this, A)) {
2461 appendStmt(
Block, A);
2468 bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->
getAttrs());
2469 assert((!isFallthrough || isa<NullStmt>(A->
getSubStmt())) &&
2470 "expected fallthrough not to have children");
2471 return isFallthrough;
2475 AddStmtChoice asc) {
2486 appendStmt(
Block, A);
2489 return VisitChildren(A);
2493 if (asc.alwaysAdd(*
this,
U)) {
2498 if (
U->getOpcode() == UO_LNot)
2499 tryEvaluateBool(
U->getSubExpr()->IgnoreParens());
2501 return Visit(
U->getSubExpr(), AddStmtChoice());
2506 appendStmt(ConfluenceBlock, B);
2511 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2512 ConfluenceBlock).first;
2515std::pair<CFGBlock*, CFGBlock*>
2528 if (B_RHS->isLogicalOp()) {
2529 std::tie(RHSBlock, ExitBlock) =
2530 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2538 ExitBlock = RHSBlock = createBlock(
false);
2543 TryResult KnownVal = tryEvaluateBool(RHS);
2544 if (!KnownVal.isKnown())
2545 KnownVal = tryEvaluateBool(B);
2548 assert(TrueBlock == FalseBlock);
2549 addSuccessor(RHSBlock, TrueBlock);
2553 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2554 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2558 RHSBlock = addStmt(RHS);
2563 return std::make_pair(
nullptr,
nullptr);
2569 if (B_LHS->isLogicalOp()) {
2571 FalseBlock = RHSBlock;
2573 TrueBlock = RHSBlock;
2578 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2583 CFGBlock *LHSBlock = createBlock(
false);
2587 CFGBlock *EntryLHSBlock = addStmt(LHS);
2590 return std::make_pair(
nullptr,
nullptr);
2593 TryResult KnownVal = tryEvaluateBool(LHS);
2597 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2598 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2601 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2602 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2605 return std::make_pair(EntryLHSBlock, ExitBlock);
2609 AddStmtChoice asc) {
2612 return VisitLogicalOperator(B);
2616 appendStmt(
Block, B);
2618 return addStmt(B->
getLHS());
2622 if (asc.alwaysAdd(*
this, B)) {
2624 appendStmt(
Block, B);
2627 return Visit(B->
getRHS());
2630 if (asc.alwaysAdd(*
this, B)) {
2632 appendStmt(
Block, B);
2643 return (LBlock ? LBlock : RBlock);
2646CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2647 if (asc.alwaysAdd(*
this, E)) {
2649 appendStmt(
Block, E);
2661 Block = createBlock(
false);
2662 Block->setTerminator(B);
2666 if (BreakJumpTarget.block) {
2667 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2668 addSuccessor(
Block, BreakJumpTarget.block);
2692 QualType calleeType =
C->getCallee()->getType();
2698 if (!boundType.
isNull()) calleeType = boundType;
2704 bool AddEHEdge =
false;
2714 bool OmitArguments =
false;
2721 if (!FD->isVariadic())
2722 findConstructionContextsForArguments(
C);
2724 if (FD->isNoReturn() ||
C->isBuiltinAssumeFalse(*Context))
2726 if (FD->
hasAttr<NoThrowAttr>())
2728 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2729 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2730 OmitArguments =
true;
2733 if (!
CanThrow(
C->getCallee(), *Context))
2736 if (OmitArguments) {
2737 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2738 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2741 return Visit(
C->getCallee());
2744 if (!NoReturn && !AddEHEdge) {
2748 return VisitChildren(
C);
2758 Block = createNoReturnBlock();
2760 Block = createBlock();
2766 if (TryTerminatedBlock)
2767 addSuccessor(
Block, TryTerminatedBlock);
2769 addSuccessor(
Block, &cfg->getExit());
2772 return VisitChildren(
C);
2776 AddStmtChoice asc) {
2778 appendStmt(ConfluenceBlock,
C);
2782 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2783 Succ = ConfluenceBlock;
2785 CFGBlock *LHSBlock = Visit(
C->getLHS(), alwaysAdd);
2789 Succ = ConfluenceBlock;
2791 CFGBlock *RHSBlock = Visit(
C->getRHS(), alwaysAdd);
2795 Block = createBlock(
false);
2797 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2798 addSuccessor(
Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2799 addSuccessor(
Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2801 return addStmt(
C->getCond());
2805 bool ExternallyDestructed) {
2806 LocalScope::const_iterator scopeBeginPos = ScopePos;
2807 addLocalScopeForStmt(
C);
2809 if (!
C->body_empty() && !isa<ReturnStmt>(*
C->body_rbegin())) {
2812 addAutomaticObjHandling(ScopePos, scopeBeginPos,
C);
2817 for (
Stmt *S : llvm::reverse(
C->body())) {
2820 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2821 ExternallyDestructed);
2824 LastBlock = newBlock;
2829 ExternallyDestructed =
false;
2836 AddStmtChoice asc) {
2843 appendStmt(ConfluenceBlock,
C);
2847 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2853 Succ = ConfluenceBlock;
2856 const Expr *trueExpr =
C->getTrueExpr();
2857 if (trueExpr != opaqueValue) {
2858 LHSBlock = Visit(
C->getTrueExpr(), alwaysAdd);
2864 LHSBlock = ConfluenceBlock;
2867 Succ = ConfluenceBlock;
2868 CFGBlock *RHSBlock = Visit(
C->getFalseExpr(), alwaysAdd);
2874 dyn_cast<BinaryOperator>(
C->getCond()->IgnoreParens()))
2875 if (Cond->isLogicalOp())
2876 return VisitLogicalOperator(Cond,
C, LHSBlock, RHSBlock).first;
2879 Block = createBlock(
false);
2882 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2883 addSuccessor(
Block, LHSBlock, !KnownVal.isFalse());
2884 addSuccessor(
Block, RHSBlock, !KnownVal.isTrue());
2886 Expr *condExpr =
C->getCond();
2891 if (condExpr != opaqueValue)
2899 return addStmt(condExpr);
2910 return VisitDeclSubExpr(DS);
2924 cfg->addSyntheticDeclStmt(DSNew, DS);
2927 B = VisitDeclSubExpr(DSNew);
2936 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2938 if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl())) {
2940 const Type *T = TND->getUnderlyingType().getTypePtr();
2945 appendStmt(
Block, DS);
2949 VA =
FindVA(VA->getElementType().getTypePtr())) {
2950 if (
CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
2951 LastBlock = NewBlock;
2964 bool HasTemporaries =
false;
2967 CFGBlock *blockAfterStaticInit =
nullptr;
2978 blockAfterStaticInit = Succ;
2985 HasTemporaries = isa<ExprWithCleanups>(Init);
2989 TempDtorContext Context;
2990 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2997 if (
const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
2998 for (
auto *BD : llvm::reverse(DD->bindings())) {
2999 if (
auto *VD = BD->getHoldingVar()) {
3003 cfg->addSyntheticDeclStmt(DSNew, DS);
3004 Block = VisitDeclSubExpr(DSNew);
3010 appendStmt(
Block, DS);
3014 const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init);
3016 findConstructionContexts(
3018 AILE ? AILE->getSubExpr() : Init);
3026 if (HasTemporaries) {
3031 LastBlock = newBlock;
3034 if (
CFGBlock *newBlock = Visit(Init))
3035 LastBlock = newBlock;
3043 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
3044 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3045 LastBlock = newBlock;
3048 maybeAddScopeBeginForVarDecl(
Block, VD, DS);
3051 if (ScopePos && VD == *ScopePos)
3055 if (blockAfterStaticInit) {
3057 Block = createBlock(
false);
3058 Block->setTerminator(DS);
3059 addSuccessor(
Block, blockAfterStaticInit);
3060 addSuccessor(
Block, B);
3081 addLocalScopeForStmt(Init);
3086 addLocalScopeForVarDecl(VD);
3088 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3110 if (!isa<CompoundStmt>(Else))
3111 addLocalScopeAndDtors(Else);
3113 ElseBlock = addStmt(Else);
3116 ElseBlock = sv.get();
3133 if (!isa<CompoundStmt>(Then))
3134 addLocalScopeAndDtors(Then);
3136 ThenBlock = addStmt(Then);
3142 ThenBlock = createBlock(
false);
3143 addSuccessor(ThenBlock, sv.get());
3163 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
3166 Block = createBlock(
false);
3169 Block->setTerminator(I);
3174 KnownVal = tryEvaluateBool(I->
getCond());
3178 addSuccessor(
Block, ThenBlock, !KnownVal.isFalse());
3179 addSuccessor(
Block, ElseBlock, !KnownVal.isTrue());
3184 LastBlock = addStmt(I->
getCond());
3190 LastBlock = addStmt(
const_cast<DeclStmt *
>(DS));
3197 LastBlock = addStmt(Init);
3210 assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
3213 Block = createBlock(
false);
3215 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3217 if (
auto *R = dyn_cast<ReturnStmt>(S))
3218 findConstructionContexts(
3224 if (!
Block->hasNoReturnElement())
3225 addSuccessor(
Block, &cfg->getExit());
3228 appendStmt(
Block, S);
3231 if (
ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3232 if (
Expr *O = RS->getRetValue())
3233 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3243 if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV))
3252 AddStmtChoice asc) {
3256 if (asc.alwaysAdd(*
this, E)) {
3258 appendStmt(
Block, E);
3282 if (!SEHExceptBlock)
3283 SEHExceptBlock = createBlock();
3285 appendStmt(SEHExceptBlock, ES);
3297 return SEHExceptBlock;
3301 return VisitCompoundStmt(FS->getBlock(),
false);
3311 Block = createBlock(
false);
3312 Block->setTerminator(LS);
3316 if (SEHLeaveJumpTarget.block) {
3317 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3318 addSuccessor(
Block, SEHLeaveJumpTarget.block);
3328 CFGBlock *SEHTrySuccessor =
nullptr;
3333 SEHTrySuccessor =
Block;
3334 }
else SEHTrySuccessor = Succ;
3340 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3343 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3350 Succ = SEHTrySuccessor;
3352 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3357 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3359 if (PrevSEHTryTerminatedBlock)
3360 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3362 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3365 Succ = SEHTrySuccessor;
3368 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3369 cfg->addTryDispatchBlock(TryTerminatedBlock);
3375 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3377 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3388 LabelBlock = createBlock();
3390 assert(!LabelMap.contains(L->
getDecl()) &&
"label already in map");
3391 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3411 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3413 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3423 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3428 it != et; ++it, ++Idx) {
3429 if (
Expr *Init = *it) {
3433 dyn_cast<ArrayInitLoopExpr>(Init));
3436 cfg->getBumpVectorContext(), {E, Idx}),
3437 AILEInit ? AILEInit : Init);
3451 Block = createBlock(
false);
3452 Block->setTerminator(G);
3455 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3457 if (I == LabelMap.end())
3459 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3461 JumpTarget JT = I->second;
3462 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
3463 addSuccessor(
Block, JT.block);
3474 return VisitStmt(G, asc);
3481 Block = createBlock();
3482 Block->setTerminator(G);
3484 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3487 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3488 return VisitChildren(G);
3502 addLocalScopeForStmt(Init);
3503 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3506 addLocalScopeForVarDecl(VD);
3507 LocalScope::const_iterator ContinueScopePos = ScopePos;
3509 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3518 LoopSuccessor =
Block;
3520 LoopSuccessor = Succ;
3525 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3527 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3540 Block = Succ = TransitionBlock = createBlock(
false);
3541 TransitionBlock->setLoopTarget(F);
3551 assert(
Block == Succ);
3559 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3560 ContinueJumpTarget.block->setLoopTarget(F);
3563 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3567 if (!isa<CompoundStmt>(F->
getBody()))
3568 addLocalScopeAndDtors(F->
getBody());
3572 BodyBlock = addStmt(F->
getBody());
3577 BodyBlock = ContinueJumpTarget.block;
3586 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3595 dyn_cast_or_null<BinaryOperator>(
C ?
C->IgnoreParens() :
nullptr))
3597 std::tie(EntryConditionBlock, ExitConditionBlock) =
3598 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3603 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3604 ExitConditionBlock->setTerminator(F);
3607 TryResult KnownVal(
true);
3613 Block = ExitConditionBlock;
3614 EntryConditionBlock = addStmt(
C);
3623 findConstructionContexts(
3626 appendStmt(
Block, DS);
3627 EntryConditionBlock = addStmt(Init);
3628 assert(
Block == EntryConditionBlock);
3629 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3633 if (
Block && badCFG)
3636 KnownVal = tryEvaluateBool(
C);
3640 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3643 addSuccessor(ExitConditionBlock,
3644 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3648 addSuccessor(TransitionBlock, EntryConditionBlock);
3651 Succ = EntryConditionBlock;
3657 ScopePos = LoopBeginScopePos;
3658 Block = createBlock();
3665 Succ = EntryConditionBlock;
3666 return EntryConditionBlock;
3671 AddStmtChoice asc) {
3672 findConstructionContexts(
3676 return VisitStmt(MTE, asc);
3680 if (asc.alwaysAdd(*
this, M)) {
3682 appendStmt(
Block, M);
3724 LoopSuccessor =
Block;
3727 LoopSuccessor = Succ;
3730 CFGBlock *ExitConditionBlock = createBlock(
false);
3738 appendStmt(ExitConditionBlock, S);
3739 Block = ExitConditionBlock;
3744 CFGBlock *EntryConditionBlock = Visit(S->getElement(),
3745 AddStmtChoice::NotAlwaysAdd);
3754 Succ = EntryConditionBlock;
3761 save_break(BreakJumpTarget);
3767 Succ = LoopBackBlock = createBlock();
3770 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3771 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3773 CFGBlock *BodyBlock = addStmt(S->getBody());
3776 BodyBlock = ContinueJumpTarget.block;
3783 addSuccessor(ExitConditionBlock, BodyBlock);
3788 addSuccessor(ExitConditionBlock, LoopSuccessor);
3791 Block = createBlock();
3792 return addStmt(S->getCollection());
3797 return addStmt(S->getSubStmt());
3805 CFGBlock *SyncBlock = addStmt(S->getSynchBody());
3819 appendStmt(
Block, S);
3822 return addStmt(S->getSynchExpr());
3829 appendStmt(
Block, E);
3841 Semantic = OVE->getSourceExpr();
3859 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3861 addLocalScopeForVarDecl(VD);
3862 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3871 LoopSuccessor =
Block;
3874 LoopSuccessor = Succ;
3877 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3886 save_break(BreakJumpTarget);
3890 Succ = TransitionBlock = createBlock(
false);
3891 TransitionBlock->setLoopTarget(W);
3892 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3895 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3898 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3902 if (!isa<CompoundStmt>(W->
getBody()))
3903 addLocalScopeAndDtors(W->
getBody());
3906 BodyBlock = addStmt(W->
getBody());
3909 BodyBlock = ContinueJumpTarget.block;
3910 else if (
Block && badCFG)
3917 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3924 if (
BinaryOperator *Cond = dyn_cast<BinaryOperator>(
C->IgnoreParens()))
3926 std::tie(EntryConditionBlock, ExitConditionBlock) =
3927 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3932 ExitConditionBlock = createBlock(
false);
3938 Block = ExitConditionBlock;
3939 Block = EntryConditionBlock = addStmt(
C);
3948 findConstructionContexts(
3952 appendStmt(
Block, DS);
3953 EntryConditionBlock = addStmt(Init);
3954 assert(
Block == EntryConditionBlock);
3955 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3959 if (
Block && badCFG)
3963 const TryResult& KnownVal = tryEvaluateBool(
C);
3966 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3969 addSuccessor(ExitConditionBlock,
3970 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3974 addSuccessor(TransitionBlock, EntryConditionBlock);
3981 Succ = EntryConditionBlock;
3982 return EntryConditionBlock;
3986 AddStmtChoice asc) {
3987 if (asc.alwaysAdd(*
this, A)) {
3989 appendStmt(
Block, A);
3998 assert(OVE &&
"ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
3999 "OpaqueValueExpr!");
4000 if (
CFGBlock *R = Visit(OVE->getSourceExpr()))
4019 CatchBlock = createBlock();
4021 appendStmt(CatchBlock, CS);
4042 Block = createBlock(
false);
4044 if (TryTerminatedBlock)
4046 addSuccessor(
Block, TryTerminatedBlock);
4049 addSuccessor(
Block, &cfg->getExit());
4053 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4064 TrySuccessor =
Block;
4066 TrySuccessor = Succ;
4072 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4075 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4079 bool HasCatchAll =
false;
4082 Succ = TrySuccessor;
4087 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4092 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4097 if (PrevTryTerminatedBlock)
4098 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4100 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4104 Succ = TrySuccessor;
4107 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4108 cfg->addTryDispatchBlock(TryTerminatedBlock);
4110 assert(Terminator->
getTryBody() &&
"try must contain a non-NULL body");
4116 AddStmtChoice asc) {
4117 findConstructionContextsForArguments(ME);
4120 appendObjCMessage(
Block, ME);
4122 return VisitChildren(ME);
4131 Block = createBlock(
false);
4133 if (TryTerminatedBlock)
4135 addSuccessor(
Block, TryTerminatedBlock);
4138 addSuccessor(
Block, &cfg->getExit());
4142 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4146 if (asc.alwaysAdd(*
this, S)) {
4148 appendStmt(
Block, S);
4157 if (S && !S->isTypeDependent() && S->isPotentiallyEvaluated())
4158 return VisitChildren(S);
4174 LoopSuccessor =
Block;
4176 LoopSuccessor = Succ;
4181 CFGBlock *ExitConditionBlock = createBlock(
false);
4182 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4190 Block = ExitConditionBlock;
4191 EntryConditionBlock = addStmt(
C);
4199 Succ = EntryConditionBlock;
4202 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
4212 save_break(BreakJumpTarget);
4215 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4218 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4225 if (!isa<CompoundStmt>(D->
getBody()))
4226 addLocalScopeAndDtors(D->
getBody());
4229 BodyBlock = addStmt(D->
getBody());
4232 BodyBlock = EntryConditionBlock;
4245 CFGBlock *LoopBackBlock = createBlock();
4248 if (!KnownVal.isFalse())
4250 addSuccessor(ExitConditionBlock, LoopBackBlock);
4252 addSuccessor(ExitConditionBlock,
nullptr);
4257 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4275 Block = createBlock(
false);
4280 if (ContinueJumpTarget.block) {
4281 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,
C);
4282 addSuccessor(
Block, ContinueJumpTarget.block);
4290 AddStmtChoice asc) {
4291 if (asc.alwaysAdd(*
this, E)) {
4293 appendStmt(
Block, E);
4299 if (E->
getKind() != UETT_SizeOf)
4306 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4307 lastBlock = addStmt(VA->getSizeExpr());
4315 if (asc.alwaysAdd(*
this, SE)) {
4317 appendStmt(
Block, SE);
4319 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4325 CFGBlock *SwitchSuccessor =
nullptr;
4333 addLocalScopeForStmt(Init);
4338 addLocalScopeForVarDecl(VD);
4340 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4345 SwitchSuccessor =
Block;
4346 }
else SwitchSuccessor = Succ;
4350 save_default(DefaultCaseBlock);
4356 DefaultCaseBlock = SwitchSuccessor;
4359 SwitchTerminatedBlock = createBlock(
false);
4363 Succ = SwitchSuccessor;
4364 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4369 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4374 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered,
false);
4377 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4379 bool b = tryEvaluate(Terminator->
getCond(), result);
4384 if (!isa<CompoundStmt>(Terminator->
getBody()))
4385 addLocalScopeAndDtors(Terminator->
getBody());
4387 addStmt(Terminator->
getBody());
4399 bool SwitchAlwaysHasSuccessor =
false;
4400 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4403 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4404 !SwitchAlwaysHasSuccessor);
4408 Block = SwitchTerminatedBlock;
4417 LastBlock = addStmt(Init);
4418 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
4425 LastBlock = addStmt(Init);
4438 bool addCase =
false;
4440 if (!switchExclusivelyCovered) {
4444 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4446 if (condInt == lhsInt) {
4448 switchExclusivelyCovered =
true;
4450 else if (condInt > lhsInt) {
4454 if (V2 >= condInt) {
4456 switchExclusivelyCovered =
true;
4470 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4476 while (isa<CaseStmt>(Sub)) {
4477 CFGBlock *currentBlock = createBlock(
false);
4481 addSuccessor(LastBlock, currentBlock);
4483 TopBlock = currentBlock;
4485 addSuccessor(SwitchTerminatedBlock,
4488 ? currentBlock :
nullptr);
4490 LastBlock = currentBlock;
4491 CS = cast<CaseStmt>(Sub);
4500 CaseBlock = createBlock();
4511 assert(SwitchTerminatedBlock);
4512 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4520 addSuccessor(LastBlock, CaseBlock);
4534 DefaultCaseBlock =
Block;
4536 if (!DefaultCaseBlock)
4537 DefaultCaseBlock = createBlock();
4541 DefaultCaseBlock->
setLabel(Terminator);
4556 Succ = DefaultCaseBlock;
4558 return DefaultCaseBlock;
4569 TrySuccessor =
Block;
4571 TrySuccessor = Succ;
4573 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4576 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4580 bool HasCatchAll =
false;
4581 for (
unsigned I = 0, E = Terminator->
getNumHandlers(); I != E; ++I) {
4583 Succ = TrySuccessor;
4589 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4594 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4597 if (PrevTryTerminatedBlock)
4598 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4600 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4604 Succ = TrySuccessor;
4607 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4608 cfg->addTryDispatchBlock(TryTerminatedBlock);
4610 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4626 LocalScope::const_iterator BeginScopePos = ScopePos;
4627 addLocalScopeForVarDecl(VD);
4628 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4636 CatchBlock = createBlock();
4642 appendStmt(CatchBlock, CS);
4676 if (
Stmt *Range = S->getRangeStmt())
4677 addLocalScopeForStmt(Range);
4679 addLocalScopeForStmt(
Begin);
4680 if (
Stmt *End = S->getEndStmt())
4681 addLocalScopeForStmt(End);
4682 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4684 LocalScope::const_iterator ContinueScopePos = ScopePos;
4692 LoopSuccessor =
Block;
4694 LoopSuccessor = Succ;
4699 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4702 CFGBlock *ConditionBlock = createBlock(
false);
4706 if (
Expr *
C = S->getCond()) {
4707 Block = ConditionBlock;
4708 CFGBlock *BeginConditionBlock = addStmt(
C);
4711 assert(BeginConditionBlock == ConditionBlock &&
4712 "condition block in for-range was unexpectedly complex");
4713 (void)BeginConditionBlock;
4718 Succ = ConditionBlock;
4721 TryResult KnownVal(
true);
4724 KnownVal = tryEvaluateBool(S->getCond());
4728 assert(S->getBody());
4737 Succ = addStmt(S->getInc());
4740 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4744 ContinueJumpTarget.block->setLoopTarget(S);
4753 addLocalScopeAndDtors(S->getLoopVarStmt());
4757 if (!isa<CompoundStmt>(S->getBody()))
4758 addLocalScopeAndDtors(S->getBody());
4761 addStmt(S->getBody());
4765 CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
4770 addSuccessor(ConditionBlock,
4771 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
4776 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4779 Block = createBlock();
4780 addStmt(S->getBeginStmt());
4781 addStmt(S->getEndStmt());
4782 CFGBlock *Head = addStmt(S->getRangeStmt());
4784 Head = addStmt(S->getInit());
4789 AddStmtChoice asc,
bool ExternallyDestructed) {
4793 TempDtorContext Context;
4794 VisitForTemporaryDtors(E->
getSubExpr(), ExternallyDestructed, Context);
4798 asc = asc.withAlwaysAdd(
true);
4804 AddStmtChoice asc) {
4805 if (asc.alwaysAdd(*
this, E)) {
4807 appendStmt(
Block, E);
4809 findConstructionContexts(
4814 asc = asc.withAlwaysAdd(
false);
4820 AddStmtChoice asc) {
4824 findConstructionContextsForArguments(
C);
4827 appendConstructor(
Block,
C);
4829 return VisitChildren(
C);
4833 AddStmtChoice asc) {
4835 appendStmt(
Block, NE);
4837 findConstructionContexts(
4841 if (
NE->getInitializer())
4842 Block = Visit(
NE->getInitializer());
4845 appendNewAllocator(
Block, NE);
4847 if (
NE->isArray() && *
NE->getArraySize())
4848 Block = Visit(*
NE->getArraySize());
4851 E =
NE->placement_arg_end(); I != E; ++I)
4858 AddStmtChoice asc) {
4860 appendStmt(
Block, DE);
4867 appendDeleteDtor(
Block, RD, DE);
4871 return VisitChildren(DE);
4875 AddStmtChoice asc) {
4876 if (asc.alwaysAdd(*
this, E)) {
4878 appendStmt(
Block, E);
4880 asc = asc.withAlwaysAdd(
false);
4886 AddStmtChoice asc) {
4890 findConstructionContextsForArguments(
C);
4893 appendConstructor(
Block,
C);
4894 return VisitChildren(
C);
4898 AddStmtChoice asc) {
4899 if (asc.alwaysAdd(*
this, E)) {
4901 appendStmt(
Block, E);
4907 return Visit(E->
getSubExpr(), AddStmtChoice());
4911 return Visit(E->
getSubExpr(), AddStmtChoice());
4916 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4919 IBlock = createBlock(
false);
4920 cfg->setIndirectGotoBlock(IBlock);
4928 Block = createBlock(
false);
4929 Block->setTerminator(I);
4930 addSuccessor(
Block, IBlock);
4934CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
4935 TempDtorContext &Context) {
4945 return VisitChildrenForTemporaryDtors(E,
false, Context);
4947 case Stmt::InitListExprClass:
4948 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
4950 case Stmt::BinaryOperatorClass:
4951 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4952 ExternallyDestructed,
4955 case Stmt::CXXBindTemporaryExprClass:
4956 return VisitCXXBindTemporaryExprForTemporaryDtors(
4957 cast<CXXBindTemporaryExpr>(E), ExternallyDestructed, Context);
4959 case Stmt::BinaryConditionalOperatorClass:
4960 case Stmt::ConditionalOperatorClass:
4961 return VisitConditionalOperatorForTemporaryDtors(
4962 cast<AbstractConditionalOperator>(E), ExternallyDestructed, Context);
4964 case Stmt::ImplicitCastExprClass:
4966 E = cast<CastExpr>(E)->getSubExpr();
4969 case Stmt::CXXFunctionalCastExprClass:
4971 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4974 case Stmt::ConstantExprClass:
4975 E = cast<ConstantExpr>(E)->getSubExpr();
4978 case Stmt::ParenExprClass:
4979 E = cast<ParenExpr>(E)->getSubExpr();
4982 case Stmt::MaterializeTemporaryExprClass: {
4988 E =
const_cast<Expr *
>(
4989 cast<MaterializeTemporaryExpr>(E)
4991 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4993 for (
const Expr *CommaLHS : CommaLHSs) {
4994 VisitForTemporaryDtors(
const_cast<Expr *
>(CommaLHS),
5000 case Stmt::BlockExprClass:
5005 case Stmt::LambdaExprClass: {
5008 auto *
LE = cast<LambdaExpr>(E);
5010 for (
Expr *Init :
LE->capture_inits()) {
5012 if (
CFGBlock *R = VisitForTemporaryDtors(
5013 Init,
true, Context))
5020 case Stmt::StmtExprClass:
5025 case Stmt::CXXDefaultArgExprClass:
5026 E = cast<CXXDefaultArgExpr>(E)->getExpr();
5029 case Stmt::CXXDefaultInitExprClass:
5030 E = cast<CXXDefaultInitExpr>(E)->getExpr();
5035CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
5036 bool ExternallyDestructed,
5037 TempDtorContext &Context) {
5038 if (isa<LambdaExpr>(E)) {
5050 if (
CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
5056CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
5057 BinaryOperator *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5061 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
5062 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(), ExternallyDestructed, Context);
5063 return RHSBlock ? RHSBlock : LHSBlock;
5067 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
5068 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
5069 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
5070 RHSExecuted.negate();
5075 TempDtorContext RHSContext(
5077 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
5078 InsertTempDtorDecisionBlock(RHSContext);
5086 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
5087 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
5088 return LHSBlock ? LHSBlock : RHSBlock;
5092 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
5095CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5100 if (!ExternallyDestructed) {
5112 Block = createNoReturnBlock();
5113 }
else if (Context.needsTempDtorBranch()) {
5117 Block = createBlock();
5121 if (Context.needsTempDtorBranch()) {
5122 Context.setDecisionPoint(Succ, E);
5124 appendTemporaryDtor(
Block, E);
5131void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
5133 if (!Context.TerminatorExpr) {
5137 assert(Context.TerminatorExpr);
5138 CFGBlock *Decision = createBlock(
false);
5141 addSuccessor(Decision,
Block, !Context.KnownExecuted.isFalse());
5142 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5143 !Context.KnownExecuted.isTrue());
5147CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
5149 TempDtorContext &Context) {
5150 VisitForTemporaryDtors(E->
getCond(),
false, Context);
5153 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
5154 TryResult NegatedVal = ConditionVal;
5155 if (NegatedVal.isKnown()) NegatedVal.negate();
5157 TempDtorContext TrueContext(
5159 VisitForTemporaryDtors(E->
getTrueExpr(), ExternallyDestructed, TrueContext);
5162 Block = ConditionBlock;
5163 Succ = ConditionSucc;
5164 TempDtorContext FalseContext(
5166 VisitForTemporaryDtors(E->
getFalseExpr(), ExternallyDestructed, FalseContext);
5168 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5169 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
5170 }
else if (TrueContext.TerminatorExpr) {
5172 InsertTempDtorDecisionBlock(TrueContext);
5174 InsertTempDtorDecisionBlock(FalseContext);
5180 AddStmtChoice asc) {
5181 if (asc.alwaysAdd(*
this, D)) {
5183 appendStmt(
Block, D);
5193 for (
Stmt *S : llvm::reverse(
Used)) {
5194 assert(S &&
"Expected non-null used-in-clause child.");
5201 if (!isa<CompoundStmt>(S))
5202 addLocalScopeAndDtors(S);
5214 bool first_block =
begin() ==
end();
5218 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
5223 Entry = Exit = &
back();
5232 CFGBuilder Builder(
C, BO);
5233 return Builder.buildCFG(D, Statement);
5248 auto IteratorAndFlag = Visited.insert(B);
5249 if (!IteratorAndFlag.second) {
5255 const CFGBlock *FirstReachableB =
nullptr;
5257 if (!AB.isReachable())
5260 if (FirstReachableB ==
nullptr) {
5261 FirstReachableB = &*AB;
5268 if (!FirstReachableB) {
5274 B = FirstReachableB;
5293 llvm_unreachable(
"getDestructorDecl should only be used with "
5296 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
5322 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
5331 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
5336 const FieldDecl *field = castAs<CFGMemberDtor>().getFieldDecl();
5351 llvm_unreachable(
"getKind() returned bogus value");
5359 : ReachableBlock(IsReachable ? B : nullptr),
5360 UnreachableBlock(!IsReachable ? B : nullptr,
5361 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5364 : ReachableBlock(B),
5365 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
5366 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5389 if (S->isAllEnumCasesCovered()) {
5391 if (!L || !isa<CaseStmt>(L))
5407 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5408 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5412 signed currentBlock = 0;
5413 unsigned currStmt = 0;
5424 BI != BEnd; ++BI, ++j ) {
5425 if (std::optional<CFGStmt> SE = BI->getAs<
CFGStmt>()) {
5427 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
5430 switch (
stmt->getStmtClass()) {
5431 case Stmt::DeclStmtClass:
5432 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
5434 case Stmt::IfStmtClass: {
5435 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
5440 case Stmt::ForStmtClass: {
5441 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
5446 case Stmt::WhileStmtClass: {
5448 cast<WhileStmt>(
stmt)->getConditionVariable();
5453 case Stmt::SwitchStmtClass: {
5455 cast<SwitchStmt>(
stmt)->getConditionVariable();
5460 case Stmt::CXXCatchStmtClass: {
5462 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
5475 ~StmtPrinterHelper()
override =
default;
5477 const LangOptions &getLangOpts()
const {
return LangOpts; }
5478 void setBlockID(
signed i) { currentBlock = i; }
5479 void setStmtID(
unsigned i) { currStmt = i; }
5481 bool handledStmt(
Stmt *S, raw_ostream &
OS)
override {
5482 StmtMapTy::iterator I = StmtMap.find(S);
5484 if (I == StmtMap.end())
5487 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5488 && I->second.second == currStmt) {
5492 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5496 bool handleDecl(
const Decl *D, raw_ostream &
OS) {
5497 DeclMapTy::iterator I = DeclMap.find(D);
5499 if (I == DeclMap.end())
5502 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5503 && I->second.second == currStmt) {
5507 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5512class CFGBlockTerminatorPrint
5513 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5515 StmtPrinterHelper* Helper;
5519 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5521 :
OS(os), Helper(helper), Policy(Policy) {
5525 void VisitIfStmt(
IfStmt *I) {
5528 C->printPretty(
OS, Helper, Policy);
5532 void VisitStmt(
Stmt *Terminator) {
5541 void VisitForStmt(
ForStmt *F) {
5547 C->printPretty(
OS, Helper, Policy);
5557 C->printPretty(
OS, Helper, Policy);
5560 void VisitDoStmt(
DoStmt *D) {
5561 OS <<
"do ... while ";
5563 C->printPretty(
OS, Helper, Policy);
5566 void VisitSwitchStmt(
SwitchStmt *Terminator) {
5571 void VisitCXXTryStmt(
CXXTryStmt *) {
OS <<
"try ..."; }
5575 void VisitSEHTryStmt(
SEHTryStmt *CS) {
OS <<
"__try ..."; }
5578 if (
Stmt *Cond =
C->getCond())
5580 OS <<
" ? ... : ...";
5584 OS <<
"__builtin_choose_expr( ";
5585 if (
Stmt *Cond =
C->getCond())
5613 llvm_unreachable(
"Invalid logical operator.");
5617 void VisitExpr(
Expr *E) {
5628 OS <<
"(Temp Dtor) ";
5632 OS <<
"(See if most derived ctor has already initialized vbases)";
5654 OS <<
" (Base initializer)";
5656 OS <<
" (Delegating initializer)";
5658 OS <<
" (Member initializer)";
5662 StmtPrinterHelper &Helper,
5668 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5675 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5677 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5681 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5682 Stmts.push_back(SDSCC->getDeclStmt());
5686 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5687 Stmts.push_back(CDSCC->getDeclStmt());
5688 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5692 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5693 Stmts.push_back(NECC->getCXXNewExpr());
5697 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5698 Stmts.push_back(RSCC->getReturnStmt());
5703 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5704 Stmts.push_back(RSCC->getReturnStmt());
5705 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5709 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5710 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5711 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5715 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5716 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5717 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5718 Stmts.push_back(TOCC->getConstructorAfterElision());
5722 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
5723 Helper.handledStmt(
const_cast<LambdaExpr *
>(LCC->getLambdaExpr()),
OS);
5724 OS <<
"+" << LCC->getIndex();
5728 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5729 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5731 Helper.handledStmt(
const_cast<Stmt *
>(BTE),
OS);
5734 Helper.handledStmt(
const_cast<Expr *
>(ACC->getCallLikeExpr()),
OS);
5735 OS <<
"+" << ACC->getIndex();
5742 Helper.handledStmt(
const_cast<Stmt *
>(I),
OS);
5746static void print_elem(raw_ostream &
OS, StmtPrinterHelper &Helper,
5751 StmtPrinterHelper Helper(
nullptr, LangOpts);
5763 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5766 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5769 auto Children = Sub->children();
5770 if (Children.begin() != Children.end()) {
5781 Helper.handledStmt(B->
getRHS(),
OS);
5789 if (isa<CXXOperatorCallExpr>(S))
5790 OS <<
" (OperatorCall)";
5791 OS <<
" (CXXRecordTypedCall";
5794 }
else if (isa<CXXOperatorCallExpr>(S)) {
5795 OS <<
" (OperatorCall)";
5796 }
else if (isa<CXXBindTemporaryExpr>(S)) {
5797 OS <<
" (BindTemporary)";
5799 OS <<
" (CXXConstructExpr";
5803 OS <<
", " << CCE->getType() <<
")";
5804 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5806 <<
", " << CE->
getType() <<
")";
5824 Helper.handleDecl(VD,
OS);
5832 OS <<
"() (Implicit destructor)\n";
5838 OS <<
" (Lifetime ends)\n";
5846 OS <<
"CFGScopeBegin(";