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; }
303 bool inSameLocalScope(const_iterator rhs) {
return Scope == rhs.
Scope; }
310 AutomaticVarsTy Vars;
319 : ctx(
std::move(ctx)), Vars(this->ctx, 4), Prev(
P) {}
322 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
325 Vars.push_back(VD, ctx);
334int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
336 const_iterator F = *
this;
337 while (F.Scope != L.Scope) {
338 assert(F != const_iterator() &&
339 "L iterator is not reachable from F iterator.");
343 D += F.VarIter - L.VarIter;
351LocalScope::const_iterator
352LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
355 if ((*
this == const_iterator()) || (L == const_iterator())) {
356 return const_iterator();
359 const_iterator F = *
this;
360 if (F.inSameLocalScope(L)) {
362 F.VarIter = std::min(F.VarIter, L.VarIter);
366 llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;
368 ScopesOfL.try_emplace(L.Scope, L.VarIter);
369 if (L == const_iterator())
375 if (
auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {
377 F.VarIter = std::min(F.VarIter, LIt->getSecond());
380 assert(F != const_iterator() &&
381 "L iterator is not reachable from F iterator.");
391struct BlockScopePosPair {
393 LocalScope::const_iterator scopePosition;
395 BlockScopePosPair() =
default;
396 BlockScopePosPair(
CFGBlock *
b, LocalScope::const_iterator scopePos)
397 : block(
b), scopePosition(scopePos) {}
408 TryResult() =
default;
409 TryResult(
bool b) :
X(
b ? 1 : 0) {}
411 bool isTrue()
const {
return X == 1; }
412 bool isFalse()
const {
return X == 0; }
413 bool isKnown()
const {
return X >= 0; }
424 if (!R1.isKnown() || !R2.isKnown())
426 return TryResult(R1.isTrue() && R2.isTrue());
431class reverse_children {
436 reverse_children(
Stmt *S);
440 iterator begin()
const {
return children.rbegin(); }
441 iterator end()
const {
return children.rend(); }
446reverse_children::reverse_children(
Stmt *S) {
447 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
448 children = CE->getRawSubExprs();
451 switch (S->getStmtClass()) {
453 case Stmt::InitListExprClass: {
464 llvm::append_range(childrenBuf, S->children());
467 children = childrenBuf;
486 using JumpTarget = BlockScopePosPair;
487 using JumpSource = BlockScopePosPair;
490 std::unique_ptr<CFG> cfg;
498 JumpTarget ContinueJumpTarget;
499 JumpTarget BreakJumpTarget;
500 JumpTarget SEHLeaveJumpTarget;
501 CFGBlock *SwitchTerminatedBlock =
nullptr;
502 CFGBlock *DefaultCaseBlock =
nullptr;
508 CFGBlock *TryTerminatedBlock =
nullptr;
511 LocalScope::const_iterator ScopePos;
514 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
519 using BackpatchBlocksTy = std::vector<JumpSource>;
520 BackpatchBlocksTy BackpatchBlocks;
524 LabelSetTy AddressTakenLabels;
529 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
530 ConstructionContextMap;
536 bool switchExclusivelyCovered =
false;
539 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
540 const Stmt *lastLookup =
nullptr;
544 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
545 CachedBoolEvalsTy CachedBoolEvals;
550 : Context(astContext), cfg(new
CFG()), BuildOpts(buildOpts) {}
553 std::unique_ptr<CFG> buildCFG(
const Decl *
D,
Stmt *Statement);
590 AddStmtChoice asc,
bool ExternallyDestructed);
602 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
632 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
633 bool ExternallyDestructed =
false);
642 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
643 appendScopeBegin(B, VD, S);
674 struct TempDtorContext {
675 TempDtorContext() =
default;
676 TempDtorContext(TryResult KnownExecuted)
677 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
685 bool needsTempDtorBranch()
const {
686 return IsConditional && !TerminatorExpr;
696 const bool IsConditional =
false;
697 const TryResult KnownExecuted =
true;
704 CFGBlock *VisitForTemporaryDtors(
Stmt *
E,
bool ExternallyDestructed,
705 TempDtorContext &Context);
706 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *
E,
bool ExternallyDestructed,
707 TempDtorContext &Context);
709 bool ExternallyDestructed,
710 TempDtorContext &Context);
711 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
713 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
715 TempDtorContext &Context);
716 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
741 template <
typename CallLikeExpr,
742 typename = std::enable_if_t<
743 std::is_base_of_v<CallExpr, CallLikeExpr> ||
744 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
745 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
746 void findConstructionContextsForArguments(CallLikeExpr *
E) {
747 for (
unsigned i = 0, e =
E->getNumArgs(); i != e; ++i) {
748 Expr *Arg =
E->getArg(i);
750 findConstructionContexts(
760 void cleanupConstructionContext(
Expr *
E);
762 void autoCreateBlock() {
if (!Block)
Block = createBlock(); }
764 CFGBlock *createBlock(
bool add_successor =
true);
768 return Visit(S, AddStmtChoice::AlwaysAdd);
772 void addLoopExit(
const Stmt *LoopStmt);
773 void addAutomaticObjHandling(LocalScope::const_iterator B,
774 LocalScope::const_iterator
E,
Stmt *S);
775 void addAutomaticObjDestruction(LocalScope::const_iterator B,
776 LocalScope::const_iterator
E,
Stmt *S);
777 void addScopeExitHandling(LocalScope::const_iterator B,
778 LocalScope::const_iterator
E,
Stmt *S);
780 void addScopeChangesHandling(LocalScope::const_iterator SrcPos,
781 LocalScope::const_iterator DstPos,
783 CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,
785 LocalScope::const_iterator DstPost,
789 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
791 void addLocalScopeForStmt(
Stmt *S);
792 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
793 LocalScope*
Scope =
nullptr);
794 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
796 void addLocalScopeAndDtors(
Stmt *S);
806 cleanupConstructionContext(
E);
814 if (alwaysAdd(S) && cachedEntry)
815 cachedEntry->second = B;
818 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
824 if (
C &&
C->isNoReturn())
825 Block = createNoReturnBlock();
830 retrieveAndCleanupConstructionContext(CE)) {
840 if (alwaysAdd(CE) && cachedEntry)
841 cachedEntry->second = B;
844 retrieveAndCleanupConstructionContext(CE)) {
850 B->
appendStmt(CE, cfg->getBumpVectorContext());
870 if (alwaysAdd(ME) && cachedEntry)
871 cachedEntry->second = B;
874 retrieveAndCleanupConstructionContext(ME)) {
880 cfg->getBumpVectorContext());
899 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
909 cfg->getBumpVectorContext());
916 cfg->getBumpVectorContext());
932 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
936 const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
937 const Expr *BoolExpr = RHSExpr;
938 bool IntFirst =
true;
940 IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
948 llvm::APInt IntValue = IntLiteral->
getValue();
949 if ((IntValue == 1) || (IntValue == 0))
953 !IntValue.isNegative();
956 if (Bok == BO_GT || Bok == BO_GE) {
959 return TryResult(IntFirst == IntLarger);
963 return TryResult(IntFirst != IntLarger);
971 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
975 std::optional<llvm::APInt> IntLiteral1 =
976 getIntegerLiteralSubexpressionValue(LHSExpr);
977 const Expr *BoolExpr = RHSExpr;
980 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
988 if (BitOp && (BitOp->
getOpcode() == BO_And ||
993 std::optional<llvm::APInt> IntLiteral2 =
994 getIntegerLiteralSubexpressionValue(LHSExpr2);
997 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
1003 (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
1005 (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1009 return TryResult(B->
getOpcode() != BO_EQ);
1012 if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1015 return TryResult(B->
getOpcode() != BO_EQ);
1027 std::optional<llvm::APInt>
1028 getIntegerLiteralSubexpressionValue(
const Expr *
E) {
1031 if (
const auto *UnOp = dyn_cast<UnaryOperator>(
E->
IgnoreParens())) {
1036 if (
const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1041 switch (UnOp->getOpcode()) {
1051 assert(
false &&
"Unexpected unary operator!");
1052 return std::nullopt;
1055 }
else if (
const auto *IntLiteral =
1059 return std::nullopt;
1063 const llvm::APSInt &Value1,
1064 const llvm::APSInt &Value2) {
1065 assert(Value1.isSigned() == Value2.isSigned());
1070 return TryResult(Value1 == Value2);
1072 return TryResult(Value1 != Value2);
1074 return TryResult(Value1 < Value2);
1076 return TryResult(Value1 <= Value2);
1078 return TryResult(Value1 > Value2);
1080 return TryResult(Value1 >= Value2);
1096 auto CheckLogicalOpWithNegatedVariable = [
this, B](
const Expr *E1,
1098 if (
const auto *Negate = dyn_cast<UnaryOperator>(E1)) {
1099 if (Negate->getOpcode() == UO_LNot &&
1101 bool AlwaysTrue = B->
getOpcode() == BO_LOr;
1104 return TryResult(AlwaysTrue);
1110 TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);
1111 if (Result.isKnown())
1113 Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);
1114 if (Result.isKnown())
1117 const auto *LHS = dyn_cast<BinaryOperator>(LHSExpr);
1118 const auto *RHS = dyn_cast<BinaryOperator>(RHSExpr);
1122 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1125 const Expr *DeclExpr1;
1126 const Expr *NumExpr1;
1130 if (!DeclExpr1 || !NumExpr1)
1133 const Expr *DeclExpr2;
1134 const Expr *NumExpr2;
1138 if (!DeclExpr2 || !NumExpr2)
1155 llvm::APSInt L1 = L1Result.
Val.
getInt();
1156 llvm::APSInt L2 = L2Result.
Val.
getInt();
1159 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1164 const llvm::APSInt Values[] = {
1166 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1170 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1175 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1184 bool AlwaysTrue =
true, AlwaysFalse =
true;
1187 bool LHSAlwaysTrue =
true, LHSAlwaysFalse =
true;
1188 bool RHSAlwaysTrue =
true, RHSAlwaysFalse =
true;
1189 for (
const llvm::APSInt &
Value : Values) {
1190 TryResult Res1, Res2;
1191 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1192 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1194 if (!Res1.isKnown() || !Res2.isKnown())
1198 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1199 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1201 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1202 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1205 LHSAlwaysTrue &= Res1.isTrue();
1206 LHSAlwaysFalse &= Res1.isFalse();
1207 RHSAlwaysTrue &= Res2.isTrue();
1208 RHSAlwaysFalse &= Res2.isFalse();
1211 if (AlwaysTrue || AlwaysFalse) {
1212 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1213 !RHSAlwaysFalse && BuildOpts.
Observer)
1215 return TryResult(AlwaysTrue);
1221 TryResult checkIncorrectBitwiseOrOperator(
const BinaryOperator *B) {
1222 const Expr *LHSConstant =
1224 const Expr *RHSConstant =
1227 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1230 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1236 if (Result.Val.getInt() == 0)
1242 return TryResult(
true);
1249 return !S->isTypeDependent() &&
1250 !S->isValueDependent() &&
1251 S->EvaluateAsRValue(outResult, *Context);
1256 TryResult tryEvaluateBool(
Expr *S) {
1258 S->isTypeDependent() || S->isValueDependent())
1262 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1264 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1265 if (I != CachedBoolEvals.end())
1269 TryResult Result = evaluateAsBooleanConditionNoCache(S);
1270 CachedBoolEvals[S] = Result;
1274 switch (Bop->getOpcode()) {
1283 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1284 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1285 if (!IntVal.getBoolValue()) {
1286 return TryResult(
false);
1290 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1291 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1292 if (!IntVal.getBoolValue()) {
1293 return TryResult(
false);
1302 return evaluateAsBooleanConditionNoCache(S);
1306 TryResult evaluateAsBooleanConditionNoCache(
Expr *
E) {
1308 if (Bop->isLogicalOp()) {
1309 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1310 if (LHS.isKnown()) {
1313 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1314 return LHS.isTrue();
1316 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1317 if (RHS.isKnown()) {
1318 if (Bop->getOpcode() == BO_LOr)
1319 return LHS.isTrue() || RHS.isTrue();
1321 return LHS.isTrue() && RHS.isTrue();
1324 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1325 if (RHS.isKnown()) {
1328 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1329 return RHS.isTrue();
1331 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1332 if (BopRes.isKnown())
1333 return BopRes.isTrue();
1338 }
else if (Bop->isEqualityOp()) {
1339 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1340 if (BopRes.isKnown())
1341 return BopRes.isTrue();
1342 }
else if (Bop->isRelationalOp()) {
1343 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1344 if (BopRes.isKnown())
1345 return BopRes.isTrue();
1346 }
else if (Bop->getOpcode() == BO_Or) {
1347 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1348 if (BopRes.isKnown())
1349 return BopRes.isTrue();
1360 bool hasTrivialDestructor(
const VarDecl *VD)
const;
1361 bool needsAutomaticDestruction(
const VarDecl *VD)
const;
1372 while (
const auto *
E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1373 AILEInit =
E->getSubExpr();
1378inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1380 return builder.alwaysAdd(
stmt) || kind == AlwaysAdd;
1383bool CFGBuilder::alwaysAdd(
const Stmt *
stmt) {
1389 if (lastLookup ==
stmt) {
1391 assert(cachedEntry->first ==
stmt);
1404 assert(!cachedEntry);
1408 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(
stmt);
1409 if (itr == fb->end()) {
1410 cachedEntry =
nullptr;
1414 cachedEntry = &*itr;
1421 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1423 if (vat->getSizeExpr())
1426 t = vt->getElementType().getTypePtr();
1432void CFGBuilder::consumeConstructionContext(
1434 assert((isa<CXXConstructExpr>(
E) || isa<CallExpr>(
E) ||
1435 isa<ObjCMessageExpr>(
E)) &&
"Expression cannot construct an object!");
1437 ConstructionContextMap.lookup(
E)) {
1438 (void)PreviouslyStoredLayer;
1441 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1442 "Already within a different construction context!");
1444 ConstructionContextMap[
E] = Layer;
1448void CFGBuilder::findConstructionContexts(
1461 switch(Child->getStmtClass()) {
1462 case Stmt::CXXConstructExprClass:
1463 case Stmt::CXXTemporaryObjectExprClass: {
1465 auto *CE = cast<CXXConstructExpr>(Child);
1467 findConstructionContexts(withExtraLayer(CE), CE->
getArg(0));
1470 consumeConstructionContext(Layer, CE);
1476 case Stmt::CallExprClass:
1477 case Stmt::CXXMemberCallExprClass:
1478 case Stmt::CXXOperatorCallExprClass:
1479 case Stmt::UserDefinedLiteralClass:
1480 case Stmt::ObjCMessageExprClass: {
1481 auto *
E = cast<Expr>(Child);
1483 consumeConstructionContext(Layer,
E);
1486 case Stmt::ExprWithCleanupsClass: {
1487 auto *Cleanups = cast<ExprWithCleanups>(Child);
1488 findConstructionContexts(Layer, Cleanups->getSubExpr());
1491 case Stmt::CXXFunctionalCastExprClass: {
1492 auto *
Cast = cast<CXXFunctionalCastExpr>(Child);
1493 findConstructionContexts(Layer,
Cast->getSubExpr());
1496 case Stmt::ImplicitCastExprClass: {
1497 auto *
Cast = cast<ImplicitCastExpr>(Child);
1499 switch (
Cast->getCastKind()) {
1501 case CK_ConstructorConversion:
1502 findConstructionContexts(Layer,
Cast->getSubExpr());
1509 case Stmt::CXXBindTemporaryExprClass: {
1510 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1511 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1514 case Stmt::MaterializeTemporaryExprClass: {
1521 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1522 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1526 case Stmt::ConditionalOperatorClass: {
1527 auto *CO = cast<ConditionalOperator>(Child);
1534 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1538 findConstructionContexts(Layer, CO->getLHS());
1539 findConstructionContexts(Layer, CO->getRHS());
1542 case Stmt::InitListExprClass: {
1543 auto *ILE = cast<InitListExpr>(Child);
1544 if (ILE->isTransparent()) {
1545 findConstructionContexts(Layer, ILE->getInit(0));
1551 case Stmt::ParenExprClass: {
1554 auto *PE = cast<ParenExpr>(Child);
1555 findConstructionContexts(Layer, PE->getSubExpr());
1563void CFGBuilder::cleanupConstructionContext(
Expr *
E) {
1565 "We should not be managing construction contexts!");
1566 assert(ConstructionContextMap.count(
E) &&
1567 "Cannot exit construction context without the context!");
1568 ConstructionContextMap.erase(
E);
1576std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *
D,
Stmt *Statement) {
1584 Succ = createBlock();
1585 assert(Succ == &cfg->getExit());
1590 addImplicitDtorsForDestructor(DD);
1610 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(
D)) {
1612 for (
auto *I : llvm::reverse(CD->inits())) {
1614 I->isBaseInitializer() && I->isBaseVirtual()) {
1618 VBaseSucc = Succ = B ? B : &cfg->getExit();
1619 Block = createBlock();
1621 B = addInitializer(I);
1631 addSuccessor(B,
Block,
true);
1640 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1641 E = BackpatchBlocks.end(); I !=
E; ++I ) {
1645 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1648 if (LI == LabelMap.end())
1650 JumpTarget JT = LI->second;
1652 CFGBlock *SuccBlk = createScopeChangesHandlingBlock(
1653 I->scopePosition, B, JT.scopePosition, JT.block);
1654 addSuccessor(B, SuccBlk);
1655 }
else if (
auto *G = dyn_cast<GCCAsmStmt>(B->
getTerminator())) {
1656 CFGBlock *Successor = (I+1)->block;
1657 for (
auto *L : G->labels()) {
1658 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1661 if (LI == LabelMap.end())
1663 JumpTarget JT = LI->second;
1665 if (JT.block == Successor)
1667 addSuccessor(B, JT.block);
1674 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1675 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1676 E = AddressTakenLabels.end(); I !=
E; ++I ) {
1678 LabelMapTy::iterator LI = LabelMap.find(*I);
1682 if (LI == LabelMap.end())
continue;
1684 addSuccessor(B, LI->second.block);
1688 cfg->setEntry(createBlock());
1691 assert(ConstructionContextMap.empty() &&
1692 "Not all construction contexts were cleaned up!");
1694 return std::move(cfg);
1699CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1701 if (add_successor && Succ)
1702 addSuccessor(B, Succ);
1709CFGBlock *CFGBuilder::createNoReturnBlock() {
1712 addSuccessor(B, &cfg->getExit(), Succ);
1721 bool HasTemporaries =
false;
1727 HasTemporaries = isa<ExprWithCleanups>(
Init);
1731 TempDtorContext Context;
1732 VisitForTemporaryDtors(cast<ExprWithCleanups>(
Init)->getSubExpr(),
1738 appendInitializer(
Block, I);
1744 dyn_cast<ArrayInitLoopExpr>(
Init));
1746 findConstructionContexts(
1748 AILEInit ? AILEInit :
Init);
1750 if (HasTemporaries) {
1753 return Visit(cast<ExprWithCleanups>(
Init)->getSubExpr());
1777 bool *FoundMTE =
nullptr) {
1784 Init = EWC->getSubExpr();
1790 = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
1791 Init = MTE->getSubExpr();
1798 const Expr *SkippedInit =
Init->skipRValueSubobjectAdjustments();
1799 if (SkippedInit !=
Init) {
1807 return Init->getType();
1812void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1816 appendLoopExit(
Block, LoopStmt);
1824void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1825 LocalScope::const_iterator
E,
1835 if (B.inSameLocalScope(
E)) {
1836 addAutomaticObjDestruction(B,
E, S);
1842 LocalScopeEndMarkers.push_back(B);
1843 for (LocalScope::const_iterator I = B; I !=
E; ++I) {
1844 if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
1845 LocalScopeEndMarkers.push_back(I);
1847 LocalScopeEndMarkers.push_back(
E);
1851 std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
1853 llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
1854 for (
auto [
E, B] : Pairwise) {
1855 if (!B.inSameLocalScope(
E))
1856 addScopeExitHandling(B,
E, S);
1857 addAutomaticObjDestruction(B,
E, S);
1864void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
1865 LocalScope::const_iterator
E,
1874 DeclsNeedDestruction.reserve(B.distance(
E));
1876 for (
VarDecl*
D : llvm::make_range(B,
E))
1877 if (needsAutomaticDestruction(
D))
1878 DeclsNeedDestruction.push_back(
D);
1880 for (
VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
1893 Block = createNoReturnBlock();
1902 appendLifetimeEnds(
Block, VD, S);
1904 appendAutomaticObjDtor(
Block, VD, S);
1905 if (VD->
hasAttr<CleanupAttr>())
1906 appendCleanupFunction(
Block, VD);
1915void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
1916 LocalScope::const_iterator
E,
Stmt *S) {
1917 assert(!B.inSameLocalScope(
E));
1923 appendScopeEnd(
Block, B.getFirstVarInScope(), S);
1931 DeclsTrivial.reserve(B.distance(
E));
1936 for (
VarDecl*
D : llvm::make_range(B,
E))
1937 if (!needsAutomaticDestruction(
D))
1938 DeclsTrivial.push_back(
D);
1940 if (DeclsTrivial.empty())
1944 for (
VarDecl *VD : llvm::reverse(DeclsTrivial))
1945 appendLifetimeEnds(
Block, VD, S);
1953void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
1954 LocalScope::const_iterator DstPos,
1956 assert(
Block &&
"Source block should be always crated");
1962 if (SrcPos == DstPos)
1967 LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
1970 if (BuildOpts.
AddScopes && !DstPos.inSameLocalScope(BasePos)) {
1971 for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
1972 if (I.pointsToFirstDeclaredVar())
1973 appendScopeBegin(
Block, *I, S);
1978 addAutomaticObjHandling(SrcPos, BasePos, S);
1986CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
1987 LocalScope::const_iterator SrcPos,
CFGBlock *SrcBlk,
1988 LocalScope::const_iterator DstPos,
CFGBlock *DstBlk) {
1989 if (SrcPos == DstPos)
1993 (!BuildOpts.
AddScopes || SrcPos.inSameLocalScope(DstPos)))
2001 Block = createBlock(
false);
2004 addSuccessor(
Block, DstBlk);
2009 assert(
Block &&
"There should be at least one scope changing Block");
2017 "Can be called only when dtors should be added");
2021 for (
const auto &VI : RD->
vbases()) {
2025 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2028 appendBaseDtor(
Block, &VI);
2033 for (
const auto &BI : RD->
bases()) {
2034 if (!BI.isVirtual()) {
2035 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2038 appendBaseDtor(
Block, &BI);
2044 for (
auto *FI : RD->
fields()) {
2049 if (AT->isZeroSize())
2051 QT = AT->getElementType();
2057 appendMemberDtor(
Block, FI);
2064LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
2067 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
2073void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
2078 LocalScope *
Scope =
nullptr;
2082 for (
auto *BI : CS->body()) {
2084 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2092 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
2093 addLocalScopeForDeclStmt(DS);
2098LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
2099 LocalScope*
Scope) {
2104 for (
auto *DI : DS->
decls())
2105 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
2110bool CFGBuilder::needsAutomaticDestruction(
const VarDecl *VD)
const {
2111 return !hasTrivialDestructor(VD) || VD->
hasAttr<CleanupAttr>();
2114bool CFGBuilder::hasTrivialDestructor(
const VarDecl *VD)
const {
2135 bool FoundMTE =
false;
2143 if (AT->isZeroSize())
2145 QT = AT->getElementType();
2157LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
2158 LocalScope*
Scope) {
2168 !needsAutomaticDestruction(VD)) {
2176 ScopePos =
Scope->begin();
2182void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
2183 LocalScope::const_iterator scopeBeginPos = ScopePos;
2184 addLocalScopeForStmt(S);
2185 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2191CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc,
2192 bool ExternallyDestructed) {
2198 if (
Expr *
E = dyn_cast<Expr>(S))
2202 if (
auto *
D = dyn_cast<OMPExecutableDirective>(S))
2203 return VisitOMPExecutableDirective(
D, asc);
2205 switch (S->getStmtClass()) {
2207 return VisitStmt(S, asc);
2209 case Stmt::ImplicitValueInitExprClass:
2212 return VisitStmt(S, asc);
2214 case Stmt::InitListExprClass:
2215 return VisitInitListExpr(cast<InitListExpr>(S), asc);
2217 case Stmt::AttributedStmtClass:
2218 return VisitAttributedStmt(cast<AttributedStmt>(S), asc);
2220 case Stmt::AddrLabelExprClass:
2221 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2223 case Stmt::BinaryConditionalOperatorClass:
2224 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2226 case Stmt::BinaryOperatorClass:
2227 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2229 case Stmt::BlockExprClass:
2230 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2232 case Stmt::BreakStmtClass:
2233 return VisitBreakStmt(cast<BreakStmt>(S));
2235 case Stmt::CallExprClass:
2236 case Stmt::CXXOperatorCallExprClass:
2237 case Stmt::CXXMemberCallExprClass:
2238 case Stmt::UserDefinedLiteralClass:
2239 return VisitCallExpr(cast<CallExpr>(S), asc);
2241 case Stmt::CaseStmtClass:
2242 return VisitCaseStmt(cast<CaseStmt>(S));
2244 case Stmt::ChooseExprClass:
2245 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2247 case Stmt::CompoundStmtClass:
2248 return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);
2250 case Stmt::ConditionalOperatorClass:
2251 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2253 case Stmt::ContinueStmtClass:
2254 return VisitContinueStmt(cast<ContinueStmt>(S));
2256 case Stmt::CXXCatchStmtClass:
2257 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2259 case Stmt::ExprWithCleanupsClass:
2260 return VisitExprWithCleanups(cast<ExprWithCleanups>(S),
2261 asc, ExternallyDestructed);
2263 case Stmt::CXXDefaultArgExprClass:
2264 case Stmt::CXXDefaultInitExprClass:
2273 return VisitStmt(S, asc);
2275 case Stmt::CXXBindTemporaryExprClass:
2276 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2278 case Stmt::CXXConstructExprClass:
2279 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2281 case Stmt::CXXNewExprClass:
2282 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2284 case Stmt::CXXDeleteExprClass:
2285 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2287 case Stmt::CXXFunctionalCastExprClass:
2288 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2290 case Stmt::CXXTemporaryObjectExprClass:
2291 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2293 case Stmt::CXXThrowExprClass:
2294 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2296 case Stmt::CXXTryStmtClass:
2297 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2299 case Stmt::CXXTypeidExprClass:
2300 return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);
2302 case Stmt::CXXForRangeStmtClass:
2303 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2305 case Stmt::DeclStmtClass:
2306 return VisitDeclStmt(cast<DeclStmt>(S));
2308 case Stmt::DefaultStmtClass:
2309 return VisitDefaultStmt(cast<DefaultStmt>(S));
2311 case Stmt::DoStmtClass:
2312 return VisitDoStmt(cast<DoStmt>(S));
2314 case Stmt::ForStmtClass:
2315 return VisitForStmt(cast<ForStmt>(S));
2317 case Stmt::GotoStmtClass:
2318 return VisitGotoStmt(cast<GotoStmt>(S));
2320 case Stmt::GCCAsmStmtClass:
2321 return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
2323 case Stmt::IfStmtClass:
2324 return VisitIfStmt(cast<IfStmt>(S));
2326 case Stmt::ImplicitCastExprClass:
2327 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2329 case Stmt::ConstantExprClass:
2330 return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2332 case Stmt::IndirectGotoStmtClass:
2333 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2335 case Stmt::LabelStmtClass:
2336 return VisitLabelStmt(cast<LabelStmt>(S));
2338 case Stmt::LambdaExprClass:
2339 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2341 case Stmt::MaterializeTemporaryExprClass:
2342 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2345 case Stmt::MemberExprClass:
2346 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2348 case Stmt::NullStmtClass:
2351 case Stmt::ObjCAtCatchStmtClass:
2352 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2354 case Stmt::ObjCAutoreleasePoolStmtClass:
2355 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2357 case Stmt::ObjCAtSynchronizedStmtClass:
2358 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2360 case Stmt::ObjCAtThrowStmtClass:
2361 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2363 case Stmt::ObjCAtTryStmtClass:
2364 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2366 case Stmt::ObjCForCollectionStmtClass:
2367 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2369 case Stmt::ObjCMessageExprClass:
2370 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2372 case Stmt::OpaqueValueExprClass:
2375 case Stmt::PseudoObjectExprClass:
2376 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2378 case Stmt::ReturnStmtClass:
2379 case Stmt::CoreturnStmtClass:
2380 return VisitReturnStmt(S);
2382 case Stmt::CoyieldExprClass:
2383 case Stmt::CoawaitExprClass:
2384 return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);
2386 case Stmt::SEHExceptStmtClass:
2387 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2389 case Stmt::SEHFinallyStmtClass:
2390 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2392 case Stmt::SEHLeaveStmtClass:
2393 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2395 case Stmt::SEHTryStmtClass:
2396 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2398 case Stmt::UnaryExprOrTypeTraitExprClass:
2399 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2402 case Stmt::StmtExprClass:
2403 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2405 case Stmt::SwitchStmtClass:
2406 return VisitSwitchStmt(cast<SwitchStmt>(S));
2408 case Stmt::UnaryOperatorClass:
2409 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2411 case Stmt::WhileStmtClass:
2412 return VisitWhileStmt(cast<WhileStmt>(S));
2414 case Stmt::ArrayInitLoopExprClass:
2415 return VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);
2419CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2420 if (asc.alwaysAdd(*
this, S)) {
2422 appendStmt(
Block, S);
2425 return VisitChildren(S);
2434 reverse_children RChildren(S);
2435 for (
Stmt *Child : RChildren) {
2444 if (asc.alwaysAdd(*
this, ILE)) {
2446 appendStmt(
Block, ILE);
2450 reverse_children RChildren(ILE);
2451 for (
Stmt *Child : RChildren) {
2457 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2458 if (
Stmt *Child = DIE->getExpr())
2467 AddStmtChoice asc) {
2468 AddressTakenLabels.insert(A->
getLabel());
2470 if (asc.alwaysAdd(*
this, A)) {
2472 appendStmt(
Block, A);
2479 bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->
getAttrs());
2480 assert((!isFallthrough || isa<NullStmt>(A->
getSubStmt())) &&
2481 "expected fallthrough not to have children");
2482 return isFallthrough;
2486 AddStmtChoice asc) {
2497 appendStmt(
Block, A);
2500 return VisitChildren(A);
2504 if (asc.alwaysAdd(*
this,
U)) {
2509 if (
U->getOpcode() == UO_LNot)
2510 tryEvaluateBool(
U->getSubExpr()->IgnoreParens());
2512 return Visit(
U->getSubExpr(), AddStmtChoice());
2517 appendStmt(ConfluenceBlock, B);
2522 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2523 ConfluenceBlock).first;
2526std::pair<CFGBlock*, CFGBlock*>
2539 if (B_RHS->isLogicalOp()) {
2540 std::tie(RHSBlock, ExitBlock) =
2541 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2549 ExitBlock = RHSBlock = createBlock(
false);
2554 TryResult KnownVal = tryEvaluateBool(RHS);
2555 if (!KnownVal.isKnown())
2556 KnownVal = tryEvaluateBool(B);
2559 assert(TrueBlock == FalseBlock);
2560 addSuccessor(RHSBlock, TrueBlock);
2564 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2565 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2569 RHSBlock = addStmt(RHS);
2574 return std::make_pair(
nullptr,
nullptr);
2580 if (B_LHS->isLogicalOp()) {
2582 FalseBlock = RHSBlock;
2584 TrueBlock = RHSBlock;
2589 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2594 CFGBlock *LHSBlock = createBlock(
false);
2598 CFGBlock *EntryLHSBlock = addStmt(LHS);
2601 return std::make_pair(
nullptr,
nullptr);
2604 TryResult KnownVal = tryEvaluateBool(LHS);
2608 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2609 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2612 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2613 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2616 return std::make_pair(EntryLHSBlock, ExitBlock);
2620 AddStmtChoice asc) {
2623 return VisitLogicalOperator(B);
2627 appendStmt(
Block, B);
2629 return addStmt(B->
getLHS());
2633 if (asc.alwaysAdd(*
this, B)) {
2635 appendStmt(
Block, B);
2638 return Visit(B->
getRHS());
2641 if (asc.alwaysAdd(*
this, B)) {
2643 appendStmt(
Block, B);
2654 return (LBlock ? LBlock : RBlock);
2657CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *
E, AddStmtChoice asc) {
2658 if (asc.alwaysAdd(*
this,
E)) {
2672 Block = createBlock(
false);
2677 if (BreakJumpTarget.block) {
2678 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2679 addSuccessor(
Block, BreakJumpTarget.block);
2703 QualType calleeType =
C->getCallee()->getType();
2709 if (!boundType.
isNull()) calleeType = boundType;
2715 bool AddEHEdge =
false;
2725 bool OmitArguments =
false;
2732 if (!FD->isVariadic())
2733 findConstructionContextsForArguments(
C);
2735 if (FD->isNoReturn() ||
C->isBuiltinAssumeFalse(*Context))
2737 if (FD->
hasAttr<NoThrowAttr>())
2739 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2740 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2741 OmitArguments =
true;
2744 if (!
CanThrow(
C->getCallee(), *Context))
2747 if (OmitArguments) {
2748 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2749 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2752 return Visit(
C->getCallee());
2755 if (!NoReturn && !AddEHEdge) {
2759 return VisitChildren(
C);
2769 Block = createNoReturnBlock();
2771 Block = createBlock();
2777 if (TryTerminatedBlock)
2778 addSuccessor(
Block, TryTerminatedBlock);
2780 addSuccessor(
Block, &cfg->getExit());
2783 return VisitChildren(
C);
2787 AddStmtChoice asc) {
2789 appendStmt(ConfluenceBlock,
C);
2793 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2794 Succ = ConfluenceBlock;
2796 CFGBlock *LHSBlock = Visit(
C->getLHS(), alwaysAdd);
2800 Succ = ConfluenceBlock;
2802 CFGBlock *RHSBlock = Visit(
C->getRHS(), alwaysAdd);
2806 Block = createBlock(
false);
2808 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2809 addSuccessor(
Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2810 addSuccessor(
Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2812 return addStmt(
C->getCond());
2816 bool ExternallyDestructed) {
2817 LocalScope::const_iterator scopeBeginPos = ScopePos;
2818 addLocalScopeForStmt(
C);
2820 if (!
C->body_empty() && !isa<ReturnStmt>(*
C->body_rbegin())) {
2823 addAutomaticObjHandling(ScopePos, scopeBeginPos,
C);
2828 for (
Stmt *S : llvm::reverse(
C->body())) {
2831 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2832 ExternallyDestructed);
2835 LastBlock = newBlock;
2840 ExternallyDestructed =
false;
2847 AddStmtChoice asc) {
2854 appendStmt(ConfluenceBlock,
C);
2858 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2864 Succ = ConfluenceBlock;
2867 const Expr *trueExpr =
C->getTrueExpr();
2868 if (trueExpr != opaqueValue) {
2869 LHSBlock = Visit(
C->getTrueExpr(), alwaysAdd);
2875 LHSBlock = ConfluenceBlock;
2878 Succ = ConfluenceBlock;
2879 CFGBlock *RHSBlock = Visit(
C->getFalseExpr(), alwaysAdd);
2885 dyn_cast<BinaryOperator>(
C->getCond()->IgnoreParens()))
2886 if (Cond->isLogicalOp())
2887 return VisitLogicalOperator(Cond,
C, LHSBlock, RHSBlock).first;
2890 Block = createBlock(
false);
2893 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2894 addSuccessor(
Block, LHSBlock, !KnownVal.isFalse());
2895 addSuccessor(
Block, RHSBlock, !KnownVal.isTrue());
2897 Expr *condExpr =
C->getCond();
2902 if (condExpr != opaqueValue)
2910 return addStmt(condExpr);
2921 return VisitDeclSubExpr(DS);
2935 cfg->addSyntheticDeclStmt(DSNew, DS);
2938 B = VisitDeclSubExpr(DSNew);
2947 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2949 if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl())) {
2951 const Type *
T = TND->getUnderlyingType().getTypePtr();
2956 appendStmt(
Block, DS);
2960 VA =
FindVA(VA->getElementType().getTypePtr())) {
2961 if (
CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
2962 LastBlock = NewBlock;
2975 bool HasTemporaries =
false;
2978 CFGBlock *blockAfterStaticInit =
nullptr;
2989 blockAfterStaticInit = Succ;
2996 HasTemporaries = isa<ExprWithCleanups>(
Init);
3000 TempDtorContext Context;
3001 VisitForTemporaryDtors(cast<ExprWithCleanups>(
Init)->getSubExpr(),
3008 if (
const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
3009 for (
auto *BD : llvm::reverse(DD->bindings())) {
3010 if (
auto *VD = BD->getHoldingVar()) {
3014 cfg->addSyntheticDeclStmt(DSNew, DS);
3015 Block = VisitDeclSubExpr(DSNew);
3021 appendStmt(
Block, DS);
3025 const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(
Init);
3027 findConstructionContexts(
3029 AILE ? AILE->getSubExpr() :
Init);
3037 if (HasTemporaries) {
3042 LastBlock = newBlock;
3046 LastBlock = newBlock;
3054 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
3055 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3056 LastBlock = newBlock;
3059 maybeAddScopeBeginForVarDecl(
Block, VD, DS);
3062 if (ScopePos && VD == *ScopePos)
3066 if (blockAfterStaticInit) {
3068 Block = createBlock(
false);
3070 addSuccessor(
Block, blockAfterStaticInit);
3071 addSuccessor(
Block, B);
3092 addLocalScopeForStmt(
Init);
3097 addLocalScopeForVarDecl(VD);
3099 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3121 if (!isa<CompoundStmt>(Else))
3122 addLocalScopeAndDtors(Else);
3124 ElseBlock = addStmt(Else);
3127 ElseBlock = sv.get();
3144 if (!isa<CompoundStmt>(Then))
3145 addLocalScopeAndDtors(Then);
3147 ThenBlock = addStmt(Then);
3153 ThenBlock = createBlock(
false);
3154 addSuccessor(ThenBlock, sv.get());
3174 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
3177 Block = createBlock(
false);
3185 KnownVal = tryEvaluateBool(I->
getCond());
3189 addSuccessor(
Block, ThenBlock, !KnownVal.isFalse());
3190 addSuccessor(
Block, ElseBlock, !KnownVal.isTrue());
3198 LastBlock = addStmt(I->
getCond());
3204 LastBlock = addStmt(
const_cast<DeclStmt *
>(DS));
3211 LastBlock = addStmt(
Init);
3224 assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
3227 Block = createBlock(
false);
3229 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3231 if (
auto *R = dyn_cast<ReturnStmt>(S))
3232 findConstructionContexts(
3239 addSuccessor(
Block, &cfg->getExit());
3242 appendStmt(
Block, S);
3245 if (
ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3246 if (
Expr *O = RS->getRetValue())
3247 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3257 if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV))
3266 AddStmtChoice asc) {
3270 if (asc.alwaysAdd(*
this,
E)) {
3275 if (
auto *R = Visit(
E->getResumeExpr()))
3277 if (
auto *R = Visit(
E->getSuspendExpr()))
3279 if (
auto *R = Visit(
E->getReadyExpr()))
3281 if (
auto *R = Visit(
E->getCommonExpr()))
3296 if (!SEHExceptBlock)
3297 SEHExceptBlock = createBlock();
3299 appendStmt(SEHExceptBlock, ES);
3311 return SEHExceptBlock;
3315 return VisitCompoundStmt(FS->getBlock(),
false);
3325 Block = createBlock(
false);
3330 if (SEHLeaveJumpTarget.block) {
3331 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3332 addSuccessor(
Block, SEHLeaveJumpTarget.block);
3342 CFGBlock *SEHTrySuccessor =
nullptr;
3347 SEHTrySuccessor =
Block;
3348 }
else SEHTrySuccessor = Succ;
3354 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3357 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3364 Succ = SEHTrySuccessor;
3366 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3371 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3373 if (PrevSEHTryTerminatedBlock)
3374 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3376 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3379 Succ = SEHTrySuccessor;
3382 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3383 cfg->addTryDispatchBlock(TryTerminatedBlock);
3389 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3391 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3402 LabelBlock = createBlock();
3404 assert(!LabelMap.contains(L->
getDecl()) &&
"label already in map");
3405 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3425 CFGBlock *LastBlock = VisitNoRecurse(
E, asc);
3427 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3437 CFGBlock *LastBlock = VisitNoRecurse(
E, asc);
3441 et =
E->capture_init_end();
3442 it != et; ++it, ++Idx) {
3447 dyn_cast<ArrayInitLoopExpr>(
Init));
3450 cfg->getBumpVectorContext(), {E, Idx}),
3451 AILEInit ? AILEInit :
Init);
3465 Block = createBlock(
false);
3469 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3471 if (I == LabelMap.end())
3473 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3475 JumpTarget JT = I->second;
3476 addSuccessor(
Block, JT.block);
3477 addScopeChangesHandling(ScopePos, JT.scopePosition, G);
3488 return VisitStmt(G, asc);
3495 Block = createBlock();
3498 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3501 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3502 return VisitChildren(G);
3516 addLocalScopeForStmt(
Init);
3517 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3520 addLocalScopeForVarDecl(VD);
3521 LocalScope::const_iterator ContinueScopePos = ScopePos;
3523 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3532 LoopSuccessor =
Block;
3534 LoopSuccessor = Succ;
3539 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3541 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3554 Block = Succ = TransitionBlock = createBlock(
false);
3555 TransitionBlock->setLoopTarget(F);
3560 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3570 assert(
Block == Succ);
3578 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3579 ContinueJumpTarget.block->setLoopTarget(F);
3584 if (!isa<CompoundStmt>(F->
getBody()))
3585 addLocalScopeAndDtors(F->
getBody());
3589 BodyBlock = addStmt(F->
getBody());
3594 BodyBlock = ContinueJumpTarget.block;
3603 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3612 dyn_cast_or_null<BinaryOperator>(
C ?
C->IgnoreParens() :
nullptr))
3614 std::tie(EntryConditionBlock, ExitConditionBlock) =
3615 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3620 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3621 ExitConditionBlock->setTerminator(F);
3624 TryResult KnownVal(
true);
3630 Block = ExitConditionBlock;
3631 EntryConditionBlock = addStmt(
C);
3640 findConstructionContexts(
3643 appendStmt(
Block, DS);
3644 EntryConditionBlock = addStmt(
Init);
3645 assert(
Block == EntryConditionBlock);
3646 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3650 if (
Block && badCFG)
3653 KnownVal = tryEvaluateBool(
C);
3657 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3660 addSuccessor(ExitConditionBlock,
3661 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3665 addSuccessor(TransitionBlock, EntryConditionBlock);
3668 Succ = EntryConditionBlock;
3674 ScopePos = LoopBeginScopePos;
3675 Block = createBlock();
3682 Succ = EntryConditionBlock;
3683 return EntryConditionBlock;
3688 AddStmtChoice asc) {
3689 findConstructionContexts(
3693 return VisitStmt(MTE, asc);
3697 if (asc.alwaysAdd(*
this, M)) {
3699 appendStmt(
Block, M);
3741 LoopSuccessor =
Block;
3744 LoopSuccessor = Succ;
3747 CFGBlock *ExitConditionBlock = createBlock(
false);
3755 appendStmt(ExitConditionBlock, S);
3756 Block = ExitConditionBlock;
3761 CFGBlock *EntryConditionBlock = Visit(S->getElement(),
3762 AddStmtChoice::NotAlwaysAdd);
3771 Succ = EntryConditionBlock;
3778 save_break(BreakJumpTarget);
3784 Succ = LoopBackBlock = createBlock();
3787 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3788 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3790 CFGBlock *BodyBlock = addStmt(S->getBody());
3793 BodyBlock = ContinueJumpTarget.block;
3800 addSuccessor(ExitConditionBlock, BodyBlock);
3805 addSuccessor(ExitConditionBlock, LoopSuccessor);
3808 Block = createBlock();
3809 return addStmt(S->getCollection());
3814 return addStmt(S->getSubStmt());
3822 CFGBlock *SyncBlock = addStmt(S->getSynchBody());
3836 appendStmt(
Block, S);
3839 return addStmt(S->getSynchExpr());
3852 for (
unsigned i =
E->getNumSemanticExprs(); i != 0; ) {
3853 Expr *Semantic =
E->getSemanticExpr(--i);
3858 Semantic = OVE->getSourceExpr();
3876 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3878 addLocalScopeForVarDecl(VD);
3879 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3888 LoopSuccessor =
Block;
3891 LoopSuccessor = Succ;
3894 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3903 save_break(BreakJumpTarget);
3907 Succ = TransitionBlock = createBlock(
false);
3908 TransitionBlock->setLoopTarget(W);
3909 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3912 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3915 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3919 if (!isa<CompoundStmt>(W->
getBody()))
3920 addLocalScopeAndDtors(W->
getBody());
3923 BodyBlock = addStmt(W->
getBody());
3926 BodyBlock = ContinueJumpTarget.block;
3927 else if (
Block && badCFG)
3934 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3941 if (
BinaryOperator *Cond = dyn_cast<BinaryOperator>(
C->IgnoreParens()))
3943 std::tie(EntryConditionBlock, ExitConditionBlock) =
3944 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3949 ExitConditionBlock = createBlock(
false);
3955 Block = ExitConditionBlock;
3956 Block = EntryConditionBlock = addStmt(
C);
3965 findConstructionContexts(
3969 appendStmt(
Block, DS);
3970 EntryConditionBlock = addStmt(
Init);
3971 assert(
Block == EntryConditionBlock);
3972 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3976 if (
Block && badCFG)
3980 const TryResult& KnownVal = tryEvaluateBool(
C);
3983 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3986 addSuccessor(ExitConditionBlock,
3987 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3991 addSuccessor(TransitionBlock, EntryConditionBlock);
3998 Succ = EntryConditionBlock;
3999 return EntryConditionBlock;
4003 AddStmtChoice asc) {
4004 if (asc.alwaysAdd(*
this, A)) {
4006 appendStmt(
Block, A);
4015 assert(OVE &&
"ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
4016 "OpaqueValueExpr!");
4017 if (
CFGBlock *R = Visit(OVE->getSourceExpr()))
4036 CatchBlock = createBlock();
4038 appendStmt(CatchBlock, CS);
4059 Block = createBlock(
false);
4061 if (TryTerminatedBlock)
4063 addSuccessor(
Block, TryTerminatedBlock);
4066 addSuccessor(
Block, &cfg->getExit());
4070 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4081 TrySuccessor =
Block;
4083 TrySuccessor = Succ;
4089 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4092 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4096 bool HasCatchAll =
false;
4099 Succ = TrySuccessor;
4104 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4109 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4114 if (PrevTryTerminatedBlock)
4115 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4117 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4121 Succ = TrySuccessor;
4124 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4125 cfg->addTryDispatchBlock(TryTerminatedBlock);
4127 assert(Terminator->
getTryBody() &&
"try must contain a non-NULL body");
4133 AddStmtChoice asc) {
4134 findConstructionContextsForArguments(ME);
4137 appendObjCMessage(
Block, ME);
4139 return VisitChildren(ME);
4148 Block = createBlock(
false);
4150 if (TryTerminatedBlock)
4152 addSuccessor(
Block, TryTerminatedBlock);
4155 addSuccessor(
Block, &cfg->getExit());
4159 return VisitStmt(
T, AddStmtChoice::AlwaysAdd);
4163 if (asc.alwaysAdd(*
this, S)) {
4165 appendStmt(
Block, S);
4174 if (!S->isTypeDependent() && S->isPotentiallyEvaluated())
4175 return VisitChildren(S);
4191 LoopSuccessor =
Block;
4193 LoopSuccessor = Succ;
4198 CFGBlock *ExitConditionBlock = createBlock(
false);
4199 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4206 if (
Stmt *
C =
D->getCond()) {
4207 Block = ExitConditionBlock;
4208 EntryConditionBlock = addStmt(
C);
4216 Succ = EntryConditionBlock;
4219 const TryResult &KnownVal = tryEvaluateBool(
D->getCond());
4229 save_break(BreakJumpTarget);
4232 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4235 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4242 if (!isa<CompoundStmt>(
D->
getBody()))
4243 addLocalScopeAndDtors(
D->
getBody());
4249 BodyBlock = EntryConditionBlock;
4262 CFGBlock *LoopBackBlock = createBlock();
4265 if (!KnownVal.isFalse())
4267 addSuccessor(ExitConditionBlock, LoopBackBlock);
4269 addSuccessor(ExitConditionBlock,
nullptr);
4274 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4292 Block = createBlock(
false);
4297 if (ContinueJumpTarget.block) {
4298 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,
C);
4299 addSuccessor(
Block, ContinueJumpTarget.block);
4307 AddStmtChoice asc) {
4308 if (asc.alwaysAdd(*
this,
E)) {
4316 if (
E->getKind() != UETT_SizeOf)
4321 if (
E->isArgumentType()) {
4323 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4324 lastBlock = addStmt(VA->getSizeExpr());
4332 if (asc.alwaysAdd(*
this, SE)) {
4334 appendStmt(
Block, SE);
4336 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4342 CFGBlock *SwitchSuccessor =
nullptr;
4350 addLocalScopeForStmt(
Init);
4355 addLocalScopeForVarDecl(VD);
4357 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4362 SwitchSuccessor =
Block;
4363 }
else SwitchSuccessor = Succ;
4367 save_default(DefaultCaseBlock);
4373 DefaultCaseBlock = SwitchSuccessor;
4376 SwitchTerminatedBlock = createBlock(
false);
4380 Succ = SwitchSuccessor;
4381 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4386 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4391 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered,
false);
4394 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4396 bool b = tryEvaluate(Terminator->
getCond(), result);
4401 if (!isa<CompoundStmt>(Terminator->
getBody()))
4402 addLocalScopeAndDtors(Terminator->
getBody());
4404 addStmt(Terminator->
getBody());
4416 bool SwitchAlwaysHasSuccessor =
false;
4417 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4420 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4421 !SwitchAlwaysHasSuccessor);
4425 Block = SwitchTerminatedBlock;
4434 LastBlock = addStmt(
Init);
4435 maybeAddScopeBeginForVarDecl(LastBlock, VD,
Init);
4442 LastBlock = addStmt(
Init);
4455 bool addCase =
false;
4457 if (!switchExclusivelyCovered) {
4461 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4463 if (condInt == lhsInt) {
4465 switchExclusivelyCovered =
true;
4467 else if (condInt > lhsInt) {
4471 if (V2 >= condInt) {
4473 switchExclusivelyCovered =
true;
4487 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4493 while (isa<CaseStmt>(Sub)) {
4494 CFGBlock *currentBlock = createBlock(
false);
4498 addSuccessor(LastBlock, currentBlock);
4500 TopBlock = currentBlock;
4502 addSuccessor(SwitchTerminatedBlock,
4505 ? currentBlock :
nullptr);
4507 LastBlock = currentBlock;
4508 CS = cast<CaseStmt>(Sub);
4517 CaseBlock = createBlock();
4528 assert(SwitchTerminatedBlock);
4529 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4537 addSuccessor(LastBlock, CaseBlock);
4551 DefaultCaseBlock =
Block;
4553 if (!DefaultCaseBlock)
4554 DefaultCaseBlock = createBlock();
4558 DefaultCaseBlock->
setLabel(Terminator);
4573 Succ = DefaultCaseBlock;
4575 return DefaultCaseBlock;
4586 TrySuccessor =
Block;
4588 TrySuccessor = Succ;
4590 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4593 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4597 bool HasCatchAll =
false;
4600 Succ = TrySuccessor;
4606 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4611 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4614 if (PrevTryTerminatedBlock)
4615 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4617 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4621 Succ = TrySuccessor;
4624 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4625 cfg->addTryDispatchBlock(TryTerminatedBlock);
4627 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4643 LocalScope::const_iterator BeginScopePos = ScopePos;
4644 addLocalScopeForVarDecl(VD);
4645 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4653 CatchBlock = createBlock();
4659 appendStmt(CatchBlock, CS);
4694 addLocalScopeForStmt(
Range);
4696 addLocalScopeForStmt(
Begin);
4697 if (
Stmt *End = S->getEndStmt())
4698 addLocalScopeForStmt(End);
4699 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4701 LocalScope::const_iterator ContinueScopePos = ScopePos;
4709 LoopSuccessor =
Block;
4711 LoopSuccessor = Succ;
4716 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4719 CFGBlock *ConditionBlock = createBlock(
false);
4723 if (
Expr *
C = S->getCond()) {
4724 Block = ConditionBlock;
4725 CFGBlock *BeginConditionBlock = addStmt(
C);
4728 assert(BeginConditionBlock == ConditionBlock &&
4729 "condition block in for-range was unexpectedly complex");
4730 (void)BeginConditionBlock;
4735 Succ = ConditionBlock;
4738 TryResult KnownVal(
true);
4741 KnownVal = tryEvaluateBool(S->getCond());
4745 assert(S->getBody());
4754 Succ = addStmt(S->getInc());
4757 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4761 ContinueJumpTarget.block->setLoopTarget(S);
4770 addLocalScopeAndDtors(S->getLoopVarStmt());
4774 if (!isa<CompoundStmt>(S->getBody()))
4775 addLocalScopeAndDtors(S->getBody());
4778 addStmt(S->getBody());
4782 CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
4787 addSuccessor(ConditionBlock,
4788 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
4793 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4796 Block = createBlock();
4797 addStmt(S->getBeginStmt());
4798 addStmt(S->getEndStmt());
4799 CFGBlock *Head = addStmt(S->getRangeStmt());
4801 Head = addStmt(S->getInit());
4806 AddStmtChoice asc,
bool ExternallyDestructed) {
4810 TempDtorContext Context;
4811 VisitForTemporaryDtors(
E->getSubExpr(), ExternallyDestructed, Context);
4815 asc = asc.withAlwaysAdd(
true);
4817 return Visit(
E->getSubExpr(), asc);
4821 AddStmtChoice asc) {
4822 if (asc.alwaysAdd(*
this,
E)) {
4826 findConstructionContexts(
4831 asc = asc.withAlwaysAdd(
false);
4833 return Visit(
E->getSubExpr(), asc);
4837 AddStmtChoice asc) {
4841 findConstructionContextsForArguments(
C);
4842 appendConstructor(
C);
4844 return VisitChildren(
C);
4848 AddStmtChoice asc) {
4850 appendStmt(
Block, NE);
4852 findConstructionContexts(
4856 if (
NE->getInitializer())
4857 Block = Visit(
NE->getInitializer());
4860 appendNewAllocator(
Block, NE);
4862 if (
NE->isArray() && *
NE->getArraySize())
4863 Block = Visit(*
NE->getArraySize());
4866 E =
NE->placement_arg_end(); I !=
E; ++I)
4873 AddStmtChoice asc) {
4875 appendStmt(
Block, DE);
4882 appendDeleteDtor(
Block, RD, DE);
4886 return VisitChildren(DE);
4890 AddStmtChoice asc) {
4891 if (asc.alwaysAdd(*
this,
E)) {
4895 asc = asc.withAlwaysAdd(
false);
4897 return Visit(
E->getSubExpr(), asc);
4901 AddStmtChoice asc) {
4905 findConstructionContextsForArguments(
E);
4906 appendConstructor(
E);
4908 return VisitChildren(
E);
4912 AddStmtChoice asc) {
4913 if (asc.alwaysAdd(*
this,
E)) {
4918 if (
E->getCastKind() == CK_IntegralToBoolean)
4921 return Visit(
E->getSubExpr(), AddStmtChoice());
4925 return Visit(
E->getSubExpr(), AddStmtChoice());
4930 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4933 IBlock = createBlock(
false);
4934 cfg->setIndirectGotoBlock(IBlock);
4942 Block = createBlock(
false);
4944 addSuccessor(
Block, IBlock);
4948CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *
E,
bool ExternallyDestructed,
4949 TempDtorContext &Context) {
4959 return VisitChildrenForTemporaryDtors(
E,
false, Context);
4961 case Stmt::InitListExprClass:
4962 return VisitChildrenForTemporaryDtors(
E, ExternallyDestructed, Context);
4964 case Stmt::BinaryOperatorClass:
4965 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(
E),
4966 ExternallyDestructed,
4969 case Stmt::CXXBindTemporaryExprClass:
4970 return VisitCXXBindTemporaryExprForTemporaryDtors(
4971 cast<CXXBindTemporaryExpr>(
E), ExternallyDestructed, Context);
4973 case Stmt::BinaryConditionalOperatorClass:
4974 case Stmt::ConditionalOperatorClass:
4975 return VisitConditionalOperatorForTemporaryDtors(
4976 cast<AbstractConditionalOperator>(
E), ExternallyDestructed, Context);
4978 case Stmt::ImplicitCastExprClass:
4980 E = cast<CastExpr>(
E)->getSubExpr();
4983 case Stmt::CXXFunctionalCastExprClass:
4985 E = cast<CXXFunctionalCastExpr>(
E)->getSubExpr();
4988 case Stmt::ConstantExprClass:
4989 E = cast<ConstantExpr>(
E)->getSubExpr();
4992 case Stmt::ParenExprClass:
4993 E = cast<ParenExpr>(
E)->getSubExpr();
4996 case Stmt::MaterializeTemporaryExprClass: {
5002 E =
const_cast<Expr *
>(
5003 cast<MaterializeTemporaryExpr>(
E)
5005 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
5007 for (
const Expr *CommaLHS : CommaLHSs) {
5008 VisitForTemporaryDtors(
const_cast<Expr *
>(CommaLHS),
5014 case Stmt::BlockExprClass:
5019 case Stmt::LambdaExprClass: {
5022 auto *
LE = cast<LambdaExpr>(
E);
5026 if (
CFGBlock *R = VisitForTemporaryDtors(
5027 Init,
true, Context))
5034 case Stmt::StmtExprClass:
5039 case Stmt::CXXDefaultArgExprClass:
5040 E = cast<CXXDefaultArgExpr>(
E)->getExpr();
5043 case Stmt::CXXDefaultInitExprClass:
5044 E = cast<CXXDefaultInitExpr>(
E)->getExpr();
5049CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *
E,
5050 bool ExternallyDestructed,
5051 TempDtorContext &Context) {
5052 if (isa<LambdaExpr>(
E)) {
5064 if (
CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
5070CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
5071 BinaryOperator *
E,
bool ExternallyDestructed, TempDtorContext &Context) {
5072 if (
E->isCommaOp()) {
5075 CFGBlock *LHSBlock = VisitForTemporaryDtors(
E->getLHS(),
false, Context);
5076 CFGBlock *RHSBlock = VisitForTemporaryDtors(
E->getRHS(), ExternallyDestructed, Context);
5077 return RHSBlock ? RHSBlock : LHSBlock;
5080 if (
E->isLogicalOp()) {
5081 VisitForTemporaryDtors(
E->getLHS(),
false, Context);
5082 TryResult RHSExecuted = tryEvaluateBool(
E->getLHS());
5083 if (RHSExecuted.isKnown() &&
E->getOpcode() == BO_LOr)
5084 RHSExecuted.negate();
5089 TempDtorContext RHSContext(
5091 VisitForTemporaryDtors(
E->getRHS(),
false, RHSContext);
5092 InsertTempDtorDecisionBlock(RHSContext);
5097 if (
E->isAssignmentOp()) {
5100 CFGBlock *RHSBlock = VisitForTemporaryDtors(
E->getRHS(),
false, Context);
5101 CFGBlock *LHSBlock = VisitForTemporaryDtors(
E->getLHS(),
false, Context);
5102 return LHSBlock ? LHSBlock : RHSBlock;
5106 return VisitChildrenForTemporaryDtors(
E, ExternallyDestructed, Context);
5109CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5113 CFGBlock *B = VisitForTemporaryDtors(
E->getSubExpr(),
true, Context);
5114 if (!ExternallyDestructed) {
5126 Block = createNoReturnBlock();
5127 }
else if (Context.needsTempDtorBranch()) {
5131 Block = createBlock();
5135 if (Context.needsTempDtorBranch()) {
5136 Context.setDecisionPoint(Succ,
E);
5138 appendTemporaryDtor(
Block,
E);
5145void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
5147 if (!Context.TerminatorExpr) {
5151 assert(Context.TerminatorExpr);
5152 CFGBlock *Decision = createBlock(
false);
5155 addSuccessor(Decision,
Block, !Context.KnownExecuted.isFalse());
5156 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5157 !Context.KnownExecuted.isTrue());
5161CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
5163 TempDtorContext &Context) {
5164 VisitForTemporaryDtors(
E->getCond(),
false, Context);
5167 TryResult ConditionVal = tryEvaluateBool(
E->getCond());
5168 TryResult NegatedVal = ConditionVal;
5169 if (NegatedVal.isKnown()) NegatedVal.negate();
5171 TempDtorContext TrueContext(
5173 VisitForTemporaryDtors(
E->getTrueExpr(), ExternallyDestructed, TrueContext);
5176 Block = ConditionBlock;
5177 Succ = ConditionSucc;
5178 TempDtorContext FalseContext(
5180 VisitForTemporaryDtors(
E->getFalseExpr(), ExternallyDestructed, FalseContext);
5182 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5183 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
5184 }
else if (TrueContext.TerminatorExpr) {
5186 InsertTempDtorDecisionBlock(TrueContext);
5188 InsertTempDtorDecisionBlock(FalseContext);
5194 AddStmtChoice asc) {
5195 if (asc.alwaysAdd(*
this,
D)) {
5207 for (
Stmt *S : llvm::reverse(
Used)) {
5208 assert(S &&
"Expected non-null used-in-clause child.");
5213 if (!
D->isStandaloneDirective()) {
5214 Stmt *S =
D->getRawStmt();
5215 if (!isa<CompoundStmt>(S))
5216 addLocalScopeAndDtors(S);
5228 bool first_block =
begin() ==
end();
5236 Entry = Exit = &
back();
5245 CFGBuilder Builder(
C, BO);
5246 return Builder.buildCFG(
D, Statement);
5261 auto IteratorAndFlag =
Visited.insert(B);
5262 if (!IteratorAndFlag.second) {
5268 const CFGBlock *FirstReachableB =
nullptr;
5270 if (!AB.isReachable())
5273 if (FirstReachableB ==
nullptr) {
5274 FirstReachableB = &*AB;
5281 if (!FirstReachableB) {
5287 B = FirstReachableB;
5307 llvm_unreachable(
"getDestructorDecl should only be used with "
5310 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
5318 if (
const Expr *
Init = var->getInit()) {
5336 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
5345 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
5350 const FieldDecl *field = castAs<CFGMemberDtor>().getFieldDecl();
5365 llvm_unreachable(
"getKind() returned bogus value");
5373 : ReachableBlock(IsReachable ? B : nullptr),
5374 UnreachableBlock(!IsReachable ? B : nullptr,
5375 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5378 : ReachableBlock(B),
5379 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
5380 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5403 if (S->isAllEnumCasesCovered()) {
5405 if (!L || !isa<CaseStmt>(L))
5421 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5422 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5426 signed currentBlock = 0;
5427 unsigned currStmt = 0;
5438 BI != BEnd; ++BI, ++j ) {
5439 if (std::optional<CFGStmt> SE = BI->getAs<
CFGStmt>()) {
5441 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
5444 switch (
stmt->getStmtClass()) {
5445 case Stmt::DeclStmtClass:
5446 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
5448 case Stmt::IfStmtClass: {
5449 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
5454 case Stmt::ForStmtClass: {
5455 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
5460 case Stmt::WhileStmtClass: {
5462 cast<WhileStmt>(
stmt)->getConditionVariable();
5467 case Stmt::SwitchStmtClass: {
5469 cast<SwitchStmt>(
stmt)->getConditionVariable();
5474 case Stmt::CXXCatchStmtClass: {
5476 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
5489 ~StmtPrinterHelper()
override =
default;
5491 const LangOptions &getLangOpts()
const {
return LangOpts; }
5492 void setBlockID(
signed i) { currentBlock = i; }
5493 void setStmtID(
unsigned i) { currStmt = i; }
5495 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
5496 StmtMapTy::iterator I = StmtMap.find(S);
5498 if (I == StmtMap.end())
5501 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5502 && I->second.second == currStmt) {
5506 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5510 bool handleDecl(
const Decl *
D, raw_ostream &OS) {
5511 DeclMapTy::iterator I = DeclMap.find(
D);
5513 if (I == DeclMap.end())
5516 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5517 && I->second.second == currStmt) {
5521 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5526class CFGBlockTerminatorPrint
5527 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5529 StmtPrinterHelper* Helper;
5533 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5535 : OS(os), Helper(helper), Policy(Policy) {
5539 void VisitIfStmt(
IfStmt *I) {
5542 C->printPretty(OS, Helper, Policy);
5546 void VisitStmt(
Stmt *Terminator) {
5552 OS <<
"static init " << VD->
getName();
5555 void VisitForStmt(
ForStmt *F) {
5561 C->printPretty(OS, Helper, Policy);
5571 C->printPretty(OS, Helper, Policy);
5575 OS <<
"do ... while ";
5576 if (
Stmt *
C =
D->getCond())
5577 C->printPretty(OS, Helper, Policy);
5580 void VisitSwitchStmt(
SwitchStmt *Terminator) {
5585 void VisitCXXTryStmt(
CXXTryStmt *) { OS <<
"try ..."; }
5587 void VisitObjCAtTryStmt(
ObjCAtTryStmt *) { OS <<
"@try ..."; }
5589 void VisitSEHTryStmt(
SEHTryStmt *CS) { OS <<
"__try ..."; }
5592 if (
Stmt *Cond =
C->getCond())
5594 OS <<
" ? ... : ...";
5598 OS <<
"__builtin_choose_expr( ";
5599 if (
Stmt *Cond =
C->getCond())
5607 T->printPretty(OS, Helper, Policy);
5627 llvm_unreachable(
"Invalid logical operator.");
5631 void VisitExpr(
Expr *
E) {
5637 switch (
T.getKind()) {
5642 OS <<
"(Temp Dtor) ";
5646 OS <<
"(See if most derived ctor has already initialized vbases)";
5664 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5668 OS <<
" (Base initializer)";
5670 OS <<
" (Delegating initializer)";
5672 OS <<
" (Member initializer)";
5676 StmtPrinterHelper &Helper,
5682 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5689 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5691 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5695 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5696 Stmts.push_back(SDSCC->getDeclStmt());
5700 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5701 Stmts.push_back(CDSCC->getDeclStmt());
5702 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5706 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5707 Stmts.push_back(NECC->getCXXNewExpr());
5711 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5712 Stmts.push_back(RSCC->getReturnStmt());
5717 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5718 Stmts.push_back(RSCC->getReturnStmt());
5719 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5723 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5724 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5725 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5729 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5730 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5731 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5732 Stmts.push_back(TOCC->getConstructorAfterElision());
5736 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
5737 Helper.handledStmt(
const_cast<LambdaExpr *
>(LCC->getLambdaExpr()), OS);
5738 OS <<
"+" << LCC->getIndex();
5742 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5743 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5745 Helper.handledStmt(
const_cast<Stmt *
>(BTE), OS);
5748 Helper.handledStmt(
const_cast<Expr *
>(ACC->getCallLikeExpr()), OS);
5749 OS <<
"+" << ACC->getIndex();
5756 Helper.handledStmt(
const_cast<Stmt *
>(I), OS);
5760static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5765 StmtPrinterHelper Helper(
nullptr, LangOpts);
5769static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5771 switch (
E.getKind()) {
5777 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5780 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5783 auto Children = Sub->children();
5784 if (Children.begin() != Children.end()) {