39 #include "llvm/ADT/APInt.h" 40 #include "llvm/ADT/APSInt.h" 41 #include "llvm/ADT/ArrayRef.h" 42 #include "llvm/ADT/DenseMap.h" 43 #include "llvm/ADT/Optional.h" 44 #include "llvm/ADT/STLExtras.h" 45 #include "llvm/ADT/SetVector.h" 46 #include "llvm/ADT/SmallPtrSet.h" 47 #include "llvm/ADT/SmallVector.h" 48 #include "llvm/Support/Allocator.h" 49 #include "llvm/Support/Casting.h" 50 #include "llvm/Support/Compiler.h" 51 #include "llvm/Support/DOTGraphTraits.h" 52 #include "llvm/Support/ErrorHandling.h" 53 #include "llvm/Support/Format.h" 54 #include "llvm/Support/GraphWriter.h" 55 #include "llvm/Support/SaveAndRestore.h" 56 #include "llvm/Support/raw_ostream.h" 64 using namespace clang;
67 if (
VarDecl *VD = dyn_cast<VarDecl>(D))
68 if (
Expr *Ex = VD->getInit())
69 return Ex->getSourceRange().getEnd();
80 if (
const auto *CE = dyn_cast<CastExpr>(E)) {
81 if (CE->getCastKind() != CK_IntegralCast)
87 if (
const auto *UO = dyn_cast<UnaryOperator>(E)) {
88 if (UO->getOpcode() != UO_Minus)
93 return isa<IntegerLiteral>(E);
104 return isa<EnumConstantDecl>(DR->getDecl()) ? DR :
nullptr;
113 static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
120 if (Constant ==
nullptr) {
124 else if (Op == BO_GE)
126 else if (Op == BO_LT)
128 else if (Op == BO_LE)
135 return std::make_tuple(MaybeDecl, Op, Constant);
147 if (isa<DeclRefExpr>(E1) != isa<DeclRefExpr>(E2))
151 if (!isa<DeclRefExpr>(E1))
156 assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
157 auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
158 auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
160 assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
164 assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
184 class AddStmtChoice {
186 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
188 AddStmtChoice(
Kind a_kind = NotAlwaysAdd) :
kind(a_kind) {}
190 bool alwaysAdd(CFGBuilder &builder,
195 AddStmtChoice withAlwaysAdd(
bool alwaysAdd)
const {
196 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
226 friend class const_iterator;
232 class const_iterator {
233 const LocalScope*
Scope =
nullptr;
237 unsigned VarIter = 0;
243 const_iterator() =
default;
247 const_iterator(
const LocalScope& S,
unsigned I)
248 : Scope(&S), VarIter(I) {
251 if (VarIter == 0 && Scope)
255 VarDecl *
const* operator->()
const {
256 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
257 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
258 return &Scope->Vars[VarIter - 1];
261 const VarDecl *getFirstVarInScope()
const {
262 assert(Scope &&
"Dereferencing invalid iterator is not allowed");
263 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
264 return Scope->Vars[0];
268 return *this->operator->();
271 const_iterator &operator++() {
275 assert(VarIter != 0 &&
"Iterator has invalid value of VarIter member");
281 const_iterator operator++(
int) {
282 const_iterator
P = *
this;
287 bool operator==(
const const_iterator &rhs)
const {
288 return Scope == rhs.Scope && VarIter == rhs.VarIter;
290 bool operator!=(
const const_iterator &rhs)
const {
291 return !(*
this == rhs);
294 explicit operator bool()
const {
295 return *
this != const_iterator();
299 const_iterator shared_parent(const_iterator L);
300 bool pointsToFirstDeclaredVar() {
return VarIter == 1; }
307 AutomaticVarsTy Vars;
316 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
319 const_iterator begin()
const {
return const_iterator(*
this, Vars.size()); }
322 Vars.push_back(VD, ctx);
333 const_iterator F = *
this;
334 while (F.Scope != L.Scope) {
335 assert(F != const_iterator() &&
336 "L iterator is not reachable from F iterator.");
340 D += F.VarIter - L.VarIter;
348 LocalScope::const_iterator
349 LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
350 llvm::SmallPtrSet<const LocalScope *, 4> ScopesOfL;
352 ScopesOfL.insert(L.Scope);
353 if (L == const_iterator())
358 const_iterator F = *
this;
360 if (ScopesOfL.count(F.Scope))
362 assert(F != const_iterator() &&
363 "L iterator is not reachable from F iterator.");
373 struct BlockScopePosPair {
375 LocalScope::const_iterator scopePosition;
377 BlockScopePosPair() =
default;
378 BlockScopePosPair(
CFGBlock *b, LocalScope::const_iterator scopePos)
379 : block(b), scopePosition(scopePos) {}
390 TryResult() =
default;
391 TryResult(
bool b) :
X(b ? 1 : 0) {}
393 bool isTrue()
const {
return X == 1; }
394 bool isFalse()
const {
return X == 0; }
395 bool isKnown()
const {
return X >= 0; }
406 if (!R1.isKnown() || !R2.isKnown())
408 return TryResult(R1.isTrue() && R2.isTrue());
413 class reverse_children {
418 reverse_children(
Stmt *S);
422 iterator begin()
const {
return children.rbegin(); }
423 iterator end()
const {
return children.rend(); }
428 reverse_children::reverse_children(
Stmt *S) {
429 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
435 case Stmt::InitListExprClass: {
447 childrenBuf.push_back(SubStmt);
469 using JumpTarget = BlockScopePosPair;
470 using JumpSource = BlockScopePosPair;
473 std::unique_ptr<CFG> cfg;
481 JumpTarget ContinueJumpTarget;
482 JumpTarget BreakJumpTarget;
483 JumpTarget SEHLeaveJumpTarget;
484 CFGBlock *SwitchTerminatedBlock =
nullptr;
485 CFGBlock *DefaultCaseBlock =
nullptr;
489 CFGBlock *TryTerminatedBlock =
nullptr;
492 LocalScope::const_iterator ScopePos;
495 using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
500 using BackpatchBlocksTy = std::vector<JumpSource>;
501 BackpatchBlocksTy BackpatchBlocks;
505 LabelSetTy AddressTakenLabels;
510 llvm::DenseMap<Expr *, const ConstructionContextLayer *>
511 ConstructionContextMap;
514 DeclsWithEndedScopeSetTy DeclsWithEndedScope;
520 bool switchExclusivelyCovered =
false;
523 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =
nullptr;
524 const Stmt *lastLookup =
nullptr;
528 using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
529 CachedBoolEvalsTy CachedBoolEvals;
534 : Context(astContext), cfg(
new CFG()),
535 ConstructionContextMap(), BuildOpts(buildOpts) {}
539 std::unique_ptr<CFG> buildCFG(
const Decl *D,
Stmt *Statement);
574 AddStmtChoice asc,
bool ExternallyDestructed);
586 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(
BinaryOperator *B,
613 CFGBlock *Visit(
Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
614 bool ExternallyDestructed =
false);
623 if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
624 appendScopeBegin(B, VD, S);
655 struct TempDtorContext {
656 TempDtorContext() =
default;
657 TempDtorContext(TryResult KnownExecuted)
658 : IsConditional(
true), KnownExecuted(KnownExecuted) {}
666 bool needsTempDtorBranch()
const {
667 return IsConditional && !TerminatorExpr;
677 const bool IsConditional =
false;
678 const TryResult KnownExecuted =
true;
685 CFGBlock *VisitForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
686 TempDtorContext &Context);
687 CFGBlock *VisitChildrenForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
688 TempDtorContext &Context);
690 bool ExternallyDestructed,
691 TempDtorContext &Context);
692 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
694 CFGBlock *VisitConditionalOperatorForTemporaryDtors(
696 TempDtorContext &Context);
697 void InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
722 template <
typename CallLikeExpr,
723 typename =
typename std::enable_if<
724 std::is_same<CallLikeExpr, CallExpr>::value ||
725 std::is_same<CallLikeExpr, CXXConstructExpr>::value ||
726 std::is_same<CallLikeExpr, ObjCMessageExpr>::value>>
727 void findConstructionContextsForArguments(CallLikeExpr *E) {
728 for (
unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
729 Expr *Arg = E->getArg(i);
731 findConstructionContexts(
741 void cleanupConstructionContext(
Expr *E);
743 void autoCreateBlock() {
if (!Block) Block = createBlock(); }
744 CFGBlock *createBlock(
bool add_successor =
true);
748 return Visit(S, AddStmtChoice::AlwaysAdd);
752 void addLoopExit(
const Stmt *LoopStmt);
753 void addAutomaticObjDtors(LocalScope::const_iterator B,
754 LocalScope::const_iterator E,
Stmt *S);
755 void addLifetimeEnds(LocalScope::const_iterator B,
756 LocalScope::const_iterator E,
Stmt *S);
757 void addAutomaticObjHandling(LocalScope::const_iterator B,
758 LocalScope::const_iterator E,
Stmt *S);
760 void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
763 void getDeclsWithEndedScope(LocalScope::const_iterator B,
764 LocalScope::const_iterator E,
Stmt *S);
767 LocalScope* createOrReuseLocalScope(LocalScope*
Scope);
769 void addLocalScopeForStmt(
Stmt *S);
770 LocalScope* addLocalScopeForDeclStmt(
DeclStmt *DS,
771 LocalScope* Scope =
nullptr);
772 LocalScope* addLocalScopeForVarDecl(
VarDecl *VD, LocalScope* Scope =
nullptr);
774 void addLocalScopeAndDtors(
Stmt *S);
784 cleanupConstructionContext(E);
792 if (alwaysAdd(S) && cachedEntry)
793 cachedEntry->second = B;
796 assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
797 B->
appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
802 retrieveAndCleanupConstructionContext(CE)) {
808 B->
appendStmt(CE, cfg->getBumpVectorContext());
812 if (alwaysAdd(CE) && cachedEntry)
813 cachedEntry->second = B;
816 retrieveAndCleanupConstructionContext(CE)) {
822 B->
appendStmt(CE, cfg->getBumpVectorContext());
842 if (alwaysAdd(ME) && cachedEntry)
843 cachedEntry->second = B;
846 retrieveAndCleanupConstructionContext(ME)) {
851 B->
appendStmt(const_cast<ObjCMessageExpr *>(ME),
852 cfg->getBumpVectorContext());
867 void appendLoopExit(
CFGBlock *B,
const Stmt *LoopStmt) {
875 void prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
876 LocalScope::const_iterator B, LocalScope::const_iterator E);
878 void prependAutomaticObjLifetimeWithTerminator(
CFGBlock *Blk,
879 LocalScope::const_iterator B,
880 LocalScope::const_iterator E);
883 prependAutomaticObjScopeEndWithTerminator(
CFGBlock *Blk,
884 LocalScope::const_iterator B,
885 LocalScope::const_iterator E);
889 cfg->getBumpVectorContext());
896 cfg->getBumpVectorContext());
922 TryResult checkIncorrectRelationalOperator(
const BinaryOperator *B) {
927 const Expr *BoolExpr = RHSExpr;
928 bool IntFirst =
true;
939 if ((IntValue == 1) || (IntValue == 0))
943 !IntValue.isNegative();
946 if (Bok == BO_GT || Bok == BO_GE) {
949 return TryResult(IntFirst == IntLarger);
953 return TryResult(IntFirst != IntLarger);
961 TryResult checkIncorrectEqualityOperator(
const BinaryOperator *B) {
966 const Expr *BoolExpr = RHSExpr;
977 if (BitOp && (BitOp->
getOpcode() == BO_And ||
992 if ((BitOp->
getOpcode() == BO_And && (L2 & L1) != L1) ||
993 (BitOp->
getOpcode() == BO_Or && (L2 | L1) != L1)) {
999 }
else if (BoolExpr->isKnownToHaveBooleanValue()) {
1001 if ((IntValue == 1) || (IntValue == 0)) {
1004 return TryResult(B->
getOpcode() != BO_EQ);
1013 assert(Value1.isSigned() == Value2.isSigned());
1018 return TryResult(Value1 == Value2);
1020 return TryResult(Value1 != Value2);
1022 return TryResult(Value1 < Value2);
1024 return TryResult(Value1 <= Value2);
1026 return TryResult(Value1 > Value2);
1028 return TryResult(Value1 >= Value2);
1045 if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1048 const Expr *DeclExpr1;
1049 const Expr *NumExpr1;
1053 if (!DeclExpr1 || !NumExpr1)
1056 const Expr *DeclExpr2;
1057 const Expr *NumExpr2;
1061 if (!DeclExpr2 || !NumExpr2)
1082 if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1089 llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1098 llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1107 bool AlwaysTrue =
true, AlwaysFalse =
true;
1110 bool LHSAlwaysTrue =
true, LHSAlwaysFalse =
true;
1111 bool RHSAlwaysTrue =
true, RHSAlwaysFalse =
true;
1113 TryResult Res1, Res2;
1114 Res1 = analyzeLogicOperatorCondition(BO1,
Value, L1);
1115 Res2 = analyzeLogicOperatorCondition(BO2,
Value, L2);
1117 if (!Res1.isKnown() || !Res2.isKnown())
1121 AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1122 AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1124 AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1125 AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1128 LHSAlwaysTrue &= Res1.isTrue();
1129 LHSAlwaysFalse &= Res1.isFalse();
1130 RHSAlwaysTrue &= Res2.isTrue();
1131 RHSAlwaysFalse &= Res2.isFalse();
1134 if (AlwaysTrue || AlwaysFalse) {
1135 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1136 !RHSAlwaysFalse && BuildOpts.
Observer)
1138 return TryResult(AlwaysTrue);
1144 TryResult checkIncorrectBitwiseOrOperator(
const BinaryOperator *B) {
1145 const Expr *LHSConstant =
1147 const Expr *RHSConstant =
1150 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1153 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1165 return TryResult(
true);
1179 TryResult tryEvaluateBool(
Expr *S) {
1185 if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1187 CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1188 if (I != CachedBoolEvals.end())
1192 TryResult
Result = evaluateAsBooleanConditionNoCache(S);
1193 CachedBoolEvals[S] =
Result;
1197 switch (Bop->getOpcode()) {
1206 if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1208 if (!IntVal.getBoolValue()) {
1209 return TryResult(
false);
1213 if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1215 if (!IntVal.getBoolValue()) {
1216 return TryResult(
false);
1225 return evaluateAsBooleanConditionNoCache(S);
1229 TryResult evaluateAsBooleanConditionNoCache(
Expr *E) {
1231 if (Bop->isLogicalOp()) {
1232 TryResult LHS = tryEvaluateBool(Bop->getLHS());
1233 if (LHS.isKnown()) {
1236 if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1237 return LHS.isTrue();
1239 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1240 if (RHS.isKnown()) {
1241 if (Bop->getOpcode() == BO_LOr)
1242 return LHS.isTrue() || RHS.isTrue();
1244 return LHS.isTrue() && RHS.isTrue();
1247 TryResult RHS = tryEvaluateBool(Bop->getRHS());
1248 if (RHS.isKnown()) {
1251 if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1252 return RHS.isTrue();
1254 TryResult BopRes = checkIncorrectLogicOperator(Bop);
1255 if (BopRes.isKnown())
1256 return BopRes.isTrue();
1261 }
else if (Bop->isEqualityOp()) {
1262 TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1263 if (BopRes.isKnown())
1264 return BopRes.isTrue();
1265 }
else if (Bop->isRelationalOp()) {
1266 TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1267 if (BopRes.isKnown())
1268 return BopRes.isTrue();
1269 }
else if (Bop->getOpcode() == BO_Or) {
1270 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1271 if (BopRes.isKnown())
1272 return BopRes.isTrue();
1283 bool hasTrivialDestructor(
VarDecl *VD);
1288 inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1290 return builder.alwaysAdd(stmt) ||
kind == AlwaysAdd;
1293 bool CFGBuilder::alwaysAdd(
const Stmt *stmt) {
1294 bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1296 if (!BuildOpts.forcedBlkExprs)
1299 if (lastLookup == stmt) {
1301 assert(cachedEntry->first == stmt);
1314 assert(!cachedEntry);
1318 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1319 if (itr == fb->end()) {
1320 cachedEntry =
nullptr;
1324 cachedEntry = &*itr;
1331 while (
const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1333 if (vat->getSizeExpr())
1336 t = vt->getElementType().getTypePtr();
1342 void CFGBuilder::consumeConstructionContext(
1344 assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1345 isa<ObjCMessageExpr>(E)) &&
"Expression cannot construct an object!");
1347 ConstructionContextMap.lookup(E)) {
1348 (void)PreviouslyStoredLayer;
1351 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1352 "Already within a different construction context!");
1354 ConstructionContextMap[E] = Layer;
1358 void CFGBuilder::findConstructionContexts(
1360 if (!BuildOpts.AddRichCXXConstructors)
1372 case Stmt::CXXConstructExprClass:
1373 case Stmt::CXXTemporaryObjectExprClass: {
1375 auto *CE = cast<CXXConstructExpr>(Child);
1376 if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
1377 findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
1380 consumeConstructionContext(Layer, CE);
1386 case Stmt::CallExprClass:
1387 case Stmt::CXXMemberCallExprClass:
1388 case Stmt::CXXOperatorCallExprClass:
1389 case Stmt::UserDefinedLiteralClass:
1390 case Stmt::ObjCMessageExprClass: {
1391 auto *E = cast<Expr>(Child);
1393 consumeConstructionContext(Layer, E);
1396 case Stmt::ExprWithCleanupsClass: {
1397 auto *Cleanups = cast<ExprWithCleanups>(Child);
1398 findConstructionContexts(Layer, Cleanups->getSubExpr());
1401 case Stmt::CXXFunctionalCastExprClass: {
1402 auto *
Cast = cast<CXXFunctionalCastExpr>(Child);
1403 findConstructionContexts(Layer,
Cast->getSubExpr());
1406 case Stmt::ImplicitCastExprClass: {
1407 auto *
Cast = cast<ImplicitCastExpr>(Child);
1409 switch (
Cast->getCastKind()) {
1411 case CK_ConstructorConversion:
1412 findConstructionContexts(Layer,
Cast->getSubExpr());
1419 case Stmt::CXXBindTemporaryExprClass: {
1420 auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1421 findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1424 case Stmt::MaterializeTemporaryExprClass: {
1431 auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1432 findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1436 case Stmt::ConditionalOperatorClass: {
1437 auto *CO = cast<ConditionalOperator>(Child);
1444 assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1448 findConstructionContexts(Layer, CO->getLHS());
1449 findConstructionContexts(Layer, CO->getRHS());
1452 case Stmt::InitListExprClass: {
1453 auto *ILE = cast<InitListExpr>(Child);
1454 if (ILE->isTransparent()) {
1455 findConstructionContexts(Layer, ILE->getInit(0));
1466 void CFGBuilder::cleanupConstructionContext(
Expr *E) {
1467 assert(BuildOpts.AddRichCXXConstructors &&
1468 "We should not be managing construction contexts!");
1469 assert(ConstructionContextMap.count(E) &&
1470 "Cannot exit construction context without the context!");
1471 ConstructionContextMap.erase(E);
1480 std::unique_ptr<CFG> CFGBuilder::buildCFG(
const Decl *D,
Stmt *Statement) {
1488 Succ = createBlock();
1489 assert(Succ == &cfg->getExit());
1492 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1493 "AddImplicitDtors and AddLifetime cannot be used at the same time");
1495 if (BuildOpts.AddImplicitDtors)
1497 addImplicitDtorsForDestructor(DD);
1517 if (
const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1519 for (
auto *I : llvm::reverse(CD->inits())) {
1520 if (BuildOpts.AddVirtualBaseBranches && !VBaseSucc &&
1521 I->isBaseInitializer() && I->isBaseVirtual()) {
1525 VBaseSucc = Succ = B ? B : &cfg->getExit();
1526 Block = createBlock();
1528 B = addInitializer(I);
1538 addSuccessor(B, Block,
true);
1547 for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1548 E = BackpatchBlocks.end(); I != E; ++I ) {
1552 LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1555 if (LI == LabelMap.end())
1557 JumpTarget JT = LI->second;
1558 prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1560 prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1562 const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
1563 B, I->scopePosition, JT.scopePosition);
1564 appendScopeBegin(JT.block, VD, G);
1565 addSuccessor(B, JT.block);
1568 CFGBlock *Successor = (I+1)->block;
1569 for (
auto *L : G->labels()) {
1570 LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1573 if (LI == LabelMap.end())
1575 JumpTarget JT = LI->second;
1577 if (JT.block == Successor)
1579 addSuccessor(B, JT.block);
1586 if (
CFGBlock *B = cfg->getIndirectGotoBlock())
1587 for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1588 E = AddressTakenLabels.end(); I != E; ++I ) {
1590 LabelMapTy::iterator LI = LabelMap.find(*I);
1594 if (LI == LabelMap.end())
continue;
1596 addSuccessor(B, LI->second.block);
1600 cfg->setEntry(createBlock());
1602 if (BuildOpts.AddRichCXXConstructors)
1603 assert(ConstructionContextMap.empty() &&
1604 "Not all construction contexts were cleaned up!");
1606 return std::move(cfg);
1611 CFGBlock *CFGBuilder::createBlock(
bool add_successor) {
1613 if (add_successor && Succ)
1614 addSuccessor(B, Succ);
1621 CFGBlock *CFGBuilder::createNoReturnBlock() {
1624 addSuccessor(B, &cfg->getExit(), Succ);
1630 if (!BuildOpts.AddInitializers)
1633 bool HasTemporaries =
false;
1639 HasTemporaries = isa<ExprWithCleanups>(Init);
1641 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1643 TempDtorContext Context;
1644 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1650 appendInitializer(Block, I);
1653 findConstructionContexts(
1657 if (HasTemporaries) {
1660 return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1662 if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1684 bool *FoundMTE =
nullptr) {
1691 Init = EWC->getSubExpr();
1697 = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1698 Init = MTE->getSubExpr();
1707 const Expr *SkippedInit =
1709 if (SkippedInit != Init) {
1722 void CFGBuilder::addLoopExit(
const Stmt *LoopStmt){
1723 if(!BuildOpts.AddLoopExit)
1726 appendLoopExit(Block, LoopStmt);
1729 void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
1730 LocalScope::const_iterator E,
Stmt *S) {
1731 if (!BuildOpts.AddScopes)
1741 LocalScope::const_iterator
P = B.shared_parent(E);
1742 int Dist = B.distance(P);
1746 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1747 if (I.pointsToFirstDeclaredVar())
1748 DeclsWithEndedScope.insert(*I);
1751 void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1752 LocalScope::const_iterator E,
1754 getDeclsWithEndedScope(B, E, S);
1755 if (BuildOpts.AddScopes)
1756 addScopesEnd(B, E, S);
1757 if (BuildOpts.AddImplicitDtors)
1758 addAutomaticObjDtors(B, E, S);
1759 if (BuildOpts.AddLifetime)
1760 addLifetimeEnds(B, E, S);
1764 void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1765 LocalScope::const_iterator E,
Stmt *S) {
1766 if (!BuildOpts.AddLifetime)
1776 LocalScope::const_iterator
P = B.shared_parent(E);
1777 int dist = B.distance(P);
1784 DeclsTrivial.reserve(dist);
1785 DeclsNonTrivial.reserve(dist);
1787 for (LocalScope::const_iterator I = B; I !=
P; ++I)
1788 if (hasTrivialDestructor(*I))
1789 DeclsTrivial.push_back(*I);
1791 DeclsNonTrivial.push_back(*I);
1797 E = DeclsTrivial.rend();
1799 appendLifetimeEnds(Block, *I, S);
1802 I = DeclsNonTrivial.rbegin(),
1803 E = DeclsNonTrivial.rend();
1805 appendLifetimeEnds(Block, *I, S);
1809 void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
1810 LocalScope::const_iterator E,
Stmt *S) {
1813 if (BuildOpts.AddImplicitDtors)
1818 for (
auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend();
1820 appendScopeEnd(Block, *I, S);
1828 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1829 LocalScope::const_iterator E,
Stmt *S) {
1830 if (!BuildOpts.AddImplicitDtors)
1841 Decls.reserve(B.distance(E));
1842 for (LocalScope::const_iterator I = B; I != E; ++I)
1843 Decls.push_back(*I);
1848 if (hasTrivialDestructor(*I)) {
1851 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) {
1853 appendScopeEnd(Block, *I, S);
1866 if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
1867 Block = createNoReturnBlock();
1872 if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I))
1873 appendScopeEnd(Block, *I, S);
1874 appendAutomaticObjDtor(Block, *I, S);
1881 assert(BuildOpts.AddImplicitDtors &&
1882 "Can be called only when dtors should be added");
1886 for (
const auto &VI : RD->
vbases()) {
1890 const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1893 appendBaseDtor(Block, &VI);
1898 for (
const auto &BI : RD->
bases()) {
1899 if (!BI.isVirtual()) {
1900 const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1903 appendBaseDtor(Block, &BI);
1909 for (
auto *FI : RD->
fields()) {
1913 if (AT->getSize() == 0)
1915 QT = AT->getElementType();
1919 if (!CD->hasTrivialDestructor()) {
1921 appendMemberDtor(Block, FI);
1928 LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*
Scope) {
1931 llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1932 return new (alloc.Allocate<LocalScope>())
1938 void CFGBuilder::addLocalScopeForStmt(
Stmt *S) {
1939 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1940 !BuildOpts.AddScopes)
1943 LocalScope *Scope =
nullptr;
1947 for (
auto *BI : CS->body()) {
1949 if (
DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1950 Scope = addLocalScopeForDeclStmt(DS, Scope);
1958 addLocalScopeForDeclStmt(DS);
1963 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(
DeclStmt *DS,
1964 LocalScope* Scope) {
1965 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
1966 !BuildOpts.AddScopes)
1969 for (
auto *DI : DS->
decls())
1970 if (
VarDecl *VD = dyn_cast<VarDecl>(DI))
1971 Scope = addLocalScopeForVarDecl(VD, Scope);
1975 bool CFGBuilder::hasTrivialDestructor(
VarDecl *VD) {
1996 bool FoundMTE =
false;
2004 if (AT->getSize() == 0)
2006 QT = AT->getElementType();
2011 return !CD->hasDefinition() || CD->hasTrivialDestructor();
2018 LocalScope* CFGBuilder::addLocalScopeForVarDecl(
VarDecl *VD,
2019 LocalScope* Scope) {
2020 assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
2021 "AddImplicitDtors and AddLifetime cannot be used at the same time");
2022 if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
2023 !BuildOpts.AddScopes)
2032 default:
return Scope;
2035 if (BuildOpts.AddImplicitDtors) {
2036 if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
2038 Scope = createOrReuseLocalScope(Scope);
2040 ScopePos = Scope->begin();
2045 assert(BuildOpts.AddLifetime);
2047 Scope = createOrReuseLocalScope(Scope);
2049 ScopePos = Scope->begin();
2055 void CFGBuilder::addLocalScopeAndDtors(
Stmt *S) {
2056 LocalScope::const_iterator scopeBeginPos = ScopePos;
2057 addLocalScopeForStmt(S);
2058 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2068 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(
CFGBlock *Blk,
2069 LocalScope::const_iterator B, LocalScope::const_iterator E) {
2070 if (!BuildOpts.AddImplicitDtors)
2075 for (LocalScope::const_iterator I = B; I != E; ++I)
2085 void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
2086 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2087 if (!BuildOpts.AddLifetime)
2092 for (LocalScope::const_iterator I = B; I != E; ++I) {
2104 CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
2105 CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2106 if (!BuildOpts.AddScopes)
2111 LocalScope::const_iterator PlaceToInsert = B;
2112 for (LocalScope::const_iterator I = B; I != E; ++I)
2115 return *PlaceToInsert;
2121 CFGBlock *CFGBuilder::Visit(
Stmt * S, AddStmtChoice asc,
2122 bool ExternallyDestructed) {
2128 if (
Expr *E = dyn_cast<Expr>(S))
2132 if (
auto *D = dyn_cast<OMPExecutableDirective>(S))
2133 return VisitOMPExecutableDirective(D, asc);
2137 return VisitStmt(S, asc);
2139 case Stmt::ImplicitValueInitExprClass:
2140 if (BuildOpts.OmitImplicitValueInitializers)
2142 return VisitStmt(S, asc);
2144 case Stmt::InitListExprClass:
2145 return VisitInitListExpr(cast<InitListExpr>(S), asc);
2147 case Stmt::AddrLabelExprClass:
2148 return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2150 case Stmt::BinaryConditionalOperatorClass:
2151 return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2153 case Stmt::BinaryOperatorClass:
2154 return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2156 case Stmt::BlockExprClass:
2157 return VisitBlockExpr(cast<BlockExpr>(S), asc);
2159 case Stmt::BreakStmtClass:
2160 return VisitBreakStmt(cast<BreakStmt>(S));
2162 case Stmt::CallExprClass:
2163 case Stmt::CXXOperatorCallExprClass:
2164 case Stmt::CXXMemberCallExprClass:
2165 case Stmt::UserDefinedLiteralClass:
2166 return VisitCallExpr(cast<CallExpr>(S), asc);
2168 case Stmt::CaseStmtClass:
2169 return VisitCaseStmt(cast<CaseStmt>(S));
2171 case Stmt::ChooseExprClass:
2172 return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2174 case Stmt::CompoundStmtClass:
2175 return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);
2177 case Stmt::ConditionalOperatorClass:
2178 return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2180 case Stmt::ContinueStmtClass:
2181 return VisitContinueStmt(cast<ContinueStmt>(S));
2183 case Stmt::CXXCatchStmtClass:
2184 return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2186 case Stmt::ExprWithCleanupsClass:
2187 return VisitExprWithCleanups(cast<ExprWithCleanups>(S),
2188 asc, ExternallyDestructed);
2190 case Stmt::CXXDefaultArgExprClass:
2191 case Stmt::CXXDefaultInitExprClass:
2201 return VisitStmt(S, asc);
2203 case Stmt::CXXBindTemporaryExprClass:
2204 return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2206 case Stmt::CXXConstructExprClass:
2207 return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2209 case Stmt::CXXNewExprClass:
2210 return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2212 case Stmt::CXXDeleteExprClass:
2213 return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2215 case Stmt::CXXFunctionalCastExprClass:
2216 return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2218 case Stmt::CXXTemporaryObjectExprClass:
2219 return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2221 case Stmt::CXXThrowExprClass:
2222 return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2224 case Stmt::CXXTryStmtClass:
2225 return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2227 case Stmt::CXXForRangeStmtClass:
2228 return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2230 case Stmt::DeclStmtClass:
2231 return VisitDeclStmt(cast<DeclStmt>(S));
2233 case Stmt::DefaultStmtClass:
2234 return VisitDefaultStmt(cast<DefaultStmt>(S));
2236 case Stmt::DoStmtClass:
2237 return VisitDoStmt(cast<DoStmt>(S));
2239 case Stmt::ForStmtClass:
2240 return VisitForStmt(cast<ForStmt>(S));
2242 case Stmt::GotoStmtClass:
2243 return VisitGotoStmt(cast<GotoStmt>(S));
2245 case Stmt::GCCAsmStmtClass:
2246 return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
2248 case Stmt::IfStmtClass:
2249 return VisitIfStmt(cast<IfStmt>(S));
2251 case Stmt::ImplicitCastExprClass:
2252 return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2254 case Stmt::ConstantExprClass:
2255 return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2257 case Stmt::IndirectGotoStmtClass:
2258 return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2260 case Stmt::LabelStmtClass:
2261 return VisitLabelStmt(cast<LabelStmt>(S));
2263 case Stmt::LambdaExprClass:
2264 return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2266 case Stmt::MaterializeTemporaryExprClass:
2267 return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2270 case Stmt::MemberExprClass:
2271 return VisitMemberExpr(cast<MemberExpr>(S), asc);
2273 case Stmt::NullStmtClass:
2276 case Stmt::ObjCAtCatchStmtClass:
2277 return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2279 case Stmt::ObjCAutoreleasePoolStmtClass:
2280 return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2282 case Stmt::ObjCAtSynchronizedStmtClass:
2283 return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2285 case Stmt::ObjCAtThrowStmtClass:
2286 return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2288 case Stmt::ObjCAtTryStmtClass:
2289 return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2291 case Stmt::ObjCForCollectionStmtClass:
2292 return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2294 case Stmt::ObjCMessageExprClass:
2295 return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2297 case Stmt::OpaqueValueExprClass:
2300 case Stmt::PseudoObjectExprClass:
2301 return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2303 case Stmt::ReturnStmtClass:
2304 case Stmt::CoreturnStmtClass:
2305 return VisitReturnStmt(S);
2307 case Stmt::SEHExceptStmtClass:
2308 return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2310 case Stmt::SEHFinallyStmtClass:
2311 return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2313 case Stmt::SEHLeaveStmtClass:
2314 return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2316 case Stmt::SEHTryStmtClass:
2317 return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2319 case Stmt::UnaryExprOrTypeTraitExprClass:
2320 return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2323 case Stmt::StmtExprClass:
2324 return VisitStmtExpr(cast<StmtExpr>(S), asc);
2326 case Stmt::SwitchStmtClass:
2327 return VisitSwitchStmt(cast<SwitchStmt>(S));
2329 case Stmt::UnaryOperatorClass:
2330 return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2332 case Stmt::WhileStmtClass:
2333 return VisitWhileStmt(cast<WhileStmt>(S));
2337 CFGBlock *CFGBuilder::VisitStmt(
Stmt *S, AddStmtChoice asc) {
2338 if (asc.alwaysAdd(*
this, S)) {
2340 appendStmt(Block, S);
2343 return VisitChildren(S);
2352 reverse_children RChildren(S);
2353 for (
Stmt *Child : RChildren) {
2362 if (asc.alwaysAdd(*
this, ILE)) {
2364 appendStmt(Block, ILE);
2368 reverse_children RChildren(ILE);
2369 for (
Stmt *Child : RChildren) {
2374 if (BuildOpts.AddCXXDefaultInitExprInAggregates) {
2375 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2376 if (
Stmt *Child = DIE->getExpr())
2385 AddStmtChoice asc) {
2386 AddressTakenLabels.insert(A->
getLabel());
2388 if (asc.alwaysAdd(*
this, A)) {
2390 appendStmt(Block, A);
2397 AddStmtChoice asc) {
2398 if (asc.alwaysAdd(*
this, U)) {
2400 appendStmt(Block, U);
2406 return Visit(U->
getSubExpr(), AddStmtChoice());
2410 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2411 appendStmt(ConfluenceBlock, B);
2416 return VisitLogicalOperator(B,
nullptr, ConfluenceBlock,
2417 ConfluenceBlock).first;
2420 std::pair<CFGBlock*, CFGBlock*>
2433 if (B_RHS->isLogicalOp()) {
2434 std::tie(RHSBlock, ExitBlock) =
2435 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2443 ExitBlock = RHSBlock = createBlock(
false);
2448 TryResult KnownVal = tryEvaluateBool(RHS);
2449 if (!KnownVal.isKnown())
2450 KnownVal = tryEvaluateBool(B);
2453 assert(TrueBlock == FalseBlock);
2454 addSuccessor(RHSBlock, TrueBlock);
2458 addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2459 addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2463 RHSBlock = addStmt(RHS);
2468 return std::make_pair(
nullptr,
nullptr);
2474 if (B_LHS->isLogicalOp()) {
2476 FalseBlock = RHSBlock;
2478 TrueBlock = RHSBlock;
2483 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2488 CFGBlock *LHSBlock = createBlock(
false);
2492 CFGBlock *EntryLHSBlock = addStmt(LHS);
2495 return std::make_pair(
nullptr,
nullptr);
2498 TryResult KnownVal = tryEvaluateBool(LHS);
2502 addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2503 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2506 addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2507 addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2510 return std::make_pair(EntryLHSBlock, ExitBlock);
2514 AddStmtChoice asc) {
2517 return VisitLogicalOperator(B);
2521 appendStmt(Block, B);
2523 return addStmt(B->
getLHS());
2527 if (asc.alwaysAdd(*
this, B)) {
2529 appendStmt(Block, B);
2532 return Visit(B->
getRHS());
2535 if (asc.alwaysAdd(*
this, B)) {
2537 appendStmt(Block, B);
2548 return (LBlock ? LBlock : RBlock);
2551 CFGBlock *CFGBuilder::VisitNoRecurse(
Expr *E, AddStmtChoice asc) {
2552 if (asc.alwaysAdd(*
this, E)) {
2554 appendStmt(Block, E);
2566 Block = createBlock(
false);
2567 Block->setTerminator(B);
2571 if (BreakJumpTarget.block) {
2572 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2573 addSuccessor(Block, BreakJumpTarget.block);
2603 if (!boundType.
isNull()) calleeType = boundType;
2609 bool AddEHEdge =
false;
2613 if (BuildOpts.AddEHEdges)
2619 bool OmitArguments =
false;
2626 if (!FD->isVariadic())
2627 findConstructionContextsForArguments(C);
2631 if (FD->hasAttr<NoThrowAttr>())
2633 if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2634 FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2635 OmitArguments =
true;
2641 if (OmitArguments) {
2642 assert(!NoReturn &&
"noreturn calls with unevaluated args not implemented");
2643 assert(!AddEHEdge &&
"EH calls with unevaluated args not implemented");
2645 appendStmt(Block, C);
2649 if (!NoReturn && !AddEHEdge) {
2651 appendCall(Block, C);
2653 return VisitChildren(C);
2663 Block = createNoReturnBlock();
2665 Block = createBlock();
2667 appendCall(Block, C);
2671 if (TryTerminatedBlock)
2672 addSuccessor(Block, TryTerminatedBlock);
2674 addSuccessor(Block, &cfg->getExit());
2677 return VisitChildren(C);
2681 AddStmtChoice asc) {
2682 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2683 appendStmt(ConfluenceBlock, C);
2687 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2688 Succ = ConfluenceBlock;
2694 Succ = ConfluenceBlock;
2700 Block = createBlock(
false);
2702 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2703 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2704 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2705 Block->setTerminator(C);
2710 LocalScope::const_iterator scopeBeginPos = ScopePos;
2711 addLocalScopeForStmt(C);
2716 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2725 CFGBlock *newBlock = Visit(*I, AddStmtChoice::AlwaysAdd,
2726 ExternallyDestructed);
2729 LastBlock = newBlock;
2734 ExternallyDestructed =
false;
2741 AddStmtChoice asc) {
2747 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2748 appendStmt(ConfluenceBlock, C);
2752 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(
true);
2758 Succ = ConfluenceBlock;
2762 if (trueExpr != opaqueValue) {
2769 LHSBlock = ConfluenceBlock;
2772 Succ = ConfluenceBlock;
2780 if (Cond->isLogicalOp())
2781 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2784 Block = createBlock(
false);
2787 const TryResult& KnownVal = tryEvaluateBool(C->
getCond());
2788 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2789 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2790 Block->setTerminator(C);
2796 if (condExpr != opaqueValue)
2804 return addStmt(condExpr);
2815 return VisitDeclSubExpr(DS);
2829 cfg->addSyntheticDeclStmt(DSNew, DS);
2832 B = VisitDeclSubExpr(DSNew);
2841 assert(DS->
isSingleDecl() &&
"Can handle single declarations only.");
2850 bool HasTemporaries =
false;
2853 CFGBlock *blockAfterStaticInit =
nullptr;
2855 if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2864 blockAfterStaticInit = Succ;
2869 Expr *Init = VD->getInit();
2871 HasTemporaries = isa<ExprWithCleanups>(Init);
2873 if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2875 TempDtorContext Context;
2876 VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2882 appendStmt(Block, DS);
2884 findConstructionContexts(
2894 if (HasTemporaries) {
2899 LastBlock = newBlock;
2902 if (
CFGBlock *newBlock = Visit(Init))
2903 LastBlock = newBlock;
2909 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr())) {
2910 if (
CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2911 LastBlock = newBlock;
2914 maybeAddScopeBeginForVarDecl(Block, VD, DS);
2917 if (ScopePos && VD == *ScopePos)
2921 if (blockAfterStaticInit) {
2923 Block = createBlock(
false);
2924 Block->setTerminator(DS);
2925 addSuccessor(Block, blockAfterStaticInit);
2926 addSuccessor(Block, B);
2947 addLocalScopeForStmt(Init);
2952 addLocalScopeForVarDecl(VD);
2954 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
2976 if (!isa<CompoundStmt>(Else))
2977 addLocalScopeAndDtors(Else);
2979 ElseBlock = addStmt(Else);
2982 ElseBlock = sv.get();
2999 if (!isa<CompoundStmt>(Then))
3000 addLocalScopeAndDtors(Then);
3002 ThenBlock = addStmt(Then);
3008 ThenBlock = createBlock(
false);
3009 addSuccessor(ThenBlock, sv.get());
3029 LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
3032 Block = createBlock(
false);
3035 Block->setTerminator(I);
3038 const TryResult &KnownVal = tryEvaluateBool(I->
getCond());
3042 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());
3043 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());
3048 LastBlock = addStmt(I->
getCond());
3054 LastBlock = addStmt(const_cast<DeclStmt *>(DS));
3061 LastBlock = addStmt(Init);
3074 assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
3077 Block = createBlock(
false);
3079 addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3081 if (
auto *R = dyn_cast<ReturnStmt>(S))
3082 findConstructionContexts(
3088 if (!Block->hasNoReturnElement())
3089 addSuccessor(Block, &cfg->getExit());
3092 appendStmt(Block, S);
3095 if (
ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3096 if (
Expr *O = RS->getRetValue())
3097 return Visit(O, AddStmtChoice::AlwaysAdd,
true);
3100 return VisitChildren(S);
3114 if (!SEHExceptBlock)
3115 SEHExceptBlock = createBlock();
3117 appendStmt(SEHExceptBlock, ES);
3120 SEHExceptBlock->setLabel(ES);
3129 return SEHExceptBlock;
3133 return VisitCompoundStmt(FS->
getBlock(),
false);
3143 Block = createBlock(
false);
3144 Block->setTerminator(LS);
3148 if (SEHLeaveJumpTarget.block) {
3149 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3150 addSuccessor(Block, SEHLeaveJumpTarget.block);
3160 CFGBlock *SEHTrySuccessor =
nullptr;
3165 SEHTrySuccessor = Block;
3166 }
else SEHTrySuccessor = Succ;
3172 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3175 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
3182 Succ = SEHTrySuccessor;
3184 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3189 addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3191 if (PrevSEHTryTerminatedBlock)
3192 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3194 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3197 Succ = SEHTrySuccessor;
3201 NewTryTerminatedBlock);
3202 cfg->addTryDispatchBlock(TryTerminatedBlock);
3208 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3210 assert(Terminator->
getTryBlock() &&
"__try must contain a non-NULL body");
3221 LabelBlock = createBlock();
3223 assert(LabelMap.find(L->
getDecl()) == LabelMap.end() &&
3224 "label already in map");
3225 LabelMap[L->
getDecl()] = JumpTarget(LabelBlock, ScopePos);
3231 LabelBlock->setLabel(L);
3245 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3247 if (
Expr *CopyExpr = CI.getCopyExpr()) {
3257 CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3260 if (
Expr *Init = *it) {
3273 Block = createBlock(
false);
3274 Block->setTerminator(G);
3277 LabelMapTy::iterator I = LabelMap.find(G->
getLabel());
3279 if (I == LabelMap.end())
3281 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3283 JumpTarget JT = I->second;
3284 addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
3285 addSuccessor(Block, JT.block);
3296 return VisitStmt(G, asc);
3303 Block = createBlock();
3304 Block->setTerminator(G);
3306 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3309 BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3324 addLocalScopeForStmt(Init);
3325 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3328 addLocalScopeForVarDecl(VD);
3329 LocalScope::const_iterator ContinueScopePos = ScopePos;
3331 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3340 LoopSuccessor = Block;
3342 LoopSuccessor = Succ;
3347 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3349 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3362 Block = Succ = TransitionBlock = createBlock(
false);
3363 TransitionBlock->setLoopTarget(F);
3373 assert(Block == Succ);
3381 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3382 ContinueJumpTarget.block->setLoopTarget(F);
3385 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3389 if (!isa<CompoundStmt>(F->
getBody()))
3390 addLocalScopeAndDtors(F->
getBody());
3394 BodyBlock = addStmt(F->
getBody());
3399 BodyBlock = ContinueJumpTarget.block;
3408 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3417 dyn_cast_or_null<BinaryOperator>(C ? C->
IgnoreParens() :
nullptr))
3418 if (Cond->isLogicalOp()) {
3419 std::tie(EntryConditionBlock, ExitConditionBlock) =
3420 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3425 EntryConditionBlock = ExitConditionBlock = createBlock(
false);
3426 ExitConditionBlock->setTerminator(F);
3429 TryResult KnownVal(
true);
3435 Block = ExitConditionBlock;
3436 EntryConditionBlock = addStmt(C);
3445 findConstructionContexts(
3448 appendStmt(Block, DS);
3449 EntryConditionBlock = addStmt(Init);
3450 assert(Block == EntryConditionBlock);
3451 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3455 if (Block && badCFG)
3458 KnownVal = tryEvaluateBool(C);
3462 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3465 addSuccessor(ExitConditionBlock,
3466 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3470 addSuccessor(TransitionBlock, EntryConditionBlock);
3473 Succ = EntryConditionBlock;
3479 ScopePos = LoopBeginScopePos;
3480 Block = createBlock();
3487 Succ = EntryConditionBlock;
3488 return EntryConditionBlock;
3493 AddStmtChoice asc) {
3494 findConstructionContexts(
3498 return VisitStmt(MTE, asc);
3502 if (asc.alwaysAdd(*
this, M)) {
3504 appendStmt(Block, M);
3546 LoopSuccessor = Block;
3549 LoopSuccessor = Succ;
3552 CFGBlock *ExitConditionBlock = createBlock(
false);
3560 appendStmt(ExitConditionBlock, S);
3561 Block = ExitConditionBlock;
3567 AddStmtChoice::NotAlwaysAdd);
3576 Succ = EntryConditionBlock;
3583 save_break(BreakJumpTarget);
3589 Succ = LoopBackBlock = createBlock();
3592 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3593 ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3598 BodyBlock = ContinueJumpTarget.block;
3605 addSuccessor(ExitConditionBlock, BodyBlock);
3610 addSuccessor(ExitConditionBlock, LoopSuccessor);
3613 Block = createBlock();
3641 appendStmt(Block, S);
3656 appendStmt(Block, E);
3668 Semantic = OVE->getSourceExpr();
3686 LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3688 addLocalScopeForVarDecl(VD);
3689 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3698 LoopSuccessor = Block;
3701 LoopSuccessor = Succ;
3704 CFGBlock *BodyBlock =
nullptr, *TransitionBlock =
nullptr;
3713 save_break(BreakJumpTarget);
3717 Succ = TransitionBlock = createBlock(
false);
3718 TransitionBlock->setLoopTarget(W);
3719 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3722 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3725 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3729 if (!isa<CompoundStmt>(W->
getBody()))
3730 addLocalScopeAndDtors(W->
getBody());
3733 BodyBlock = addStmt(W->
getBody());
3736 BodyBlock = ContinueJumpTarget.block;
3737 else if (Block && badCFG)
3744 CFGBlock *EntryConditionBlock =
nullptr, *ExitConditionBlock =
nullptr;
3752 if (Cond->isLogicalOp()) {
3753 std::tie(EntryConditionBlock, ExitConditionBlock) =
3754 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3759 ExitConditionBlock = createBlock(
false);
3760 ExitConditionBlock->setTerminator(W);
3765 Block = ExitConditionBlock;
3766 Block = EntryConditionBlock = addStmt(C);
3775 findConstructionContexts(
3779 appendStmt(Block, DS);
3780 EntryConditionBlock = addStmt(Init);
3781 assert(Block == EntryConditionBlock);
3782 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3786 if (Block && badCFG)
3790 const TryResult& KnownVal = tryEvaluateBool(C);
3793 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3796 addSuccessor(ExitConditionBlock,
3797 KnownVal.isTrue() ? nullptr : LoopSuccessor);
3801 addSuccessor(TransitionBlock, EntryConditionBlock);
3808 Succ = EntryConditionBlock;
3809 return EntryConditionBlock;
3827 Block = createBlock(
false);
3830 addSuccessor(Block, &cfg->getExit());
3834 return VisitStmt(S, AddStmtChoice::AlwaysAdd);
3838 AddStmtChoice asc) {
3839 findConstructionContextsForArguments(ME);
3842 appendObjCMessage(Block, ME);
3844 return VisitChildren(ME);
3853 Block = createBlock(
false);
3855 if (TryTerminatedBlock)
3857 addSuccessor(Block, TryTerminatedBlock);
3860 addSuccessor(Block, &cfg->getExit());
3864 return VisitStmt(T, AddStmtChoice::AlwaysAdd);
3877 LoopSuccessor = Block;
3879 LoopSuccessor = Succ;
3884 CFGBlock *ExitConditionBlock = createBlock(
false);
3885 CFGBlock *EntryConditionBlock = ExitConditionBlock;
3893 Block = ExitConditionBlock;
3894 EntryConditionBlock = addStmt(C);
3902 Succ = EntryConditionBlock;
3905 const TryResult &KnownVal = tryEvaluateBool(D->
getCond());
3915 save_break(BreakJumpTarget);
3918 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
3921 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3928 if (!isa<CompoundStmt>(D->
getBody()))
3929 addLocalScopeAndDtors(D->
getBody());
3932 BodyBlock = addStmt(D->
getBody());
3935 BodyBlock = EntryConditionBlock;
3948 CFGBlock *LoopBackBlock = createBlock();
3951 if (!KnownVal.isFalse())
3953 addSuccessor(ExitConditionBlock, LoopBackBlock);
3955 addSuccessor(ExitConditionBlock,
nullptr);
3960 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3978 Block = createBlock(
false);
3979 Block->setTerminator(C);
3983 if (ContinueJumpTarget.block) {
3984 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
3985 addSuccessor(Block, ContinueJumpTarget.block);
3993 AddStmtChoice asc) {
3994 if (asc.alwaysAdd(*
this, E)) {
3996 appendStmt(Block, E);
4004 VA !=
nullptr; VA =
FindVA(VA->getElementType().getTypePtr()))
4005 lastBlock = addStmt(VA->getSizeExpr());
4013 if (asc.alwaysAdd(*
this, SE)) {
4015 appendStmt(Block, SE);
4017 return VisitCompoundStmt(SE->
getSubStmt(),
true);
4023 CFGBlock *SwitchSuccessor =
nullptr;
4031 addLocalScopeForStmt(Init);
4036 addLocalScopeForVarDecl(VD);
4038 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4043 SwitchSuccessor = Block;
4044 }
else SwitchSuccessor = Succ;
4048 save_default(DefaultCaseBlock);
4054 DefaultCaseBlock = SwitchSuccessor;
4057 SwitchTerminatedBlock = createBlock(
false);
4061 Succ = SwitchSuccessor;
4062 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4067 assert(Terminator->
getBody() &&
"switch must contain a non-NULL body");
4076 assert(Terminator->
getCond() &&
"switch condition must be non-NULL");
4078 bool b = tryEvaluate(Terminator->
getCond(), result);
4080 b ? &result :
nullptr);
4084 if (!isa<CompoundStmt>(Terminator->
getBody()))
4085 addLocalScopeAndDtors(Terminator->
getBody());
4087 addStmt(Terminator->
getBody());
4099 bool SwitchAlwaysHasSuccessor =
false;
4100 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4103 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4104 !SwitchAlwaysHasSuccessor);
4107 SwitchTerminatedBlock->setTerminator(Terminator);
4108 Block = SwitchTerminatedBlock;
4117 LastBlock = addStmt(Init);
4118 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
4125 LastBlock = addStmt(Init);
4138 bool addCase =
false;
4140 if (!switchExclusivelyCovered) {
4146 if (condInt == lhsInt) {
4148 switchExclusivelyCovered =
true;
4150 else if (condInt > lhsInt) {
4153 const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
4154 if (V2 >= condInt) {
4156 switchExclusivelyCovered =
true;
4170 CFGBlock *TopBlock =
nullptr, *LastBlock =
nullptr;
4176 while (isa<CaseStmt>(
Sub)) {
4177 CFGBlock *currentBlock = createBlock(
false);
4181 addSuccessor(LastBlock, currentBlock);
4183 TopBlock = currentBlock;
4185 addSuccessor(SwitchTerminatedBlock,
4188 ? currentBlock :
nullptr);
4190 LastBlock = currentBlock;
4191 CS = cast<CaseStmt>(
Sub);
4200 CaseBlock = createBlock();
4211 assert(SwitchTerminatedBlock);
4212 addSuccessor(SwitchTerminatedBlock, CaseBlock,
4220 addSuccessor(LastBlock, CaseBlock);
4234 DefaultCaseBlock = Block;
4236 if (!DefaultCaseBlock)
4237 DefaultCaseBlock = createBlock();
4241 DefaultCaseBlock->setLabel(Terminator);
4256 Succ = DefaultCaseBlock;
4258 return DefaultCaseBlock;
4269 TrySuccessor = Block;
4270 }
else TrySuccessor = Succ;
4272 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4275 CFGBlock *NewTryTerminatedBlock = createBlock(
false);
4279 bool HasCatchAll =
false;
4282 Succ = TrySuccessor;
4288 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4293 addSuccessor(NewTryTerminatedBlock, CatchBlock);
4296 if (PrevTryTerminatedBlock)
4297 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4299 addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4303 Succ = TrySuccessor;
4307 cfg->addTryDispatchBlock(TryTerminatedBlock);
4309 assert(Terminator->
getTryBlock() &&
"try must contain a non-NULL body");
4325 LocalScope::const_iterator BeginScopePos = ScopePos;
4326 addLocalScopeForVarDecl(VD);
4327 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4335 CatchBlock = createBlock();
4341 appendStmt(CatchBlock, CS);
4376 addLocalScopeForStmt(Range);
4378 addLocalScopeForStmt(
Begin);
4380 addLocalScopeForStmt(
End);
4381 addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4383 LocalScope::const_iterator ContinueScopePos = ScopePos;
4391 LoopSuccessor = Block;
4393 LoopSuccessor = Succ;
4398 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4401 CFGBlock *ConditionBlock = createBlock(
false);
4406 Block = ConditionBlock;
4407 CFGBlock *BeginConditionBlock = addStmt(C);
4410 assert(BeginConditionBlock == ConditionBlock &&
4411 "condition block in for-range was unexpectedly complex");
4412 (void)BeginConditionBlock;
4417 Succ = ConditionBlock;
4420 TryResult KnownVal(
true);
4423 KnownVal = tryEvaluateBool(S->
getCond());
4436 Succ = addStmt(S->
getInc());
4439 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4443 ContinueJumpTarget.block->setLoopTarget(S);
4463 addSuccessor(ConditionBlock,
4464 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
4469 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4472 Block = createBlock();
4482 AddStmtChoice asc,
bool ExternallyDestructed) {
4483 if (BuildOpts.AddTemporaryDtors) {
4486 TempDtorContext Context;
4487 VisitForTemporaryDtors(E->
getSubExpr(), ExternallyDestructed, Context);
4491 asc = asc.withAlwaysAdd(
true);
4497 AddStmtChoice asc) {
4498 if (asc.alwaysAdd(*
this, E)) {
4500 appendStmt(Block, E);
4502 findConstructionContexts(
4507 asc = asc.withAlwaysAdd(
false);
4513 AddStmtChoice asc) {
4517 findConstructionContextsForArguments(C);
4520 appendConstructor(Block, C);
4522 return VisitChildren(C);
4526 AddStmtChoice asc) {
4528 appendStmt(Block, NE);
4530 findConstructionContexts(
4537 if (BuildOpts.AddCXXNewAllocator)
4538 appendNewAllocator(Block, NE);
4551 AddStmtChoice asc) {
4553 appendStmt(Block, DE);
4560 appendDeleteDtor(Block, RD, DE);
4564 return VisitChildren(DE);
4568 AddStmtChoice asc) {
4569 if (asc.alwaysAdd(*
this, E)) {
4571 appendStmt(Block, E);
4573 asc = asc.withAlwaysAdd(
false);
4579 AddStmtChoice asc) {
4583 findConstructionContextsForArguments(C);
4586 appendConstructor(Block, C);
4587 return VisitChildren(C);
4591 AddStmtChoice asc) {
4592 if (asc.alwaysAdd(*
this, E)) {
4594 appendStmt(Block, E);
4600 return Visit(E->
getSubExpr(), AddStmtChoice());
4604 return Visit(E->
getSubExpr(), AddStmtChoice());
4609 CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4612 IBlock = createBlock(
false);
4613 cfg->setIndirectGotoBlock(IBlock);
4621 Block = createBlock(
false);
4622 Block->setTerminator(I);
4623 addSuccessor(Block, IBlock);
4627 CFGBlock *CFGBuilder::VisitForTemporaryDtors(
Stmt *E,
bool ExternallyDestructed,
4628 TempDtorContext &Context) {
4629 assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
4638 return VisitChildrenForTemporaryDtors(E,
false, Context);
4640 case Stmt::InitListExprClass:
4641 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
4643 case Stmt::BinaryOperatorClass:
4644 return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4645 ExternallyDestructed,
4648 case Stmt::CXXBindTemporaryExprClass:
4649 return VisitCXXBindTemporaryExprForTemporaryDtors(
4650 cast<CXXBindTemporaryExpr>(E), ExternallyDestructed, Context);
4652 case Stmt::BinaryConditionalOperatorClass:
4653 case Stmt::ConditionalOperatorClass:
4654 return VisitConditionalOperatorForTemporaryDtors(
4655 cast<AbstractConditionalOperator>(E), ExternallyDestructed, Context);
4657 case Stmt::ImplicitCastExprClass:
4659 E = cast<CastExpr>(E)->getSubExpr();
4662 case Stmt::CXXFunctionalCastExprClass:
4664 E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4667 case Stmt::ConstantExprClass:
4668 E = cast<ConstantExpr>(E)->getSubExpr();
4671 case Stmt::ParenExprClass:
4672 E = cast<ParenExpr>(E)->getSubExpr();
4675 case Stmt::MaterializeTemporaryExprClass: {
4681 E =
const_cast<Expr *
>(
4682 cast<MaterializeTemporaryExpr>(E)
4684 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4686 for (
const Expr *CommaLHS : CommaLHSs) {
4687 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
4693 case Stmt::BlockExprClass:
4698 case Stmt::LambdaExprClass: {
4701 auto *
LE = cast<LambdaExpr>(E);
4703 for (
Expr *Init :
LE->capture_inits()) {
4705 if (
CFGBlock *R = VisitForTemporaryDtors(
4706 Init,
true, Context))
4713 case Stmt::StmtExprClass:
4718 case Stmt::CXXDefaultArgExprClass:
4719 E = cast<CXXDefaultArgExpr>(E)->getExpr();
4722 case Stmt::CXXDefaultInitExprClass:
4723 E = cast<CXXDefaultInitExpr>(E)->getExpr();
4728 CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(
Stmt *E,
4729 bool ExternallyDestructed,
4730 TempDtorContext &Context) {
4731 if (isa<LambdaExpr>(E)) {
4743 if (
CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
4749 CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
4750 BinaryOperator *E,
bool ExternallyDestructed, TempDtorContext &Context) {
4754 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(), ExternallyDestructed, Context);
4755 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4756 return LHSBlock ? LHSBlock : RHSBlock;
4760 VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4761 TryResult RHSExecuted = tryEvaluateBool(E->
getLHS());
4762 if (RHSExecuted.isKnown() && E->
getOpcode() == BO_LOr)
4763 RHSExecuted.negate();
4768 TempDtorContext RHSContext(
4770 VisitForTemporaryDtors(E->
getRHS(),
false, RHSContext);
4771 InsertTempDtorDecisionBlock(RHSContext);
4779 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4780 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4781 return LHSBlock ? LHSBlock : RHSBlock;
4787 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->
getLHS(),
false, Context);
4788 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->
getRHS(),
false, Context);
4789 return RHSBlock ? RHSBlock : LHSBlock;
4792 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
4797 if (!ExternallyDestructed) {
4809 Block = createNoReturnBlock();
4810 }
else if (Context.needsTempDtorBranch()) {
4814 Block = createBlock();
4818 if (Context.needsTempDtorBranch()) {
4819 Context.setDecisionPoint(Succ, E);
4821 appendTemporaryDtor(Block, E);
4828 void CFGBuilder::InsertTempDtorDecisionBlock(
const TempDtorContext &Context,
4830 if (!Context.TerminatorExpr) {
4834 assert(Context.TerminatorExpr);
4835 CFGBlock *Decision = createBlock(
false);
4838 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
4839 addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
4840 !Context.KnownExecuted.isTrue());
4844 CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
4846 TempDtorContext &Context) {
4847 VisitForTemporaryDtors(E->
getCond(),
false, Context);
4850 TryResult ConditionVal = tryEvaluateBool(E->
getCond());
4851 TryResult NegatedVal = ConditionVal;
4852 if (NegatedVal.isKnown()) NegatedVal.negate();
4854 TempDtorContext TrueContext(
4856 VisitForTemporaryDtors(E->
getTrueExpr(), ExternallyDestructed, TrueContext);
4859 Block = ConditionBlock;
4860 Succ = ConditionSucc;
4861 TempDtorContext FalseContext(
4863 VisitForTemporaryDtors(E->
getFalseExpr(), ExternallyDestructed, FalseContext);
4865 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
4866 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
4867 }
else if (TrueContext.TerminatorExpr) {
4869 InsertTempDtorDecisionBlock(TrueContext);
4871 InsertTempDtorDecisionBlock(FalseContext);
4877 AddStmtChoice asc) {
4878 if (asc.alwaysAdd(*
this, D)) {
4880 appendStmt(Block, D);
4890 for (
Stmt *S : llvm::reverse(Used)) {
4891 assert(S &&
"Expected non-null used-in-clause child.");
4898 Stmt *S = CS->getCapturedStmt();
4899 if (!isa<CompoundStmt>(S))
4900 addLocalScopeAndDtors(S);
4912 bool first_block = begin() == end();
4916 new (Mem)
CFGBlock(NumBlockIDs++, BlkBVC,
this);
4917 Blocks.push_back(Mem, BlkBVC);
4921 Entry = Exit = &back();
4930 CFGBuilder Builder(C, BO);
4931 return Builder.buildCFG(D, Statement);
4943 llvm::SmallPtrSet<const CFGBlock *, 4> Visited;
4946 auto IteratorAndFlag = Visited.insert(B);
4947 if (!IteratorAndFlag.second) {
4953 const CFGBlock *FirstReachableB =
nullptr;
4955 if (!AB.isReachable())
4958 if (FirstReachableB ==
nullptr) {
4959 FirstReachableB = &*AB;
4966 if (!FirstReachableB) {
4972 B = FirstReachableB;
4991 llvm_unreachable(
"getDestructorDecl should only be used with " 4994 const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
5020 const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
5029 castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
5038 llvm_unreachable(
"getKind() returned bogus value");
5046 : ReachableBlock(IsReachable ? B : nullptr),
5047 UnreachableBlock(!IsReachable ? B : nullptr,
5048 B && IsReachable ? AB_Normal : AB_Unreachable) {}
5051 : ReachableBlock(B),
5052 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
5053 B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5061 UnreachableB->Preds.push_back(
AdjacentBlock(
this,
false), C);
5063 Succs.push_back(Succ, C);
5076 if (S->isAllEnumCasesCovered()) {
5078 if (!L || !isa<CaseStmt>(L))
5094 using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5095 using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5099 signed currentBlock = 0;
5100 unsigned currStmt = 0;
5111 BI != BEnd; ++BI, ++j ) {
5113 const Stmt *stmt= SE->getStmt();
5114 std::pair<unsigned, unsigned>
P((*I)->getBlockID(), j);
5118 case Stmt::DeclStmtClass:
5119 DeclMap[cast<DeclStmt>(
stmt)->getSingleDecl()] =
P;
5121 case Stmt::IfStmtClass: {
5122 const VarDecl *var = cast<IfStmt>(
stmt)->getConditionVariable();
5127 case Stmt::ForStmtClass: {
5128 const VarDecl *var = cast<ForStmt>(
stmt)->getConditionVariable();
5133 case Stmt::WhileStmtClass: {
5135 cast<WhileStmt>(
stmt)->getConditionVariable();
5140 case Stmt::SwitchStmtClass: {
5142 cast<SwitchStmt>(
stmt)->getConditionVariable();
5147 case Stmt::CXXCatchStmtClass: {
5149 cast<CXXCatchStmt>(
stmt)->getExceptionDecl();
5162 ~StmtPrinterHelper()
override =
default;
5164 const LangOptions &getLangOpts()
const {
return LangOpts; }
5165 void setBlockID(
signed i) { currentBlock = i; }
5166 void setStmtID(
unsigned i) { currStmt = i; }
5168 bool handledStmt(
Stmt *S, raw_ostream &OS)
override {
5169 StmtMapTy::iterator I = StmtMap.find(S);
5171 if (I == StmtMap.end())
5174 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5175 && I->second.second == currStmt) {
5179 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5183 bool handleDecl(
const Decl *D, raw_ostream &OS) {
5184 DeclMapTy::iterator I = DeclMap.find(D);
5186 if (I == DeclMap.end())
5189 if (currentBlock >= 0 && I->second.first == (
unsigned) currentBlock
5190 && I->second.second == currStmt) {
5194 OS <<
"[B" << I->second.first <<
"." << I->second.second <<
"]";
5199 class CFGBlockTerminatorPrint
5200 :
public StmtVisitor<CFGBlockTerminatorPrint,void> {
5202 StmtPrinterHelper* Helper;
5206 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5208 : OS(os), Helper(helper), Policy(Policy) {
5212 void VisitIfStmt(
IfStmt *I) {
5219 void VisitStmt(
Stmt *Terminator) {
5225 OS <<
"static init " << VD->
getName();
5228 void VisitForStmt(
ForStmt *F) {
5247 void VisitDoStmt(
DoStmt *D) {
5248 OS <<
"do ... while ";
5253 void VisitSwitchStmt(
SwitchStmt *Terminator) {
5268 Cond->printPretty(OS, Helper, Policy);
5269 OS <<
" ? ... : ...";
5273 OS <<
"__builtin_choose_expr( ";
5275 Cond->printPretty(OS, Helper, Policy);
5302 llvm_unreachable(
"Invalid logical operator.");
5306 void VisitExpr(
Expr *E) {
5317 OS <<
"(Temp Dtor) ";
5321 OS <<
"(See if most derived ctor has already initialized vbases)";
5339 IE->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5343 OS <<
" (Base initializer)";
5345 OS <<
" (Delegating initializer)";
5347 OS <<
" (Member initializer)";
5351 StmtPrinterHelper &Helper,
5357 const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5364 cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5366 Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5370 const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5371 Stmts.push_back(SDSCC->getDeclStmt());
5375 const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5376 Stmts.push_back(CDSCC->getDeclStmt());
5377 Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5381 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5382 Stmts.push_back(NECC->getCXXNewExpr());
5386 const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5387 Stmts.push_back(RSCC->getReturnStmt());
5392 cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5393 Stmts.push_back(RSCC->getReturnStmt());
5394 Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5398 const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5399 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5400 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5404 const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5405 Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5406 Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5407 Stmts.push_back(TOCC->getConstructorAfterElision());
5411 const auto *ACC = cast<ArgumentConstructionContext>(CC);
5412 if (
const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5414 Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
5417 Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
5418 OS <<
"+" << ACC->getIndex();
5425 Helper.handledStmt(const_cast<Stmt *>(I), OS);
5429 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5433 StmtPrinterHelper Helper(
nullptr, {});
5437 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5440 case CFGElement::Kind::Statement:
5441 case CFGElement::Kind::CXXRecordTypedCall:
5442 case CFGElement::Kind::Constructor: {
5445 assert(S !=
nullptr &&
"Expecting non-null Stmt");
5448 if (
const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5452 if (Children.begin() != Children.end()) {
5461 if (B->getOpcode() == BO_Comma) {
5463 Helper.handledStmt(B->getRHS(),OS);
5468 S->printPretty(OS, &Helper,
PrintingPolicy(Helper.getLangOpts()));
5471 if (isa<CXXOperatorCallExpr>(S))
5472 OS <<
" (OperatorCall)";
5473 OS <<
" (CXXRecordTypedCall";
5476 }
else if (isa<CXXOperatorCallExpr>(S)) {
5477 OS <<
" (OperatorCall)";
5478 }
else if (isa<CXXBindTemporaryExpr>(S)) {
5479 OS <<
" (BindTemporary)";
5481 OS <<
" (CXXConstructExpr";
5485 OS <<
", " << CCE->getType().getAsString() <<
")";
5486 }
else if (
const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5487 OS <<
" (" << CE->getStmtClassName() <<
", " 5488 << CE->getCastKindName()
5489 <<
", " << CE->getType().getAsString()
5500 case CFGElement::Kind::Initializer:
5505 case CFGElement::Kind::AutomaticObjectDtor: {
5508 Helper.handleDecl(VD, OS);
5516 OS <<
"() (Implicit destructor)\n";
5520 case CFGElement::Kind::LifetimeEnds:
5522 OS <<
" (Lifetime ends)\n";
5525 case CFGElement::Kind::LoopExit:
5526 OS << E.
castAs<
CFGLoopExit>().getLoopStmt()->getStmtClassName() <<
" (LoopExit)\n";
5529 case CFGElement::Kind::ScopeBegin:
5530 OS <<
"CFGScopeBegin(";
5536 case CFGElement::Kind::ScopeEnd:
5537 OS <<
"CFGScopeEnd(";
5543 case CFGElement::Kind::NewAllocator:
5544 OS <<
"CFGNewAllocator(";
5546 AllocExpr->getType().print(OS,
PrintingPolicy(Helper.getLangOpts()));
5550 case CFGElement::Kind::DeleteDtor: {
5557 Helper.handledStmt(cast<Stmt>(DelExpr->
getArgument()), OS);
5558 OS <<
"->~" << RD->getName().str() <<
"()";
5559 OS <<
" (Implicit destructor)\n";
5563 case CFGElement::Kind::BaseDtor: {
5566 OS <<
" (Base object destructor)\n";
5570 case CFGElement::Kind::MemberDtor: {
5573 OS <<
"this->" << FD->
getName();
5575 OS <<
" (Member object destructor)\n";
5579 case CFGElement::Kind::TemporaryDtor: {
5583 OS <<
"() (Temporary object destructor)\n";
5591 StmtPrinterHelper &Helper,
bool print_edges,
5597 OS.changeColor(raw_ostream::YELLOW,
true);
5602 OS <<
" (ENTRY)]\n";
5603 else if (&B == &cfg->
getExit())
5606 OS <<
" (INDIRECT GOTO DISPATCH)]\n";
5608 OS <<
" (NORETURN)]\n";
5632 }
else if (isa<DefaultStmt>(
Label))
5648 llvm_unreachable(
"Invalid label statement in CFGBlock.");
5657 I != E ; ++I, ++j ) {
5662 OS << llvm::format(
"%3d", j) <<
": ";
5664 Helper.setStmtID(j);
5672 OS.changeColor(raw_ostream::GREEN);
5676 Helper.setBlockID(-1);
5679 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
5690 const raw_ostream::Colors Color = raw_ostream::BLUE;
5692 OS.changeColor(Color);
5700 OS.changeColor(Color);
5708 bool Reachable =
true;
5711 B = I->getPossiblyUnreachableBlock();
5716 OS <<
"(Unreachable)";
5727 const raw_ostream::Colors Color = raw_ostream::MAGENTA;
5729 OS.changeColor(Color);
5737 OS.changeColor(Color);
5746 bool Reachable =
true;
5749 B = I->getPossiblyUnreachableBlock();
5755 OS <<
"(Unreachable)";
5771 print(llvm::errs(), LO, ShowColors);
5776 StmtPrinterHelper Helper(
this, LO);
5779 print_block(OS,
this, getEntry(), Helper,
true, ShowColors);
5782 for (
const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
5784 if (&(**I) == &getEntry() || &(**I) == &getExit())
5787 print_block(OS,
this, **I, Helper,
true, ShowColors);
5791 print_block(OS,
this, getExit(), Helper,
true, ShowColors);
5802 bool ShowColors)
const {
5803 print(llvm::errs(), cfg, LO, ShowColors);
5814 StmtPrinterHelper Helper(cfg, LO);
5815 print_block(OS, cfg, *
this, Helper,
true, ShowColors);
5822 CFGBlockTerminatorPrint TPrinter(OS,
nullptr,
PrintingPolicy(LO));
5828 bool AddQuotes)
const {
5830 llvm::raw_string_ostream TempOut(Buf);
5855 if (isa<CXXThrowExpr>(StmtElm->getStmt()))
5872 llvm::SmallPtrSet<const CFGBlock *, 32> Visited;
5874 DFSWorkList.push_back(StartBlk);
5875 while (!DFSWorkList.empty()) {
5876 const CFGBlock *Blk = DFSWorkList.back();
5877 DFSWorkList.pop_back();
5878 Visited.insert(Blk);
5887 for (
const auto &Succ : Blk->
succs()) {
5888 if (
const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
5892 DFSWorkList.push_back(SuccBlk);
5921 const Stmt *Cond = StmtElem->getStmt();
5922 if (isa<ObjCForCollectionStmt>(Cond) || isa<DeclStmt>(Cond))
5927 return cast<Expr>(Cond)->IgnoreParens();
5941 case Stmt::CXXForRangeStmtClass:
5942 E = cast<CXXForRangeStmt>(
Terminator)->getCond();
5945 case Stmt::ForStmtClass:
5949 case Stmt::WhileStmtClass:
5953 case Stmt::DoStmtClass:
5957 case Stmt::IfStmtClass:
5961 case Stmt::ChooseExprClass:
5965 case Stmt::IndirectGotoStmtClass:
5966 E = cast<IndirectGotoStmt>(
Terminator)->getTarget();
5969 case Stmt::SwitchStmtClass:
5973 case Stmt::BinaryConditionalOperatorClass:
5974 E = cast<BinaryConditionalOperator>(
Terminator)->getCond();
5977 case Stmt::ConditionalOperatorClass:
5978 E = cast<ConditionalOperator>(
Terminator)->getCond();
5981 case Stmt::BinaryOperatorClass:
5982 E = cast<BinaryOperator>(
Terminator)->getLHS();
5985 case Stmt::ObjCForCollectionStmtClass:
6005 StmtPrinterHelper H(
this, LO);
6007 llvm::ViewGraph(
this,
"CFG");
6008 GraphHelper =
nullptr;
6020 std::string OutSStr;
6021 llvm::raw_string_ostream Out(OutSStr);
6022 print_block(Out,Graph, *Node, *GraphHelper,
false,
false);
6023 std::string& OutStr = Out.str();
6025 if (OutStr[0] ==
'\n') OutStr.erase(OutStr.begin());
6028 for (
unsigned i = 0; i != OutStr.length(); ++i)
6029 if (OutStr[i] ==
'\n') {
6031 OutStr.insert(OutStr.begin()+i+1,
'l');
unsigned getNumSemanticExprs() const
const Expr * getSubExpr() const
Stmt * Label
An (optional) label that prefixes the executable statements in the block.
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Defines the clang::ASTContext interface.
const BlockDecl * getBlockDecl() const
Represents C++ allocator call.
const CXXDestructorDecl * getDestructor() const
This represents a GCC inline-assembly statement extension.
Represents a function declaration or definition.
static llvm::iterator_range< used_clauses_child_iterator > used_clauses_children(ArrayRef< OMPClause *> Clauses)
Expr * getInit() const
Get the initializer.
bool Cast(InterpState &S, CodePtr OpPC)
CompoundStmt * getBlock() const
A class which contains all the information about a particular captured value.
A (possibly-)qualified type.
bool isBlockPointerType() const
ArrayRef< OMPClause * > clauses()
static SourceLocation GetEndLoc(Decl *D)
AdjacentBlocks::const_iterator const_pred_iterator
iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr *> &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
const Stmt * getStmt() const
bool operator==(CanQual< T > x, CanQual< U > y)
DOTGraphTraits(bool isSimple=false)
ElementList::iterator iterator
succ_iterator succ_begin()
CompoundStmt * getSubStmt()
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
const DeclStmt * getConditionVariableDeclStmt() const
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
Stmt - This represents one statement.
bool isStandaloneDirective() const
Returns whether or not this is a Standalone directive.
FunctionType - C99 6.7.5.3 - Function Declarators.
CXXCatchStmt * getHandler(unsigned i)
IfStmt - This represents an if/then/else.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
StorageClass getStorageClass() const
Returns the storage class as written in the source.
void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
C Language Family Type Representation.
void prependScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
unsigned getBlockID() const
Decl - This represents one declaration (or definition), e.g.
Stmt * getHandlerBlock() const
CapturedStmt * getInnermostCapturedStmt()
Get innermost captured statement for the construct.
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Expr * getFalseExpr() const
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)
The base class of the type hierarchy.
Represents Objective-C's @throw statement.
Represents C++ object destructor generated from a call to delete.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents a call to a C++ constructor.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
DOTGraphTraits(bool isSimple=false)
unsigned IgnoreDefaultsWithCoveredEnums
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
A shortcut around virtual base initializers.
void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
unsigned succ_size() const
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
const char * getName() const
Describes how types, statements, expressions, and declarations should be printed. ...
Defines the Objective-C statement AST node classes.
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E)
A C++ throw-expression (C++ [except.throw]).
Represents an expression – generally a full-expression – that introduces cleanups to be run at the ...
static bool isAssignmentOp(Opcode Opc)
Defines the clang::Expr interface and subclasses for C++ expressions.
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const
printTerminatorJson - Pretty-prints the terminator in JSON format.
const Stmt * getSubStmt() const
Represents a function call that returns a C++ object by value.
LabelStmt - Represents a label, which has a substatement.
static TryResult bothKnownTrue(TryResult R1, TryResult R2)
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
DeclStmt * getConditionVariableDeclStmt()
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void setLoopTarget(const Stmt *loopTarget)
static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)
field_range fields() const
Represents a member of a struct/union/class.
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
Defines the ExceptionSpecificationType enumeration and various utility functions. ...
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
const CXXRecordDecl * getCXXRecordDecl() const
bool isReferenceType() const
const CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
void setTerminator(CFGTerminator Term)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static std::tuple< const Expr *, BinaryOperatorKind, const Expr * > tryNormalizeBinaryOperator(const BinaryOperator *B)
Tries to interpret a binary operator into Expr Op NumExpr form, if NumExpr is an integer literal or a...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
Represents Objective-C's @catch statement.
AdjacentBlocks::const_iterator const_succ_iterator
static bool isRelationalOp(Opcode Opc)
IndirectGotoStmt - This represents an indirect goto.
Describes an C or C++ initializer list.
Optional< Expr * > getArraySize()
std::string JsonFormat(StringRef RawSR, bool AddQuotes)
ForStmt - This represents a 'for (init;cond;inc)' stmt.
static bool isEqualityOp(Opcode Opc)
APValue Val
Val - This is the value the expression can be folded to.
LabelDecl * getDecl() const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
static bool IsIntegerLiteralConstantExpr(const Expr *E)
Returns true on constant values based around a single IntegerLiteral.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Expr * getInitializer()
The initializer of this new-expression.
static QualType getReferenceInitTemporaryType(const Expr *Init, bool *FoundMTE=nullptr)
Retrieve the type of the temporary object whose lifetime was extended by a local reference with the g...
A builtin binary operation expression such as "x + y" or "x <= y".
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
static bool areExprTypesCompatible(const Expr *E1, const Expr *E2)
For an expression x == Foo && x == Bar, this determines whether the Foo and Bar are either of the sam...
void print(raw_ostream &OS, const CFG *cfg, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFGBlock that outputs to an ostream.
bool isLinear() const
Returns true if the CFG has no branches.
Scope - A scope is a transient data structure that is used while parsing the program.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
const VarDecl * getVarDecl() const
CaseStmt - Represent a case statement.
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Represents binding an expression to a temporary.
CXXTemporary * getTemporary()
FieldDecl * getAnyMember() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
arg_iterator placement_arg_end()
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
CFGBlockListTy::const_iterator const_iterator
CXXCtorInitializer * getInitializer() const
void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, BumpVectorContext &C)
CompoundStmt - This represents a group of statements like { stmt stmt }.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a prototype with parameter type info, e.g.
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
static bool shouldAddCase(bool &switchExclusivelyCovered, const Expr::EvalResult *switchCond, const CaseStmt *CS, ASTContext &Ctx)
Represents a single basic block in a source-level CFG.
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
const VarDecl * getVarDecl() const
This represents one expression.
Defines the clang::LangOptions interface.
Stmt * getTerminatorCondition(bool StripParens=true)
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
void dumpToStream(llvm::raw_ostream &OS) const
const Expr * getLastCondition() const
Represents a C++ functional cast expression that builds a temporary object.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
VarDecl * getExceptionDecl() const
unsigned getNumInits() const
Represents C++ constructor call.
QualType getArgumentType() const
const CompoundStmt * getSynchBody() const
ElementList::const_iterator const_iterator
Represents Objective-C's @synchronized statement.
CXXTryStmt - A C++ try block, including all handlers.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
std::reverse_iterator< body_iterator > reverse_body_iterator
static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXCtorInitializer *I)
LabelDecl * getLabel() const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
An expression that sends a message to the given Objective-C object or class.
SwitchCase * getSwitchCaseList()
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
static bool CanThrow(Expr *E, ASTContext &Ctx)
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Represents C++ object destructor implicitly generated for base object in destructor.
Expr * getTrueExpr() const
The result type of a method or function.
QualType getDestroyedType() const
Retrieve the type being destroyed.
const Expr * getSubExpr() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
reverse_iterator rbegin()
DoStmt - This represents a 'do/while' stmt.
static const ConstructionContext * createFromLayers(BumpVectorContext &C, const ConstructionContextLayer *TopLayer)
Consume the construction context layer, together with its parent layers, and wrap it up into a comple...
std::reverse_iterator< decl_iterator > reverse_decl_iterator
static bool isCommaOp(Opcode Opc)
void appendStmt(Stmt *statement, BumpVectorContext &C)
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
This captures a statement into a function.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
virtual void compareBitwiseOr(const BinaryOperator *B)
Construction context can be seen as a linked list of multiple layers.
Encodes a location in the source.
unsigned getNumHandlers() const
Expr * getSubExpr() const
Represents a C++ temporary.
static bool isImmediateSinkBlock(const CFGBlock *Blk)
This is a basic class for representing single OpenMP executable directive.
CastKind getCastKind() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
void setLabel(Stmt *Statement)
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S)
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
bool PruneTriviallyFalseEdges
reverse_body_iterator body_rend()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
CFGTerminator Terminator
The terminator for a basic block that indicates the type of control-flow that occurs between a block ...
static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
A branch in control flow of destructors of temporaries.
decl_iterator decl_begin()
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
reverse_decl_iterator decl_rbegin()
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static bool isCXXRecordTypedCall(Expr *E)
Returns true when call expression CE needs to be represented by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
static QualType findBoundMemberType(const Expr *expr)
Given an expression of bound-member type, find the type of the member.
Expr ** getInits()
Retrieve the set of initializers.
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
static bool isLogicalOp(Opcode Opc)
static const Expr * tryTransformToIntOrEnumConstant(const Expr *E)
Helper for tryNormalizeBinaryOperator.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
DeclStmt * getConditionVariableDeclStmt()
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
bool isArgumentType() const
Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Defines various enumerations that describe declaration and type specifiers.
AddrLabelExpr - The GNU address of label extension, representing &&label.
ast_type_traits::DynTypedNode Node
pred_iterator pred_begin()
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
const VarDecl * getVarDecl() const
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
bool isKnownToHaveBooleanValue(bool Semantic=true) const
isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...
Dataflow Directional Tag Classes.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
EvalResult is a struct with detailed info about an evaluated expression.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
ArrayRef< Capture > captures() const
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
const VarDecl * getVarDecl() const
const Stmt * stripLabelLikeStatements() const
Strip off all label-like statements.
bool NE(InterpState &S, CodePtr OpPC)
static const VariableArrayType * FindVA(const Type *t)
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
const Expr * getInit() const
unsigned pred_size() const
A branch that corresponds to a statement in the code, such as an if-statement.
StmtClass getStmtClass() const
static StmtPrinterHelper * GraphHelper
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined...
bool isAnyDestructorNoReturn() const
Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn...
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
SEHExceptStmt * getExceptHandler() const
Returns 0 if not defined.
const Decl * getSingleDecl() const
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
Stmt * getTerminatorStmt()
const Expr * getSynchExpr() const
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
This class represents a potential adjacent block in the CFG.
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
Represents the point where the lifetime of an automatic object ends.
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
const CXXDeleteExpr * getDeleteExpr() const
Represents a single point (AST node) in the program that requires attention during construction of an...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
llvm::APInt getValue() const
Represents a __leave statement.
LabelDecl * getLabel() const
SwitchStmt - This represents a 'switch' stmt.
CFGBlock * getIndirectGotoBlock()
Iterator for iterating over Stmt * arrays that contain only T *.
Represents Objective-C's collection statement.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Represents a C++ base or member initializer.
size_t getIndexInCFG() const
reverse_decl_iterator decl_rend()
const ConstructionContextItem & getItem() const
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S)
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFG that outputs to an ostream.
CanQualType BoundMemberTy
static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC)
static const ConstructionContextLayer * create(BumpVectorContext &C, const ConstructionContextItem &Item, const ConstructionContextLayer *Parent=nullptr)
Represents a base class of a C++ class.
arg_iterator placement_arg_begin()
DeclStmt * getRangeStmt()
SEHFinallyStmt * getFinallyHandler() const
GotoStmt - This represents a direct goto.
A use of a default initializer in a constructor or in aggregate initialization.
unsigned IgnoreNullPredecessors
bool hasNoReturnElement() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
void setHasNoReturnElement()
const CXXNewExpr * getAllocatorExpr() const
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\, const ASTContext *Context=nullptr) const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
void viewCFG(const LangOptions &LO) const
Defines the clang::SourceLocation class and associated facilities.
ConstructionContext's subclasses describe different ways of constructing an object in C++...
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Represents a C++ struct/union/class.
ContinueStmt - This represents a continue.
reverse_body_iterator body_rbegin()
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Expr * getFilterExpr() const
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
CXXCatchStmt - This represents a C++ catch block.
bool LE(InterpState &S, CodePtr OpPC)
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr.type.conv]).
bool operator!=(CanQual< T > x, CanQual< U > y)
WhileStmt - This represents a 'while' stmt.
Represents a top-level expression in a basic block.
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Represents CFGBlock terminator statement.
CompoundStmt * getTryBlock()
bool AddRichCXXConstructors
Represents C++ object destructor implicitly generated for member object in destructor.
Represents Objective-C's @try ... @catch ... @finally statement.
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Full-expression storage duration (for temporaries).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
bool isBuiltinAssumeFalse(const ASTContext &Ctx) const
Return true if this is a call to __assume() or __builtin_assume() with a non-value-dependent constant...
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getQualifiedNameAsString() const
static Decl::Kind getKind(const Decl *D)
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument for this lambda expression...
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
BreakStmt - This represents a break.
Represents C++ base or member initializer from constructor's initialization list. ...
Expr * getSemanticExpr(unsigned index)
DeclStmt * getLoopVarStmt()
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
Represents a C array with a specified size that is not an integer-constant-expression.
CFGBlock * createBlock()
Create a new block in the CFG.
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
CFGTerminator getTerminator() const
DeclStmt * getBeginStmt()
bool isFunctionPointerType() const
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue...
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const LangOptions & getLangOpts() const
Represents Objective-C's @autoreleasepool Statement.
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
CompoundStmt * getTryBlock() const
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Defines enum values for all the target-independent builtin functions.
CompoundStmt * getBlock() const
bool Sub(InterpState &S, CodePtr OpPC)
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point...
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt...
QualType getType() const
Retrieves the type of the base class.
Represents the point where a loop ends.