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(); }
763 CFGBlock *createBlock(
bool add_successor =
true);
767 return Visit(S, AddStmtChoice::AlwaysAdd);
771 void addLoopExit(
const Stmt *LoopStmt);
772 void addAutomaticObjHandling(LocalScope::const_iterator B,
773 LocalScope::const_iterator E,
Stmt *S);
774 void addAutomaticObjDestruction(LocalScope::const_iterator B,
775 LocalScope::const_iterator E,
Stmt *S);
776 void addScopeExitHandling(LocalScope::const_iterator B,
777 LocalScope::const_iterator E,
Stmt *S);
779 void addScopeChangesHandling(LocalScope::const_iterator SrcPos,
780 LocalScope::const_iterator DstPos,
782 CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,
784 LocalScope::const_iterator DstPost,
788 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
790 void addLocalScopeForStmt(
Stmt *S);
791 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
792 LocalScope*
Scope =
nullptr);
793 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope*
Scope =
nullptr);
795 void addLocalScopeAndDtors(
Stmt *S);
805 cleanupConstructionContext(E);
813 if (alwaysAdd(S) && cachedEntry)
814 cachedEntry->second = B;
817 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
823 retrieveAndCleanupConstructionContext(CE)) {
829 B->
appendStmt(CE, cfg->getBumpVectorContext());
833 if (alwaysAdd(CE) && cachedEntry)
834 cachedEntry->second = B;
837 retrieveAndCleanupConstructionContext(CE)) {
843 B->
appendStmt(CE, cfg->getBumpVectorContext());
863 if (alwaysAdd(ME) && cachedEntry)
864 cachedEntry->second = B;
867 retrieveAndCleanupConstructionContext(ME)) {
873 cfg->getBumpVectorContext());
892 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
902 cfg->getBumpVectorContext());
909 cfg->getBumpVectorContext());
925 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
929 const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
930 const Expr *BoolExpr = RHSExpr;
931 bool IntFirst =
true;
933 IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
941 llvm::APInt IntValue = IntLiteral->
getValue();
942 if ((IntValue == 1) || (IntValue == 0))
946 !IntValue.isNegative();
949 if (Bok == BO_GT || Bok == BO_GE) {
952 return TryResult(IntFirst == IntLarger);
956 return TryResult(IntFirst != IntLarger);
964 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
968 std::optional<llvm::APInt> IntLiteral1 =
969 getIntegerLiteralSubexpressionValue(LHSExpr);
970 const Expr *BoolExpr = RHSExpr;
973 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
981 if (BitOp && (BitOp->
getOpcode() == BO_And ||
986 std::optional<llvm::APInt> IntLiteral2 =
987 getIntegerLiteralSubexpressionValue(LHSExpr2);
990 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
996 (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
998 (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1002 return TryResult(B->
getOpcode() != BO_EQ);
1005 if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1008 return TryResult(B->
getOpcode() != BO_EQ);
1020 std::optional<llvm::APInt>
1021 getIntegerLiteralSubexpressionValue(
const Expr *E) {
1024 if (
const auto *UnOp = dyn_cast<UnaryOperator>(E->
IgnoreParens())) {
1029 if (
const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1034 switch (UnOp->getOpcode()) {
1044 assert(
false &&
"Unexpected unary operator!");
1045 return std::nullopt;
1048 }
else if (
const auto *IntLiteral =
1052 return std::nullopt;
1056 const llvm::APSInt &Value1,
1057 const llvm::APSInt &Value2) {
1058 assert(Value1.isSigned() == Value2.isSigned());
1063 return TryResult(Value1 == Value2);
1065 return TryResult(Value1 != Value2);
1067 return TryResult(Value1 < Value2);
1069 return TryResult(Value1 <= Value2);
1071 return TryResult(Value1 > Value2);
1073 return TryResult(Value1 >= Value2);
1089 auto CheckLogicalOpWithNegatedVariable = [
this, B](
const Expr *E1,
1091 if (
const auto *Negate = dyn_cast<UnaryOperator>(E1)) {
1092 if (Negate->getOpcode() == UO_LNot &&
1094 bool AlwaysTrue = B->
getOpcode() == BO_LOr;
1097 return TryResult(AlwaysTrue);
1103 TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);
1104 if (Result.isKnown())
1106 Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);
1107 if (Result.isKnown())
1110 const auto *LHS = dyn_cast<BinaryOperator>(LHSExpr);
1111 const auto *RHS = dyn_cast<BinaryOperator>(RHSExpr);
1115 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1118 const Expr *DeclExpr1;
1119 const Expr *NumExpr1;
1123 if (!DeclExpr1 || !NumExpr1)
1126 const Expr *DeclExpr2;
1127 const Expr *NumExpr2;
1131 if (!DeclExpr2 || !NumExpr2)
1148 llvm::APSInt L1 = L1Result.
Val.
getInt();
1149 llvm::APSInt L2 = L2Result.
Val.
getInt();
1152 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1157 const llvm::APSInt Values[] = {
1159 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1163 ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1168 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1177 bool AlwaysTrue =
true, AlwaysFalse =
true;
1180 bool LHSAlwaysTrue =
true, LHSAlwaysFalse =
true;
1181 bool RHSAlwaysTrue =
true, RHSAlwaysFalse =
true;
1182 for (
const llvm::APSInt &
Value : Values) {
1183 TryResult Res1, Res2;
1184 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1185 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1187 if (!Res1.isKnown() || !Res2.isKnown())
1191 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1192 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1194 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1195 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1198 LHSAlwaysTrue &= Res1.isTrue();
1199 LHSAlwaysFalse &= Res1.isFalse();
1200 RHSAlwaysTrue &= Res2.isTrue();
1201 RHSAlwaysFalse &= Res2.isFalse();
1204 if (AlwaysTrue || AlwaysFalse) {
1205 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1206 !RHSAlwaysFalse && BuildOpts.
Observer)
1208 return TryResult(AlwaysTrue);
1214 TryResult checkIncorrectBitwiseOrOperator(
const BinaryOperator *B) {
1215 const Expr *LHSConstant =
1217 const Expr *RHSConstant =
1220 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1223 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1229 if (Result.Val.getInt() == 0)
1235 return TryResult(
true);
1242 return !S->isTypeDependent() &&
1243 !S->isValueDependent() &&
1244 S->EvaluateAsRValue(outResult, *Context);
1249 TryResult tryEvaluateBool(
Expr *S) {
1251 S->isTypeDependent() || S->isValueDependent())
1255 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1257 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1258 if (I != CachedBoolEvals.end())
1262 TryResult Result = evaluateAsBooleanConditionNoCache(S);
1263 CachedBoolEvals[S] = Result;
1267 switch (Bop->getOpcode()) {
1276 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1277 llvm::APSInt IntVal = LHSResult.
Val.
getInt();
1278 if (!IntVal.getBoolValue()) {
1279 return TryResult(
false);
1283 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1284 llvm::APSInt IntVal = RHSResult.
Val.
getInt();
1285 if (!IntVal.getBoolValue()) {
1286 return TryResult(
false);
1295 return evaluateAsBooleanConditionNoCache(S);
1299 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1301 if (Bop->isLogicalOp()) {
1302 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1303 if (LHS.isKnown()) {
1306 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1307 return LHS.isTrue();
1309 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1310 if (RHS.isKnown()) {
1311 if (Bop->getOpcode() == BO_LOr)
1312 return LHS.isTrue() || RHS.isTrue();
1314 return LHS.isTrue() && RHS.isTrue();
1317 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1318 if (RHS.isKnown()) {
1321 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1322 return RHS.isTrue();
1324 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1325 if (BopRes.isKnown())
1326 return BopRes.isTrue();
1331 }
else if (Bop->isEqualityOp()) {
1332 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1333 if (BopRes.isKnown())
1334 return BopRes.isTrue();
1335 }
else if (Bop->isRelationalOp()) {
1336 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1337 if (BopRes.isKnown())
1338 return BopRes.isTrue();
1339 }
else if (Bop->getOpcode() == BO_Or) {
1340 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1341 if (BopRes.isKnown())
1342 return BopRes.isTrue();
1353 bool hasTrivialDestructor(
const VarDecl *VD)
const;
1354 bool needsAutomaticDestruction(
const VarDecl *VD)
const;
1365 while (
const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1366 AILEInit = E->getSubExpr();
1371inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1373 return builder.alwaysAdd(
stmt) || kind == AlwaysAdd;
1376bool CFGBuilder::alwaysAdd(
const Stmt *
stmt) {
1382 if (lastLookup ==
stmt) {
1384 assert(cachedEntry->first ==
stmt);
1397 assert(!cachedEntry);
1401 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(
stmt);
1402 if (itr == fb->end()) {
1403 cachedEntry =
nullptr;
1407 cachedEntry = &*itr;
1414 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1416 if (vat->getSizeExpr())
1419 t = vt->getElementType().getTypePtr();
1425void CFGBuilder::consumeConstructionContext(
1427 assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1428 isa<ObjCMessageExpr>(E)) &&
"Expression cannot construct an object!");
1430 ConstructionContextMap.lookup(E)) {
1431 (void)PreviouslyStoredLayer;
1434 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1435 "Already within a different construction context!");
1437 ConstructionContextMap[E] = Layer;
1441void CFGBuilder::findConstructionContexts(
1454 switch(Child->getStmtClass()) {
1455 case Stmt::CXXConstructExprClass:
1456 case Stmt::CXXTemporaryObjectExprClass: {
1458 auto *CE = cast<CXXConstructExpr>(Child);
1460 findConstructionContexts(withExtraLayer(CE), CE->
getArg(0));
1463 consumeConstructionContext(Layer, CE);
1469 case Stmt::CallExprClass:
1470 case Stmt::CXXMemberCallExprClass:
1471 case Stmt::CXXOperatorCallExprClass:
1472 case Stmt::UserDefinedLiteralClass:
1473 case Stmt::ObjCMessageExprClass: {
1474 auto *E = cast<Expr>(Child);
1476 consumeConstructionContext(Layer, E);
1479 case Stmt::ExprWithCleanupsClass: {
1480 auto *Cleanups = cast<ExprWithCleanups>(Child);
1481 findConstructionContexts(Layer, Cleanups->getSubExpr());
1484 case Stmt::CXXFunctionalCastExprClass: {
1485 auto *
Cast = cast<CXXFunctionalCastExpr>(Child);
1486 findConstructionContexts(Layer,
Cast->getSubExpr());
1489 case Stmt::ImplicitCastExprClass: {
1490 auto *
Cast = cast<ImplicitCastExpr>(Child);
1492 switch (
Cast->getCastKind()) {
1494 case CK_ConstructorConversion:
1495 findConstructionContexts(Layer,
Cast->getSubExpr());
1502 case Stmt::CXXBindTemporaryExprClass: {
1503 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1504 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1507 case Stmt::MaterializeTemporaryExprClass: {
1514 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1515 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1519 case Stmt::ConditionalOperatorClass: {
1520 auto *CO = cast<ConditionalOperator>(Child);
1527 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1531 findConstructionContexts(Layer, CO->getLHS());
1532 findConstructionContexts(Layer, CO->getRHS());
1535 case Stmt::InitListExprClass: {
1536 auto *ILE = cast<InitListExpr>(Child);
1537 if (ILE->isTransparent()) {
1538 findConstructionContexts(Layer, ILE->getInit(0));
1544 case Stmt::ParenExprClass: {
1547 auto *PE = cast<ParenExpr>(Child);
1548 findConstructionContexts(Layer, PE->getSubExpr());
1556void CFGBuilder::cleanupConstructionContext(
Expr *E) {
1558 "We should not be managing construction contexts!");
1559 assert(ConstructionContextMap.count(E) &&
1560 "Cannot exit construction context without the context!");
1561 ConstructionContextMap.erase(E);
1569std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1577 Succ = createBlock();
1578 assert(Succ == &cfg->getExit());
1583 addImplicitDtorsForDestructor(DD);
1603 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1605 for (
auto *I : llvm::reverse(CD->inits())) {
1607 I->isBaseInitializer() && I->isBaseVirtual()) {
1611 VBaseSucc = Succ = B ? B : &cfg->getExit();
1612 Block = createBlock();
1614 B = addInitializer(I);
1624 addSuccessor(B,
Block,
true);
1633 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1634 E = BackpatchBlocks.end(); I != E; ++I ) {
1638 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1641 if (LI == LabelMap.end())
1643 JumpTarget JT = LI->second;
1645 CFGBlock *SuccBlk = createScopeChangesHandlingBlock(
1646 I->scopePosition, B, JT.scopePosition, JT.block);
1647 addSuccessor(B, SuccBlk);
1648 }
else if (
auto *G = dyn_cast<GCCAsmStmt>(B->
getTerminator())) {
1649 CFGBlock *Successor = (I+1)->block;
1650 for (
auto *L : G->labels()) {
1651 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1654 if (LI == LabelMap.end())
1656 JumpTarget JT = LI->second;
1658 if (JT.block == Successor)
1660 addSuccessor(B, JT.block);
1667 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1668 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1669 E = AddressTakenLabels.end(); I != E; ++I ) {
1671 LabelMapTy::iterator LI = LabelMap.find(*I);
1675 if (LI == LabelMap.end())
continue;
1677 addSuccessor(B, LI->second.block);
1681 cfg->setEntry(createBlock());
1684 assert(ConstructionContextMap.empty() &&
1685 "Not all construction contexts were cleaned up!");
1687 return std::move(cfg);
1692CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1694 if (add_successor && Succ)
1695 addSuccessor(B, Succ);
1702CFGBlock *CFGBuilder::createNoReturnBlock() {
1705 addSuccessor(B, &cfg->getExit(), Succ);
1714 bool HasTemporaries =
false;
1720 HasTemporaries = isa<ExprWithCleanups>(Init);
1724 TempDtorContext Context;
1725 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1731 appendInitializer(
Block, I);
1737 dyn_cast<ArrayInitLoopExpr>(Init));
1739 findConstructionContexts(
1741 AILEInit ? AILEInit : Init);
1743 if (HasTemporaries) {
1746 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1770 bool *FoundMTE =
nullptr) {
1773 Init = Init->IgnoreParens();
1777 Init = EWC->getSubExpr();
1783 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1784 Init = MTE->getSubExpr();
1793 const Expr *SkippedInit =
1794 Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
1795 if (SkippedInit != Init) {
1803 return Init->getType();
1808void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1812 appendLoopExit(
Block, LoopStmt);
1820void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1821 LocalScope::const_iterator E,
1831 if (B.inSameLocalScope(E)) {
1832 addAutomaticObjDestruction(B, E, S);
1838 LocalScopeEndMarkers.push_back(B);
1839 for (LocalScope::const_iterator I = B; I != E; ++I) {
1840 if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
1841 LocalScopeEndMarkers.push_back(I);
1843 LocalScopeEndMarkers.push_back(E);
1847 std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
1849 llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
1850 for (
auto [E, B] : Pairwise) {
1851 if (!B.inSameLocalScope(E))
1852 addScopeExitHandling(B, E, S);
1853 addAutomaticObjDestruction(B, E, S);
1860void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
1861 LocalScope::const_iterator E,
1870 DeclsNeedDestruction.reserve(B.distance(E));
1872 for (
VarDecl* D : llvm::make_range(B, E))
1873 if (needsAutomaticDestruction(D))
1874 DeclsNeedDestruction.push_back(D);
1876 for (
VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
1889 Block = createNoReturnBlock();
1898 appendLifetimeEnds(
Block, VD, S);
1900 appendAutomaticObjDtor(
Block, VD, S);
1901 if (VD->
hasAttr<CleanupAttr>())
1902 appendCleanupFunction(
Block, VD);
1911void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
1912 LocalScope::const_iterator E,
Stmt *S) {
1913 assert(!B.inSameLocalScope(E));
1919 appendScopeEnd(
Block, B.getFirstVarInScope(), S);
1927 DeclsTrivial.reserve(B.distance(E));
1932 for (
VarDecl* D : llvm::make_range(B, E))
1933 if (!needsAutomaticDestruction(D))
1934 DeclsTrivial.push_back(D);
1936 if (DeclsTrivial.empty())
1940 for (
VarDecl *VD : llvm::reverse(DeclsTrivial))
1941 appendLifetimeEnds(
Block, VD, S);
1949void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
1950 LocalScope::const_iterator DstPos,
1952 assert(
Block &&
"Source block should be always crated");
1958 if (SrcPos == DstPos)
1963 LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
1966 if (BuildOpts.
AddScopes && !DstPos.inSameLocalScope(BasePos)) {
1967 for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
1968 if (I.pointsToFirstDeclaredVar())
1969 appendScopeBegin(
Block, *I, S);
1974 addAutomaticObjHandling(SrcPos, BasePos, S);
1982CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
1983 LocalScope::const_iterator SrcPos,
CFGBlock *SrcBlk,
1984 LocalScope::const_iterator DstPos,
CFGBlock *DstBlk) {
1985 if (SrcPos == DstPos)
1989 (!BuildOpts.
AddScopes || SrcPos.inSameLocalScope(DstPos)))
1997 Block = createBlock(
false);
2000 addSuccessor(
Block, DstBlk);
2005 assert(
Block &&
"There should be at least one scope changing Block");
2013 "Can be called only when dtors should be added");
2017 for (
const auto &VI : RD->
vbases()) {
2021 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2024 appendBaseDtor(
Block, &VI);
2029 for (
const auto &BI : RD->
bases()) {
2030 if (!BI.isVirtual()) {
2031 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2034 appendBaseDtor(
Block, &BI);
2040 for (
auto *FI : RD->
fields()) {
2045 if (AT->getSize() == 0)
2047 QT = AT->getElementType();
2053 appendMemberDtor(
Block, FI);
2060LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
2063 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
2069void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
2074 LocalScope *
Scope =
nullptr;
2078 for (
auto *BI : CS->body()) {
2080 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2088 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
2089 addLocalScopeForDeclStmt(DS);
2094LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
2095 LocalScope*
Scope) {
2100 for (
auto *DI : DS->
decls())
2101 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
2106bool CFGBuilder::needsAutomaticDestruction(
const VarDecl *VD)
const {
2107 return !hasTrivialDestructor(VD) || VD->
hasAttr<CleanupAttr>();
2110bool CFGBuilder::hasTrivialDestructor(
const VarDecl *VD)
const {
2131 bool FoundMTE =
false;
2139 if (AT->getSize() == 0)
2141 QT = AT->getElementType();
2153LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
2154 LocalScope*
Scope) {
2164 !needsAutomaticDestruction(VD)) {
2172 ScopePos =
Scope->begin();
2178void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
2179 LocalScope::const_iterator scopeBeginPos = ScopePos;
2180 addLocalScopeForStmt(S);
2181 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2187CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc,
2188 bool ExternallyDestructed) {
2194 if (
Expr *E = dyn_cast<Expr>(S))
2195 S = E->IgnoreParens();
2198 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2199 return VisitOMPExecutableDirective(D, asc);
2201 switch (S->getStmtClass()) {
2203 return VisitStmt(S, asc);
2205 case Stmt::ImplicitValueInitExprClass:
2208 return VisitStmt(S, asc);
2210 case Stmt::InitListExprClass:
2211 return VisitInitListExpr(cast<InitListExpr>(S), asc);
2213 case Stmt::AttributedStmtClass:
2214 return VisitAttributedStmt(cast<AttributedStmt>(S), asc);
2216 case Stmt::AddrLabelExprClass:
2217 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2219 case Stmt::BinaryConditionalOperatorClass:
2220 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2222 case Stmt::BinaryOperatorClass:
2223 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2225 case Stmt::BlockExprClass:
2226 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2228 case Stmt::BreakStmtClass:
2229 return VisitBreakStmt(cast<BreakStmt>(S));
2231 case Stmt::CallExprClass:
2232 case Stmt::CXXOperatorCallExprClass:
2233 case Stmt::CXXMemberCallExprClass:
2234 case Stmt::UserDefinedLiteralClass:
2235 return VisitCallExpr(cast<CallExpr>(S), asc);
2237 case Stmt::CaseStmtClass:
2238 return VisitCaseStmt(cast<CaseStmt>(S));
2240 case Stmt::ChooseExprClass:
2241 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2243 case Stmt::CompoundStmtClass:
2244 return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);
2246 case Stmt::ConditionalOperatorClass:
2247 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2249 case Stmt::ContinueStmtClass:
2250 return VisitContinueStmt(cast<ContinueStmt>(S));
2252 case Stmt::CXXCatchStmtClass:
2253 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2255 case Stmt::ExprWithCleanupsClass:
2256 return VisitExprWithCleanups(cast<ExprWithCleanups>(S),
2257 asc, ExternallyDestructed);
2259 case Stmt::CXXDefaultArgExprClass:
2260 case Stmt::CXXDefaultInitExprClass:
2269 return VisitStmt(S, asc);
2271 case Stmt::CXXBindTemporaryExprClass:
2272 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2274 case Stmt::CXXConstructExprClass:
2275 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2277 case Stmt::CXXNewExprClass:
2278 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2280 case Stmt::CXXDeleteExprClass:
2281 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2283 case Stmt::CXXFunctionalCastExprClass:
2284 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2286 case Stmt::CXXTemporaryObjectExprClass:
2287 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2289 case Stmt::CXXThrowExprClass:
2290 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2292 case Stmt::CXXTryStmtClass:
2293 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2295 case Stmt::CXXTypeidExprClass:
2296 return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);
2298 case Stmt::CXXForRangeStmtClass:
2299 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2301 case Stmt::DeclStmtClass:
2302 return VisitDeclStmt(cast<DeclStmt>(S));
2304 case Stmt::DefaultStmtClass:
2305 return VisitDefaultStmt(cast<DefaultStmt>(S));
2307 case Stmt::DoStmtClass:
2308 return VisitDoStmt(cast<DoStmt>(S));
2310 case Stmt::ForStmtClass:
2311 return VisitForStmt(cast<ForStmt>(S));
2313 case Stmt::GotoStmtClass:
2314 return VisitGotoStmt(cast<GotoStmt>(S));
2316 case Stmt::GCCAsmStmtClass:
2317 return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
2319 case Stmt::IfStmtClass:
2320 return VisitIfStmt(cast<IfStmt>(S));
2322 case Stmt::ImplicitCastExprClass:
2323 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2325 case Stmt::ConstantExprClass:
2326 return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2328 case Stmt::IndirectGotoStmtClass:
2329 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2331 case Stmt::LabelStmtClass:
2332 return VisitLabelStmt(cast<LabelStmt>(S));
2334 case Stmt::LambdaExprClass:
2335 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2337 case Stmt::MaterializeTemporaryExprClass:
2338 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2341 case Stmt::MemberExprClass:
2342 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2344 case Stmt::NullStmtClass:
2347 case Stmt::ObjCAtCatchStmtClass:
2348 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2350 case Stmt::ObjCAutoreleasePoolStmtClass:
2351 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2353 case Stmt::ObjCAtSynchronizedStmtClass:
2354 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2356 case Stmt::ObjCAtThrowStmtClass:
2357 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2359 case Stmt::ObjCAtTryStmtClass:
2360 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2362 case Stmt::ObjCForCollectionStmtClass:
2363 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2365 case Stmt::ObjCMessageExprClass:
2366 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2368 case Stmt::OpaqueValueExprClass:
2371 case Stmt::PseudoObjectExprClass:
2372 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2374 case Stmt::ReturnStmtClass:
2375 case Stmt::CoreturnStmtClass:
2376 return VisitReturnStmt(S);
2378 case Stmt::CoyieldExprClass:
2379 case Stmt::CoawaitExprClass:
2380 return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);
2382 case Stmt::SEHExceptStmtClass:
2383 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2385 case Stmt::SEHFinallyStmtClass:
2386 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2388 case Stmt::SEHLeaveStmtClass:
2389 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2391 case Stmt::SEHTryStmtClass:
2392 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2394 case Stmt::UnaryExprOrTypeTraitExprClass:
2395 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2398 case Stmt::StmtExprClass:
2399 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2401 case Stmt::SwitchStmtClass:
2402 return VisitSwitchStmt(cast<SwitchStmt>(S));
2404 case Stmt::UnaryOperatorClass:
2405 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2407 case Stmt::WhileStmtClass:
2408 return VisitWhileStmt(cast<WhileStmt>(S));
2410 case Stmt::ArrayInitLoopExprClass:
2411 return VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);
2415CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2416 if (asc.alwaysAdd(*
this, S)) {
2418 appendStmt(
Block, S);
2421 return VisitChildren(S);
2430 reverse_children RChildren(S);
2431 for (
Stmt *Child : RChildren) {
2440 if (asc.alwaysAdd(*
this, ILE)) {
2442 appendStmt(
Block, ILE);
2446 reverse_children RChildren(ILE);
2447 for (
Stmt *Child : RChildren) {
2453 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2454 if (
Stmt *Child = DIE->getExpr())
2463 AddStmtChoice asc) {
2464 AddressTakenLabels.insert(A->
getLabel());
2466 if (asc.alwaysAdd(*
this, A)) {
2468 appendStmt(
Block, A);
2475 bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->
getAttrs());
2476 assert((!isFallthrough || isa<NullStmt>(A->
getSubStmt())) &&
2477 "expected fallthrough not to have children");
2478 return isFallthrough;
2482 AddStmtChoice asc) {
2493 appendStmt(
Block, A);
2496 return VisitChildren(A);
2500 if (asc.alwaysAdd(*
this,
U)) {
2505 if (
U->getOpcode() == UO_LNot)
2506 tryEvaluateBool(
U->getSubExpr()->IgnoreParens());
2508 return Visit(
U->getSubExpr(), AddStmtChoice());
2513 appendStmt(ConfluenceBlock, B);
2518 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2519 ConfluenceBlock).first;
2522std::pair<CFGBlock*, CFGBlock*>
2535 if (B_RHS->isLogicalOp()) {
2536 std::tie(RHSBlock, ExitBlock) =
2537 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2545 ExitBlock = RHSBlock = createBlock(
false);
2550 TryResult KnownVal = tryEvaluateBool(RHS);
2551 if (!KnownVal.isKnown())
2552 KnownVal = tryEvaluateBool(B);
2555 assert(TrueBlock == FalseBlock);
2556 addSuccessor(RHSBlock, TrueBlock);
2560 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2561 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2565 RHSBlock = addStmt(RHS);
2570 return std::make_pair(
nullptr,
nullptr);
2576 if (B_LHS->isLogicalOp()) {
2578 FalseBlock = RHSBlock;
2580 TrueBlock = RHSBlock;
2585 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2590 CFGBlock *LHSBlock = createBlock(
false);
2594 CFGBlock *EntryLHSBlock = addStmt(LHS);
2597 return std::make_pair(
nullptr,
nullptr);
2600 TryResult KnownVal = tryEvaluateBool(LHS);
2604 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2605 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2608 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2609 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2612 return std::make_pair(EntryLHSBlock, ExitBlock);
2616 AddStmtChoice asc) {
2619 return VisitLogicalOperator(B);
2623 appendStmt(
Block, B);
2625 return addStmt(B->
getLHS());
2629 if (asc.alwaysAdd(*
this, B)) {
2631 appendStmt(
Block, B);
2634 return Visit(B->
getRHS());
2637 if (asc.alwaysAdd(*
this, B)) {
2639 appendStmt(
Block, B);
2650 return (LBlock ? LBlock : RBlock);
2653CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2654 if (asc.alwaysAdd(*
this, E)) {
2656 appendStmt(
Block, E);
2668 Block = createBlock(
false);
2673 if (BreakJumpTarget.block) {
2674 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2675 addSuccessor(
Block, BreakJumpTarget.block);
2699 QualType calleeType =
C->getCallee()->getType();
2705 if (!boundType.
isNull()) calleeType = boundType;
2711 bool AddEHEdge =
false;
2721 bool OmitArguments =
false;
2728 if (!FD->isVariadic())
2729 findConstructionContextsForArguments(
C);
2731 if (FD->isNoReturn() ||
C->isBuiltinAssumeFalse(*Context))
2733 if (FD->
hasAttr<NoThrowAttr>())
2735 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2736 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2737 OmitArguments =
true;
2740 if (!
CanThrow(
C->getCallee(), *Context))
2743 if (OmitArguments) {
2744 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2745 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2748 return Visit(
C->getCallee());
2751 if (!NoReturn && !AddEHEdge) {
2755 return VisitChildren(
C);
2765 Block = createNoReturnBlock();
2767 Block = createBlock();
2773 if (TryTerminatedBlock)
2774 addSuccessor(
Block, TryTerminatedBlock);
2776 addSuccessor(
Block, &cfg->getExit());
2779 return VisitChildren(
C);
2783 AddStmtChoice asc) {
2785 appendStmt(ConfluenceBlock,
C);
2789 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2790 Succ = ConfluenceBlock;
2792 CFGBlock *LHSBlock = Visit(
C->getLHS(), alwaysAdd);
2796 Succ = ConfluenceBlock;
2798 CFGBlock *RHSBlock = Visit(
C->getRHS(), alwaysAdd);
2802 Block = createBlock(
false);
2804 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2805 addSuccessor(
Block, KnownVal.isFalse() ?
nullptr : LHSBlock);
2806 addSuccessor(
Block, KnownVal.isTrue() ?
nullptr : RHSBlock);
2808 return addStmt(
C->getCond());
2812 bool ExternallyDestructed) {
2813 LocalScope::const_iterator scopeBeginPos = ScopePos;
2814 addLocalScopeForStmt(
C);
2816 if (!
C->body_empty() && !isa<ReturnStmt>(*
C->body_rbegin())) {
2819 addAutomaticObjHandling(ScopePos, scopeBeginPos,
C);
2824 for (
Stmt *S : llvm::reverse(
C->body())) {
2827 CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2828 ExternallyDestructed);
2831 LastBlock = newBlock;
2836 ExternallyDestructed =
false;
2843 AddStmtChoice asc) {
2850 appendStmt(ConfluenceBlock,
C);
2854 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2860 Succ = ConfluenceBlock;
2863 const Expr *trueExpr =
C->getTrueExpr();
2864 if (trueExpr != opaqueValue) {
2865 LHSBlock = Visit(
C->getTrueExpr(), alwaysAdd);
2871 LHSBlock = ConfluenceBlock;
2874 Succ = ConfluenceBlock;
2875 CFGBlock *RHSBlock = Visit(
C->getFalseExpr(), alwaysAdd);
2881 dyn_cast<BinaryOperator>(
C->getCond()->IgnoreParens()))
2882 if (Cond->isLogicalOp())
2883 return VisitLogicalOperator(Cond,
C, LHSBlock, RHSBlock).first;
2886 Block = createBlock(
false);
2889 const TryResult& KnownVal = tryEvaluateBool(
C->getCond());
2890 addSuccessor(
Block, LHSBlock, !KnownVal.isFalse());
2891 addSuccessor(
Block, RHSBlock, !KnownVal.isTrue());
2893 Expr *condExpr =
C->getCond();
2898 if (condExpr != opaqueValue)
2906 return addStmt(condExpr);
2917 return VisitDeclSubExpr(DS);
2931 cfg->addSyntheticDeclStmt(DSNew, DS);
2934 B = VisitDeclSubExpr(DSNew);
2943 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2945 if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl())) {
2947 const Type *T = TND->getUnderlyingType().getTypePtr();
2952 appendStmt(
Block, DS);
2956 VA =
FindVA(VA->getElementType().getTypePtr())) {
2957 if (
CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
2958 LastBlock = NewBlock;
2971 bool HasTemporaries =
false;
2974 CFGBlock *blockAfterStaticInit =
nullptr;
2985 blockAfterStaticInit = Succ;
2992 HasTemporaries = isa<ExprWithCleanups>(Init);
2996 TempDtorContext Context;
2997 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
3004 if (
const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
3005 for (
auto *BD : llvm::reverse(DD->bindings())) {
3006 if (
auto *VD = BD->getHoldingVar()) {
3010 cfg->addSyntheticDeclStmt(DSNew, DS);
3011 Block = VisitDeclSubExpr(DSNew);
3017 appendStmt(
Block, DS);
3021 const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init);
3023 findConstructionContexts(
3025 AILE ? AILE->getSubExpr() : Init);
3033 if (HasTemporaries) {
3038 LastBlock = newBlock;
3041 if (
CFGBlock *newBlock = Visit(Init))
3042 LastBlock = newBlock;
3050 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
3051 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3052 LastBlock = newBlock;
3055 maybeAddScopeBeginForVarDecl(
Block, VD, DS);
3058 if (ScopePos && VD == *ScopePos)
3062 if (blockAfterStaticInit) {
3064 Block = createBlock(
false);
3066 addSuccessor(
Block, blockAfterStaticInit);
3067 addSuccessor(
Block, B);
3088 addLocalScopeForStmt(Init);
3093 addLocalScopeForVarDecl(VD);
3095 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3117 if (!isa<CompoundStmt>(Else))
3118 addLocalScopeAndDtors(Else);
3120 ElseBlock = addStmt(Else);
3123 ElseBlock = sv.get();
3140 if (!isa<CompoundStmt>(Then))
3141 addLocalScopeAndDtors(Then);
3143 ThenBlock = addStmt(Then);
3149 ThenBlock = createBlock(
false);
3150 addSuccessor(ThenBlock, sv.get());
3170 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
3173 Block = createBlock(
false);
3181 KnownVal = tryEvaluateBool(I->
getCond());
3185 addSuccessor(
Block, ThenBlock, !KnownVal.isFalse());
3186 addSuccessor(
Block, ElseBlock, !KnownVal.isTrue());
3191 LastBlock = addStmt(I->
getCond());
3197 LastBlock = addStmt(
const_cast<DeclStmt *
>(DS));
3204 LastBlock = addStmt(Init);
3217 assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
3220 Block = createBlock(
false);
3222 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3224 if (
auto *R = dyn_cast<ReturnStmt>(S))
3225 findConstructionContexts(
3232 addSuccessor(
Block, &cfg->getExit());
3235 appendStmt(
Block, S);
3238 if (
ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3239 if (
Expr *O = RS->getRetValue())
3240 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3250 if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV))
3259 AddStmtChoice asc) {
3263 if (asc.alwaysAdd(*
this, E)) {
3265 appendStmt(
Block, E);
3289 if (!SEHExceptBlock)
3290 SEHExceptBlock = createBlock();
3292 appendStmt(SEHExceptBlock, ES);
3304 return SEHExceptBlock;
3308 return VisitCompoundStmt(FS->getBlock(),
false);
3318 Block = createBlock(
false);
3323 if (SEHLeaveJumpTarget.block) {
3324 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3325 addSuccessor(
Block, SEHLeaveJumpTarget.block);
3335 CFGBlock *SEHTrySuccessor =
nullptr;
3340 SEHTrySuccessor =
Block;
3341 }
else SEHTrySuccessor = Succ;
3347 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3350 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3357 Succ = SEHTrySuccessor;
3359 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3364 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3366 if (PrevSEHTryTerminatedBlock)
3367 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3369 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3372 Succ = SEHTrySuccessor;
3375 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3376 cfg->addTryDispatchBlock(TryTerminatedBlock);
3382 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3384 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3395 LabelBlock = createBlock();
3397 assert(!LabelMap.contains(L->
getDecl()) &&
"label already in map");
3398 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3418 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3420 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3430 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3435 it != et; ++it, ++Idx) {
3436 if (
Expr *Init = *it) {
3440 dyn_cast<ArrayInitLoopExpr>(Init));
3443 cfg->getBumpVectorContext(), {E, Idx}),
3444 AILEInit ? AILEInit : Init);
3458 Block = createBlock(
false);
3462 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3464 if (I == LabelMap.end())
3466 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3468 JumpTarget JT = I->second;
3469 addSuccessor(
Block, JT.block);
3470 addScopeChangesHandling(ScopePos, JT.scopePosition, G);
3481 return VisitStmt(G, asc);
3488 Block = createBlock();
3491 BackpatchBlocks.push_back(JumpSource(
Block, ScopePos));
3494 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3495 return VisitChildren(G);
3509 addLocalScopeForStmt(Init);
3510 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3513 addLocalScopeForVarDecl(VD);
3514 LocalScope::const_iterator ContinueScopePos = ScopePos;
3516 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3525 LoopSuccessor =
Block;
3527 LoopSuccessor = Succ;
3532 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3534 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3547 Block = Succ = TransitionBlock = createBlock(
false);
3548 TransitionBlock->setLoopTarget(F);
3553 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3563 assert(
Block == Succ);
3571 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3572 ContinueJumpTarget.block->setLoopTarget(F);
3577 if (!isa<CompoundStmt>(F->
getBody()))
3578 addLocalScopeAndDtors(F->
getBody());
3582 BodyBlock = addStmt(F->
getBody());
3587 BodyBlock = ContinueJumpTarget.block;
3596 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3605 dyn_cast_or_null<BinaryOperator>(
C ?
C->IgnoreParens() :
nullptr))
3607 std::tie(EntryConditionBlock, ExitConditionBlock) =
3608 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3613 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3614 ExitConditionBlock->setTerminator(F);
3617 TryResult KnownVal(
true);
3623 Block = ExitConditionBlock;
3624 EntryConditionBlock = addStmt(
C);
3633 findConstructionContexts(
3636 appendStmt(
Block, DS);
3637 EntryConditionBlock = addStmt(Init);
3638 assert(
Block == EntryConditionBlock);
3639 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3643 if (
Block && badCFG)
3646 KnownVal = tryEvaluateBool(
C);
3650 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3653 addSuccessor(ExitConditionBlock,
3654 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3658 addSuccessor(TransitionBlock, EntryConditionBlock);
3661 Succ = EntryConditionBlock;
3667 ScopePos = LoopBeginScopePos;
3668 Block = createBlock();
3675 Succ = EntryConditionBlock;
3676 return EntryConditionBlock;
3681 AddStmtChoice asc) {
3682 findConstructionContexts(
3686 return VisitStmt(MTE, asc);
3690 if (asc.alwaysAdd(*
this, M)) {
3692 appendStmt(
Block, M);
3734 LoopSuccessor =
Block;
3737 LoopSuccessor = Succ;
3740 CFGBlock *ExitConditionBlock = createBlock(
false);
3748 appendStmt(ExitConditionBlock, S);
3749 Block = ExitConditionBlock;
3754 CFGBlock *EntryConditionBlock = Visit(S->getElement(),
3755 AddStmtChoice::NotAlwaysAdd);
3764 Succ = EntryConditionBlock;
3771 save_break(BreakJumpTarget);
3777 Succ = LoopBackBlock = createBlock();
3780 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3781 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3783 CFGBlock *BodyBlock = addStmt(S->getBody());
3786 BodyBlock = ContinueJumpTarget.block;
3793 addSuccessor(ExitConditionBlock, BodyBlock);
3798 addSuccessor(ExitConditionBlock, LoopSuccessor);
3801 Block = createBlock();
3802 return addStmt(S->getCollection());
3807 return addStmt(S->getSubStmt());
3815 CFGBlock *SyncBlock = addStmt(S->getSynchBody());
3829 appendStmt(
Block, S);
3832 return addStmt(S->getSynchExpr());
3839 appendStmt(
Block, E);
3851 Semantic = OVE->getSourceExpr();
3869 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3871 addLocalScopeForVarDecl(VD);
3872 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3881 LoopSuccessor =
Block;
3884 LoopSuccessor = Succ;
3887 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3896 save_break(BreakJumpTarget);
3900 Succ = TransitionBlock = createBlock(
false);
3901 TransitionBlock->setLoopTarget(W);
3902 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3905 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3908 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3912 if (!isa<CompoundStmt>(W->
getBody()))
3913 addLocalScopeAndDtors(W->
getBody());
3916 BodyBlock = addStmt(W->
getBody());
3919 BodyBlock = ContinueJumpTarget.block;
3920 else if (
Block && badCFG)
3927 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3934 if (
BinaryOperator *Cond = dyn_cast<BinaryOperator>(
C->IgnoreParens()))
3936 std::tie(EntryConditionBlock, ExitConditionBlock) =
3937 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3942 ExitConditionBlock = createBlock(
false);
3948 Block = ExitConditionBlock;
3949 Block = EntryConditionBlock = addStmt(
C);
3958 findConstructionContexts(
3962 appendStmt(
Block, DS);
3963 EntryConditionBlock = addStmt(Init);
3964 assert(
Block == EntryConditionBlock);
3965 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,
C);
3969 if (
Block && badCFG)
3973 const TryResult& KnownVal = tryEvaluateBool(
C);
3976 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?
nullptr : BodyBlock);
3979 addSuccessor(ExitConditionBlock,
3980 KnownVal.isTrue() ?
nullptr : LoopSuccessor);
3984 addSuccessor(TransitionBlock, EntryConditionBlock);
3991 Succ = EntryConditionBlock;
3992 return EntryConditionBlock;
3996 AddStmtChoice asc) {
3997 if (asc.alwaysAdd(*
this, A)) {
3999 appendStmt(
Block, A);
4008 assert(OVE &&
"ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
4009 "OpaqueValueExpr!");
4010 if (
CFGBlock *R = Visit(OVE->getSourceExpr()))
4029 CatchBlock = createBlock();
4031 appendStmt(CatchBlock, CS);
4052 Block = createBlock(
false);
4054 if (TryTerminatedBlock)
4056 addSuccessor(
Block, TryTerminatedBlock);
4059 addSuccessor(
Block, &cfg->getExit());
4063 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4074 TrySuccessor =
Block;
4076 TrySuccessor = Succ;
4082 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4085 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4089 bool HasCatchAll =
false;
4092 Succ = TrySuccessor;
4097 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4102 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4107 if (PrevTryTerminatedBlock)
4108 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4110 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4114 Succ = TrySuccessor;
4117 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4118 cfg->addTryDispatchBlock(TryTerminatedBlock);
4120 assert(Terminator->
getTryBody() &&
"try must contain a non-NULL body");
4126 AddStmtChoice asc) {
4127 findConstructionContextsForArguments(ME);
4130 appendObjCMessage(
Block, ME);
4132 return VisitChildren(ME);
4141 Block = createBlock(
false);
4143 if (TryTerminatedBlock)
4145 addSuccessor(
Block, TryTerminatedBlock);
4148 addSuccessor(
Block, &cfg->getExit());
4152 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4156 if (asc.alwaysAdd(*
this, S)) {
4158 appendStmt(
Block, S);
4167 if (!S->isTypeDependent() && S->isPotentiallyEvaluated())
4168 return VisitChildren(S);
4184 LoopSuccessor =
Block;
4186 LoopSuccessor = Succ;
4191 CFGBlock *ExitConditionBlock = createBlock(
false);
4192 CFGBlock *EntryConditionBlock = ExitConditionBlock;
4200 Block = ExitConditionBlock;
4201 EntryConditionBlock = addStmt(
C);
4209 Succ = EntryConditionBlock;
4212 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
4222 save_break(BreakJumpTarget);
4225 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4228 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4235 if (!isa<CompoundStmt>(D->
getBody()))
4236 addLocalScopeAndDtors(D->
getBody());
4239 BodyBlock = addStmt(D->
getBody());
4242 BodyBlock = EntryConditionBlock;
4255 CFGBlock *LoopBackBlock = createBlock();
4258 if (!KnownVal.isFalse())
4260 addSuccessor(ExitConditionBlock, LoopBackBlock);
4262 addSuccessor(ExitConditionBlock,
nullptr);
4267 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4285 Block = createBlock(
false);
4290 if (ContinueJumpTarget.block) {
4291 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,
C);
4292 addSuccessor(
Block, ContinueJumpTarget.block);
4300 AddStmtChoice asc) {
4301 if (asc.alwaysAdd(*
this, E)) {
4303 appendStmt(
Block, E);
4309 if (E->
getKind() != UETT_SizeOf)
4316 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4317 lastBlock = addStmt(VA->getSizeExpr());
4325 if (asc.alwaysAdd(*
this, SE)) {
4327 appendStmt(
Block, SE);
4329 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4335 CFGBlock *SwitchSuccessor =
nullptr;
4343 addLocalScopeForStmt(Init);
4348 addLocalScopeForVarDecl(VD);
4350 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4355 SwitchSuccessor =
Block;
4356 }
else SwitchSuccessor = Succ;
4360 save_default(DefaultCaseBlock);
4366 DefaultCaseBlock = SwitchSuccessor;
4369 SwitchTerminatedBlock = createBlock(
false);
4373 Succ = SwitchSuccessor;
4374 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4379 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4384 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered,
false);
4387 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4389 bool b = tryEvaluate(Terminator->
getCond(), result);
4394 if (!isa<CompoundStmt>(Terminator->
getBody()))
4395 addLocalScopeAndDtors(Terminator->
getBody());
4397 addStmt(Terminator->
getBody());
4409 bool SwitchAlwaysHasSuccessor =
false;
4410 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4413 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4414 !SwitchAlwaysHasSuccessor);
4418 Block = SwitchTerminatedBlock;
4427 LastBlock = addStmt(Init);
4428 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
4435 LastBlock = addStmt(Init);
4448 bool addCase =
false;
4450 if (!switchExclusivelyCovered) {
4454 const llvm::APSInt &condInt = switchCond->
Val.
getInt();
4456 if (condInt == lhsInt) {
4458 switchExclusivelyCovered =
true;
4460 else if (condInt > lhsInt) {
4464 if (V2 >= condInt) {
4466 switchExclusivelyCovered =
true;
4480 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4486 while (isa<CaseStmt>(Sub)) {
4487 CFGBlock *currentBlock = createBlock(
false);
4491 addSuccessor(LastBlock, currentBlock);
4493 TopBlock = currentBlock;
4495 addSuccessor(SwitchTerminatedBlock,
4498 ? currentBlock :
nullptr);
4500 LastBlock = currentBlock;
4501 CS = cast<CaseStmt>(Sub);
4510 CaseBlock = createBlock();
4521 assert(SwitchTerminatedBlock);
4522 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4530 addSuccessor(LastBlock, CaseBlock);
4544 DefaultCaseBlock =
Block;
4546 if (!DefaultCaseBlock)
4547 DefaultCaseBlock = createBlock();
4551 DefaultCaseBlock->
setLabel(Terminator);
4566 Succ = DefaultCaseBlock;
4568 return DefaultCaseBlock;
4579 TrySuccessor =
Block;
4581 TrySuccessor = Succ;
4583 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4586 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4590 bool HasCatchAll =
false;
4591 for (
unsigned I = 0, E = Terminator->
getNumHandlers(); I != E; ++I) {
4593 Succ = TrySuccessor;
4599 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4604 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4607 if (PrevTryTerminatedBlock)
4608 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4610 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4614 Succ = TrySuccessor;
4617 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4618 cfg->addTryDispatchBlock(TryTerminatedBlock);
4620 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4636 LocalScope::const_iterator BeginScopePos = ScopePos;
4637 addLocalScopeForVarDecl(VD);
4638 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4646 CatchBlock = createBlock();
4652 appendStmt(CatchBlock, CS);
4686 if (
Stmt *Range = S->getRangeStmt())
4687 addLocalScopeForStmt(Range);
4689 addLocalScopeForStmt(
Begin);
4690 if (
Stmt *End = S->getEndStmt())
4691 addLocalScopeForStmt(End);
4692 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4694 LocalScope::const_iterator ContinueScopePos = ScopePos;
4702 LoopSuccessor =
Block;
4704 LoopSuccessor = Succ;
4709 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4712 CFGBlock *ConditionBlock = createBlock(
false);
4716 if (
Expr *
C = S->getCond()) {
4717 Block = ConditionBlock;
4718 CFGBlock *BeginConditionBlock = addStmt(
C);
4721 assert(BeginConditionBlock == ConditionBlock &&
4722 "condition block in for-range was unexpectedly complex");
4723 (void)BeginConditionBlock;
4728 Succ = ConditionBlock;
4731 TryResult KnownVal(
true);
4734 KnownVal = tryEvaluateBool(S->getCond());
4738 assert(S->getBody());
4747 Succ = addStmt(S->getInc());
4750 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4754 ContinueJumpTarget.block->setLoopTarget(S);
4763 addLocalScopeAndDtors(S->getLoopVarStmt());
4767 if (!isa<CompoundStmt>(S->getBody()))
4768 addLocalScopeAndDtors(S->getBody());
4771 addStmt(S->getBody());
4775 CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
4780 addSuccessor(ConditionBlock,
4781 KnownVal.isFalse() ?
nullptr : LoopVarStmtBlock);
4786 addSuccessor(ConditionBlock, KnownVal.isTrue() ?
nullptr : LoopSuccessor);
4789 Block = createBlock();
4790 addStmt(S->getBeginStmt());
4791 addStmt(S->getEndStmt());
4792 CFGBlock *Head = addStmt(S->getRangeStmt());
4794 Head = addStmt(S->getInit());
4799 AddStmtChoice asc,
bool ExternallyDestructed) {
4803 TempDtorContext Context;
4804 VisitForTemporaryDtors(E->
getSubExpr(), ExternallyDestructed, Context);
4808 asc = asc.withAlwaysAdd(
true);
4814 AddStmtChoice asc) {
4815 if (asc.alwaysAdd(*
this, E)) {
4817 appendStmt(
Block, E);
4819 findConstructionContexts(
4824 asc = asc.withAlwaysAdd(
false);
4830 AddStmtChoice asc) {
4834 findConstructionContextsForArguments(
C);
4837 appendConstructor(
Block,
C);
4839 return VisitChildren(
C);
4843 AddStmtChoice asc) {
4845 appendStmt(
Block, NE);
4847 findConstructionContexts(
4851 if (
NE->getInitializer())
4852 Block = Visit(
NE->getInitializer());
4855 appendNewAllocator(
Block, NE);
4857 if (
NE->isArray() && *
NE->getArraySize())
4858 Block = Visit(*
NE->getArraySize());
4861 E =
NE->placement_arg_end(); I != E; ++I)
4868 AddStmtChoice asc) {
4870 appendStmt(
Block, DE);
4877 appendDeleteDtor(
Block, RD, DE);
4881 return VisitChildren(DE);
4885 AddStmtChoice asc) {
4886 if (asc.alwaysAdd(*
this, E)) {
4888 appendStmt(
Block, E);
4890 asc = asc.withAlwaysAdd(
false);
4896 AddStmtChoice asc) {
4900 findConstructionContextsForArguments(
C);
4903 appendConstructor(
Block,
C);
4904 return VisitChildren(
C);
4908 AddStmtChoice asc) {
4909 if (asc.alwaysAdd(*
this, E)) {
4911 appendStmt(
Block, E);
4917 return Visit(E->
getSubExpr(), AddStmtChoice());
4921 return Visit(E->
getSubExpr(), AddStmtChoice());
4926 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4929 IBlock = createBlock(
false);
4930 cfg->setIndirectGotoBlock(IBlock);
4938 Block = createBlock(
false);
4940 addSuccessor(
Block, IBlock);
4944CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
4945 TempDtorContext &Context) {
4955 return VisitChildrenForTemporaryDtors(E,
false, Context);
4957 case Stmt::InitListExprClass:
4958 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
4960 case Stmt::BinaryOperatorClass:
4961 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4962 ExternallyDestructed,
4965 case Stmt::CXXBindTemporaryExprClass:
4966 return VisitCXXBindTemporaryExprForTemporaryDtors(
4967 cast<CXXBindTemporaryExpr>(E), ExternallyDestructed, Context);
4969 case Stmt::BinaryConditionalOperatorClass:
4970 case Stmt::ConditionalOperatorClass:
4971 return VisitConditionalOperatorForTemporaryDtors(
4972 cast<AbstractConditionalOperator>(E), ExternallyDestructed, Context);
4974 case Stmt::ImplicitCastExprClass:
4976 E = cast<CastExpr>(E)->getSubExpr();
4979 case Stmt::CXXFunctionalCastExprClass:
4981 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4984 case Stmt::ConstantExprClass:
4985 E = cast<ConstantExpr>(E)->getSubExpr();
4988 case Stmt::ParenExprClass:
4989 E = cast<ParenExpr>(E)->getSubExpr();
4992 case Stmt::MaterializeTemporaryExprClass: {
4998 E =
const_cast<Expr *
>(
4999 cast<MaterializeTemporaryExpr>(E)
5001 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
5003 for (
const Expr *CommaLHS : CommaLHSs) {
5004 VisitForTemporaryDtors(
const_cast<Expr *
>(CommaLHS),
5010 case Stmt::BlockExprClass:
5015 case Stmt::LambdaExprClass: {
5018 auto *
LE = cast<LambdaExpr>(E);
5020 for (
Expr *Init :
LE->capture_inits()) {
5022 if (
CFGBlock *R = VisitForTemporaryDtors(
5023 Init,
true, Context))
5030 case Stmt::StmtExprClass:
5035 case Stmt::CXXDefaultArgExprClass:
5036 E = cast<CXXDefaultArgExpr>(E)->getExpr();
5039 case Stmt::CXXDefaultInitExprClass:
5040 E = cast<CXXDefaultInitExpr>(E)->getExpr();
5045CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
5046 bool ExternallyDestructed,
5047 TempDtorContext &Context) {
5048 if (isa<LambdaExpr>(E)) {
5060 if (
CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
5066CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
5067 BinaryOperator *E,
bool ExternallyDestructed, TempDtorContext &Context) {
5071 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
5072 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(), ExternallyDestructed, Context);
5073 return RHSBlock ? RHSBlock : LHSBlock;
5077 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
5078 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
5079 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
5080 RHSExecuted.negate();
5085 TempDtorContext RHSContext(
5087 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
5088 InsertTempDtorDecisionBlock(RHSContext);
5096 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
5097 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
5098 return LHSBlock ? LHSBlock : RHSBlock;
5102 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
5105CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5110 if (!ExternallyDestructed) {
5122 Block = createNoReturnBlock();
5123 }
else if (Context.needsTempDtorBranch()) {
5127 Block = createBlock();
5131 if (Context.needsTempDtorBranch()) {
5132 Context.setDecisionPoint(Succ, E);
5134 appendTemporaryDtor(
Block, E);
5141void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
5143 if (!Context.TerminatorExpr) {
5147 assert(Context.TerminatorExpr);
5148 CFGBlock *Decision = createBlock(
false);
5151 addSuccessor(Decision,
Block, !Context.KnownExecuted.isFalse());
5152 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5153 !Context.KnownExecuted.isTrue());
5157CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
5159 TempDtorContext &Context) {
5160 VisitForTemporaryDtors(E->
getCond(),
false, Context);
5163 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
5164 TryResult NegatedVal = ConditionVal;
5165 if (NegatedVal.isKnown()) NegatedVal.negate();
5167 TempDtorContext TrueContext(
5169 VisitForTemporaryDtors(E->
getTrueExpr(), ExternallyDestructed, TrueContext);
5172 Block = ConditionBlock;
5173 Succ = ConditionSucc;
5174 TempDtorContext FalseContext(
5176 VisitForTemporaryDtors(E->
getFalseExpr(), ExternallyDestructed, FalseContext);
5178 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5179 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
5180 }
else if (TrueContext.TerminatorExpr) {
5182 InsertTempDtorDecisionBlock(TrueContext);
5184 InsertTempDtorDecisionBlock(FalseContext);
5190 AddStmtChoice asc) {
5191 if (asc.alwaysAdd(*
this, D)) {
5193 appendStmt(
Block, D);
5203 for (
Stmt *S : llvm::reverse(
Used)) {
5204 assert(S &&
"Expected non-null used-in-clause child.");
5211 if (!isa<CompoundStmt>(S))
5212 addLocalScopeAndDtors(S);
5224 bool first_block =
begin() ==
end();
5232 Entry = Exit = &
back();
5241 CFGBuilder Builder(
C, BO);
5242 return Builder.buildCFG(D, Statement);
5257 auto IteratorAndFlag =
Visited.insert(B);
5258 if (!IteratorAndFlag.second) {
5264 const CFGBlock *FirstReachableB =
nullptr;
5266 if (!AB.isReachable())
5269 if (FirstReachableB ==
nullptr) {
5270 FirstReachableB = &*AB;
5277 if (!FirstReachableB) {
5283 B = FirstReachableB;
5303 llvm_unreachable(
"getDestructorDecl should only be used with "
5306 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
5332 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
5341 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
5346 const FieldDecl *field = castAs<CFGMemberDtor>().getFieldDecl();
5361 llvm_unreachable(
"getKind() returned bogus value");
5369 : ReachableBlock(IsReachable ? B : nullptr),
5370 UnreachableBlock(!IsReachable ? B : nullptr,
5371 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5374 : ReachableBlock(B),
5375 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
5376 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5399 if (S->isAllEnumCasesCovered()) {
5401 if (!L || !isa<CaseStmt>(L))
5417 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5418 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5422 signed currentBlock = 0;
5423 unsigned currStmt = 0;
5434 BI != BEnd; ++BI, ++j ) {
5435 if (std::optional<CFGStmt> SE = BI->getAs<
CFGStmt>()) {
5437 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
5440 switch (
stmt->getStmtClass()) {
5441 case Stmt::DeclStmtClass:
5442 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
5444 case Stmt::IfStmtClass: {
5445 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
5450 case Stmt::ForStmtClass: {
5451 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
5456 case Stmt::WhileStmtClass: {
5458 cast<WhileStmt>(
stmt)->getConditionVariable();
5463 case Stmt::SwitchStmtClass: {
5465 cast<SwitchStmt>(
stmt)->getConditionVariable();
5470 case Stmt::CXXCatchStmtClass: {
5472 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
5485 ~StmtPrinterHelper()
override =
default;
5487 const LangOptions &getLangOpts()
const {
return LangOpts; }
5488 void setBlockID(
signed i) { currentBlock = i; }
5489 void setStmtID(
unsigned i) { currStmt = i; }
5491 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
5492 StmtMapTy::iterator I = StmtMap.find(S);
5494 if (I == StmtMap.end())
5497 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5498 && I->second.second == currStmt) {
5502 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5506 bool handleDecl(
const Decl *D, raw_ostream &OS) {
5507 DeclMapTy::iterator I = DeclMap.find(D);
5509 if (I == DeclMap.end())
5512 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5513 && I->second.second == currStmt) {
5517 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5522class CFGBlockTerminatorPrint
5523 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5525 StmtPrinterHelper* Helper;
5529 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5531 : OS(os), Helper(helper), Policy(Policy) {
5535 void VisitIfStmt(
IfStmt *I) {
5538 C->printPretty(OS, Helper, Policy);
5542 void VisitStmt(
Stmt *Terminator) {
5548 OS <<
"static init " << VD->
getName();
5551 void VisitForStmt(
ForStmt *F) {
5557 C->printPretty(OS, Helper, Policy);
5567 C->printPretty(OS, Helper, Policy);
5570 void VisitDoStmt(
DoStmt *D) {
5571 OS <<
"do ... while ";
5573 C->printPretty(OS, Helper, Policy);
5576 void VisitSwitchStmt(
SwitchStmt *Terminator) {
5581 void VisitCXXTryStmt(
CXXTryStmt *) { OS <<
"try ..."; }
5583 void VisitObjCAtTryStmt(
ObjCAtTryStmt *) { OS <<
"@try ..."; }
5585 void VisitSEHTryStmt(
SEHTryStmt *CS) { OS <<
"__try ..."; }
5588 if (
Stmt *Cond =
C->getCond())
5590 OS <<
" ? ... : ...";
5594 OS <<
"__builtin_choose_expr( ";
5595 if (
Stmt *Cond =
C->getCond())
5623 llvm_unreachable(
"Invalid logical operator.");
5627 void VisitExpr(
Expr *E) {
5638 OS <<
"(Temp Dtor) ";
5642 OS <<
"(See if most derived ctor has already initialized vbases)";
5660 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5664 OS <<
" (Base initializer)";
5666 OS <<
" (Delegating initializer)";
5668 OS <<
" (Member initializer)";
5672 StmtPrinterHelper &Helper,
5678 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5685 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5687 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5691 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5692 Stmts.push_back(SDSCC->getDeclStmt());
5696 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5697 Stmts.push_back(CDSCC->getDeclStmt());
5698 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5702 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5703 Stmts.push_back(NECC->getCXXNewExpr());
5707 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5708 Stmts.push_back(RSCC->getReturnStmt());
5713 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5714 Stmts.push_back(RSCC->getReturnStmt());
5715 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5719 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5720 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5721 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5725 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5726 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5727 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5728 Stmts.push_back(TOCC->getConstructorAfterElision());
5732 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
5733 Helper.handledStmt(
const_cast<LambdaExpr *
>(LCC->getLambdaExpr()), OS);
5734 OS <<
"+" << LCC->getIndex();
5738 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5739 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5741 Helper.handledStmt(
const_cast<Stmt *
>(BTE), OS);
5744 Helper.handledStmt(
const_cast<Expr *
>(ACC->getCallLikeExpr()), OS);
5745 OS <<
"+" << ACC->getIndex();
5752 Helper.handledStmt(
const_cast<Stmt *
>(I), OS);
5756static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5761 StmtPrinterHelper Helper(
nullptr, LangOpts);
5765static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5773 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5776 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5779 auto Children = Sub->children();
5780 if (Children.begin() != Children.end()) {
5791 Helper.handledStmt(B->
getRHS(),OS);
5796 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5799 if (isa<CXXOperatorCallExpr>(S))
5800 OS <<
" (OperatorCall)";
5801 OS <<
" (CXXRecordTypedCall";
5804 }
else if (isa<CXXOperatorCallExpr>(S)) {
5805 OS <<
" (OperatorCall)";
5806 }
else if (isa<CXXBindTemporaryExpr>(S)) {
5807 OS <<
" (BindTemporary)";
5809 OS <<
" (CXXConstructExpr";
5813 OS <<
", " << CCE->getType() <<
")";
5814 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5816 <<
", " << CE->
getType() <<
")";
5834 Helper.handleDecl(VD, OS);
5842 OS <<
"() (Implicit destructor)\n";
5847 OS <<
"CleanupFunction ("
5853 OS <<
" (Lifetime ends)\n";
5857 OS << E.
castAs<
CFGLoopExit>().getLoopStmt()->getStmtClassName() <<
" (LoopExit)\n";
5861 OS <<
"CFGScopeBegin(";
5868 OS <<
"CFGScopeEnd(";
5875 OS <<
"CFGNewAllocator(";
5877 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
5888 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
5889 OS <<
"->~" << RD->getName().str() <<
"()";
5890 OS <<
" (Implicit destructor)\n";
5897 OS <<
" (Base object destructor)\n";
5904 OS <<
"this->" << FD->
getName();
5906 OS <<
" (Member object destructor)\n";
5915 OS <<
"() (Temporary object destructor)\n";
5923 StmtPrinterHelper &Helper,
bool print_edges,
5925 Helper.setBlockID(B.