A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://clang.llvm.org/doxygen/CFG_8cpp_source.html below:

clang: lib/Analysis/CFG.cpp Source File

39#include "llvm/ADT/APInt.h" 40#include "llvm/ADT/APSInt.h" 41#include "llvm/ADT/ArrayRef.h" 42#include "llvm/ADT/DenseMap.h" 43#include "llvm/ADT/STLExtras.h" 44#include "llvm/ADT/SetVector.h" 45#include "llvm/ADT/SmallPtrSet.h" 46#include "llvm/ADT/SmallVector.h" 47#include "llvm/Support/Allocator.h" 48#include "llvm/Support/Casting.h" 49#include "llvm/Support/Compiler.h" 50#include "llvm/Support/DOTGraphTraits.h" 51#include "llvm/Support/ErrorHandling.h" 52#include "llvm/Support/Format.h" 53#include "llvm/Support/GraphWriter.h" 54#include "llvm/Support/SaveAndRestore.h" 55#include "llvm/Support/raw_ostream.h" 64using namespace clang

;

67 if

(

VarDecl

*VD = dyn_cast<VarDecl>(

D

))

68 if

(

Expr

*Ex = VD->getInit())

69 return

Ex->getSourceRange().getEnd();

84 if

(

const auto

*CE = dyn_cast<CastExpr>(

E

)) {

85 if

(CE->getCastKind() != CK_IntegralCast)

91 if

(

const auto

*UO = dyn_cast<UnaryOperator>(

E

)) {

92 if

(UO->getOpcode() != UO_Minus)

97 return

isa<IntegerLiteral>(

E

);

108 return

isa<EnumConstantDecl>(DR->getDecl()) ? DR :

nullptr

;

117static

std::tuple<const Expr *, BinaryOperatorKind, const Expr *>

124 if

(Constant ==

nullptr

) {

128 else if

(Op == BO_GE)

130 else if

(Op == BO_LT)

132 else if

(Op == BO_LE)

135

MaybeDecl = B->

getRHS

();

139 return

std::make_tuple(MaybeDecl, Op, Constant);

151 if

(isa<DeclRefExpr>(E1) != isa<DeclRefExpr>(E2))

155 if

(!isa<DeclRefExpr>(E1))

160

assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));

161 auto

*Decl1 = cast<DeclRefExpr>(E1)->getDecl();

162 auto

*Decl2 = cast<DeclRefExpr>(E2)->getDecl();

164

assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));

168

assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));

190 enum Kind

{ NotAlwaysAdd = 0, AlwaysAdd = 1 };

192

AddStmtChoice(Kind a_kind = NotAlwaysAdd) :

kind

(a_kind) {}

194 bool

alwaysAdd(CFGBuilder &builder,

199

AddStmtChoice withAlwaysAdd(

bool

alwaysAdd)

const

{

200 return

AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);

234 class

const_iterator {

235 const

LocalScope*

Scope

=

nullptr

;

239 unsigned

VarIter = 0;

245

const_iterator() =

default

;

249

const_iterator(

const

LocalScope& S,

unsigned

I)

250

:

Scope

(&S), VarIter(I) {

253 if

(VarIter == 0 &&

Scope

)

254

*

this

=

Scope

->Prev;

257 VarDecl

*

const

* operator->()

const

{

258

assert(

Scope

&&

"Dereferencing invalid iterator is not allowed"

);

259

assert(VarIter != 0 &&

"Iterator has invalid value of VarIter member"

);

260 return

&

Scope

->Vars[VarIter - 1];

263 const VarDecl

*getFirstVarInScope()

const

{

264

assert(

Scope

&&

"Dereferencing invalid iterator is not allowed"

);

265

assert(VarIter != 0 &&

"Iterator has invalid value of VarIter member"

);

266 return Scope

->Vars[0];

270 return

*this->operator->();

273

const_iterator &operator++() {

277

assert(VarIter != 0 &&

"Iterator has invalid value of VarIter member"

);

280

*

this

=

Scope

->Prev;

283

const_iterator operator++(

int

) {

284

const_iterator

P

= *

this

;

289 bool operator==

(

const

const_iterator &rhs)

const

{

290 return Scope

== rhs.

Scope

&& VarIter == rhs.VarIter;

292 bool operator!=

(

const

const_iterator &rhs)

const

{

293 return

!(*

this

== rhs);

296 explicit operator bool

()

const

{

297 return

*

this

!= const_iterator();

301

const_iterator shared_parent(const_iterator L);

302 bool

pointsToFirstDeclaredVar() {

return

VarIter == 1; }

303 bool

inSameLocalScope(const_iterator rhs) {

return Scope

== rhs.

Scope

; }

310

AutomaticVarsTy Vars;

319

: ctx(

std

::move(ctx)), Vars(this->ctx, 4), Prev(

P

) {}

322

const_iterator begin()

const

{

return

const_iterator(*

this

, Vars.size()); }

325

Vars.push_back(VD, ctx);

334int

LocalScope::const_iterator::distance(LocalScope::const_iterator L) {

336

const_iterator F = *

this

;

337 while

(F.Scope != L.Scope) {

338

assert(F != const_iterator() &&

339 "L iterator is not reachable from F iterator."

);

343 D

+= F.VarIter - L.VarIter;

351

LocalScope::const_iterator

352

LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {

355 if

((*

this

== const_iterator()) || (L == const_iterator())) {

356 return

const_iterator();

359

const_iterator F = *

this

;

360 if

(F.inSameLocalScope(L)) {

362

F.VarIter = std::min(F.VarIter, L.VarIter);

366

llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;

368

ScopesOfL.try_emplace(L.Scope, L.VarIter);

369 if

(L == const_iterator())

375 if

(

auto

LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {

377

F.VarIter = std::min(F.VarIter, LIt->getSecond());

380

assert(F != const_iterator() &&

381 "L iterator is not reachable from F iterator."

);

391struct

BlockScopePosPair {

393

LocalScope::const_iterator scopePosition;

395

BlockScopePosPair() =

default

;

396

BlockScopePosPair(

CFGBlock

*

b

, LocalScope::const_iterator scopePos)

397

: block(

b

), scopePosition(scopePos) {}

408

TryResult() =

default

;

409

TryResult(

bool b

) :

X

(

b

? 1 : 0) {}

411 bool

isTrue()

const

{

return X

== 1; }

412 bool

isFalse()

const

{

return X

== 0; }

413 bool

isKnown()

const

{

return X

>= 0; }

424 if

(!R1.isKnown() || !R2.isKnown())

426 return

TryResult(R1.isTrue() && R2.isTrue());

431class

reverse_children {

436

reverse_children(

Stmt

*S);

440

iterator begin()

const

{

return

children.rbegin(); }

441

iterator end()

const

{

return

children.rend(); }

446

reverse_children::reverse_children(

Stmt

*S) {

447 if

(

CallExpr

*CE = dyn_cast<CallExpr>(S)) {

448

children = CE->getRawSubExprs();

451 switch

(S->getStmtClass()) {

453 case

Stmt::InitListExprClass: {

464

llvm::append_range(childrenBuf, S->children());

467

children = childrenBuf;

486 using

JumpTarget = BlockScopePosPair;

487 using

JumpSource = BlockScopePosPair;

490

std::unique_ptr<CFG> cfg;

498

JumpTarget ContinueJumpTarget;

499

JumpTarget BreakJumpTarget;

500

JumpTarget SEHLeaveJumpTarget;

501 CFGBlock

*SwitchTerminatedBlock =

nullptr

;

502 CFGBlock

*DefaultCaseBlock =

nullptr

;

508 CFGBlock

*TryTerminatedBlock =

nullptr

;

511

LocalScope::const_iterator ScopePos;

514 using

LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;

519 using

BackpatchBlocksTy = std::vector<JumpSource>;

520

BackpatchBlocksTy BackpatchBlocks;

524

LabelSetTy AddressTakenLabels;

529

llvm::DenseMap<Expr *, const ConstructionContextLayer *>

530

ConstructionContextMap;

532 bool

badCFG =

false

;

536 bool

switchExclusivelyCovered =

false

;

539

CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry =

nullptr

;

540 const Stmt

*lastLookup =

nullptr

;

544 using

CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;

545

CachedBoolEvalsTy CachedBoolEvals;

550

: Context(astContext), cfg(new

CFG

()), BuildOpts(buildOpts) {}

553

std::unique_ptr<CFG> buildCFG(

const Decl

*

D

,

Stmt

*Statement);

555 bool

alwaysAdd(

const Stmt

*

stmt

);

590

AddStmtChoice asc,

bool

ExternallyDestructed);

602

std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(

BinaryOperator

*B,

632 CFGBlock

*Visit(

Stmt

*S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,

633 bool

ExternallyDestructed =

false

);

642 if

(ScopePos && (VD == ScopePos.getFirstVarInScope()))

643

appendScopeBegin(B, VD, S);

674 struct

TempDtorContext {

675

TempDtorContext() =

default

;

676

TempDtorContext(TryResult KnownExecuted)

677

: IsConditional(

true

), KnownExecuted(KnownExecuted) {}

685 bool

needsTempDtorBranch()

const

{

686 return

IsConditional && !TerminatorExpr;

696 const bool

IsConditional =

false

;

697 const

TryResult KnownExecuted =

true

;

704 CFGBlock

*VisitForTemporaryDtors(

Stmt

*

E

,

bool

ExternallyDestructed,

705

TempDtorContext &Context);

706 CFGBlock

*VisitChildrenForTemporaryDtors(

Stmt

*

E

,

bool

ExternallyDestructed,

707

TempDtorContext &Context);

709 bool

ExternallyDestructed,

710

TempDtorContext &Context);

711 CFGBlock

*VisitCXXBindTemporaryExprForTemporaryDtors(

713 CFGBlock

*VisitConditionalOperatorForTemporaryDtors(

715

TempDtorContext &Context);

716 void

InsertTempDtorDecisionBlock(

const

TempDtorContext &Context,

741 template

<

typename

CallLikeExpr,

742 typename

= std::enable_if_t<

743

std::is_base_of_v<CallExpr, CallLikeExpr> ||

744

std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||

745

std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>

746 void

findConstructionContextsForArguments(CallLikeExpr *

E

) {

747 for

(

unsigned

i = 0, e =

E

->getNumArgs(); i != e; ++i) {

748 Expr

*Arg =

E

->getArg(i);

750

findConstructionContexts(

760 void

cleanupConstructionContext(

Expr

*

E

);

762 void

autoCreateBlock() {

if

(!Block)

Block

= createBlock(); }

764 CFGBlock

*createBlock(

bool

add_successor =

true

);

768 return

Visit(S, AddStmtChoice::AlwaysAdd);

772 void

addLoopExit(

const Stmt

*LoopStmt);

773 void

addAutomaticObjHandling(LocalScope::const_iterator B,

774

LocalScope::const_iterator

E

,

Stmt

*S);

775 void

addAutomaticObjDestruction(LocalScope::const_iterator B,

776

LocalScope::const_iterator

E

,

Stmt

*S);

777 void

addScopeExitHandling(LocalScope::const_iterator B,

778

LocalScope::const_iterator

E

,

Stmt

*S);

780 void

addScopeChangesHandling(LocalScope::const_iterator SrcPos,

781

LocalScope::const_iterator DstPos,

783 CFGBlock

*createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,

785

LocalScope::const_iterator DstPost,

789

LocalScope* createOrReuseLocalScope(LocalScope*

Scope

);

791 void

addLocalScopeForStmt(

Stmt

*S);

792

LocalScope* addLocalScopeForDeclStmt(

DeclStmt

*DS,

793

LocalScope*

Scope

=

nullptr

);

794

LocalScope* addLocalScopeForVarDecl(

VarDecl

*VD, LocalScope*

Scope

=

nullptr

);

796 void

addLocalScopeAndDtors(

Stmt

*S);

806

cleanupConstructionContext(

E

);

814 if

(alwaysAdd(S) && cachedEntry)

815

cachedEntry->second = B;

818

assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);

819

B->

appendStmt

(

const_cast<Stmt

*

>

(S), cfg->getBumpVectorContext());

824 if

(

C

&&

C

->isNoReturn())

825 Block

= createNoReturnBlock();

830

retrieveAndCleanupConstructionContext(CE)) {

840 if

(alwaysAdd(CE) && cachedEntry)

841

cachedEntry->second = B;

844

retrieveAndCleanupConstructionContext(CE)) {

850

B->

appendStmt

(CE, cfg->getBumpVectorContext());

870 if

(alwaysAdd(ME) && cachedEntry)

871

cachedEntry->second = B;

874

retrieveAndCleanupConstructionContext(ME)) {

880

cfg->getBumpVectorContext());

899 void

appendLoopExit(

CFGBlock

*B,

const Stmt

*LoopStmt) {

909

cfg->getBumpVectorContext());

916

cfg->getBumpVectorContext());

932

TryResult checkIncorrectRelationalOperator(

const BinaryOperator

*B) {

936 const IntegerLiteral

*IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);

937 const Expr

*BoolExpr = RHSExpr;

938 bool

IntFirst =

true

;

940

IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);

948

llvm::APInt IntValue = IntLiteral->

getValue

();

949 if

((IntValue == 1) || (IntValue == 0))

953

!IntValue.isNegative();

956 if

(Bok == BO_GT || Bok == BO_GE) {

959 return

TryResult(IntFirst == IntLarger);

963 return

TryResult(IntFirst != IntLarger);

971

TryResult checkIncorrectEqualityOperator(

const BinaryOperator

*B) {

975

std::optional<llvm::APInt> IntLiteral1 =

976

getIntegerLiteralSubexpressionValue(LHSExpr);

977 const Expr

*BoolExpr = RHSExpr;

980

IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);

988 if

(BitOp && (BitOp->

getOpcode

() == BO_And ||

993

std::optional<llvm::APInt> IntLiteral2 =

994

getIntegerLiteralSubexpressionValue(LHSExpr2);

997

IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);

1003

(*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||

1005

(*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {

1009 return

TryResult(B->

getOpcode

() != BO_EQ);

1012 if

((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {

1015 return

TryResult(B->

getOpcode

() != BO_EQ);

1027

std::optional<llvm::APInt>

1028

getIntegerLiteralSubexpressionValue(

const Expr

*

E

) {

1031 if

(

const auto

*UnOp = dyn_cast<UnaryOperator>(

E

->

IgnoreParens

())) {

1036 if

(

const auto

*IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {

1041 switch

(UnOp->getOpcode()) {

1051

assert(

false

&&

"Unexpected unary operator!"

);

1052 return

std::nullopt;

1055

}

else if

(

const auto

*IntLiteral =

1059 return

std::nullopt;

1063 const

llvm::APSInt &Value1,

1064 const

llvm::APSInt &Value2) {

1065

assert(Value1.isSigned() == Value2.isSigned());

1070 return

TryResult(Value1 == Value2);

1072 return

TryResult(Value1 != Value2);

1074 return

TryResult(Value1 < Value2);

1076 return

TryResult(Value1 <= Value2);

1078 return

TryResult(Value1 > Value2);

1080 return

TryResult(Value1 >= Value2);

1091

TryResult checkIncorrectLogicOperator(

const BinaryOperator

*B) {

1096 auto

CheckLogicalOpWithNegatedVariable = [

this

, B](

const Expr

*E1,

1098 if

(

const auto

*Negate = dyn_cast<UnaryOperator>(E1)) {

1099 if

(Negate->getOpcode() == UO_LNot &&

1101 bool

AlwaysTrue = B->

getOpcode

() == BO_LOr;

1104 return

TryResult(AlwaysTrue);

1110

TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);

1111 if

(Result.isKnown())

1113

Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);

1114 if

(Result.isKnown())

1117 const auto

*LHS = dyn_cast<BinaryOperator>(LHSExpr);

1118 const auto

*RHS = dyn_cast<BinaryOperator>(RHSExpr);

1122 if

(!LHS->isComparisonOp() || !RHS->isComparisonOp())

1125 const Expr

*DeclExpr1;

1126 const Expr

*NumExpr1;

1130 if

(!DeclExpr1 || !NumExpr1)

1133 const Expr

*DeclExpr2;

1134 const Expr

*NumExpr2;

1138 if

(!DeclExpr2 || !NumExpr2)

1155

llvm::APSInt L1 = L1Result.

Val

.

getInt

();

1156

llvm::APSInt L2 = L2Result.

Val

.

getInt

();

1159 if

(L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())

1164 const

llvm::APSInt Values[] = {

1166

llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),

1170

((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),

1175

llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),

1184 bool

AlwaysTrue =

true

, AlwaysFalse =

true

;

1187 bool

LHSAlwaysTrue =

true

, LHSAlwaysFalse =

true

;

1188 bool

RHSAlwaysTrue =

true

, RHSAlwaysFalse =

true

;

1189 for

(

const

llvm::APSInt &

Value

: Values) {

1190

TryResult Res1, Res2;

1191

Res1 = analyzeLogicOperatorCondition(BO1,

Value

, L1);

1192

Res2 = analyzeLogicOperatorCondition(BO2,

Value

, L2);

1194 if

(!Res1.isKnown() || !Res2.isKnown())

1198

AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());

1199

AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());

1201

AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());

1202

AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());

1205

LHSAlwaysTrue &= Res1.isTrue();

1206

LHSAlwaysFalse &= Res1.isFalse();

1207

RHSAlwaysTrue &= Res2.isTrue();

1208

RHSAlwaysFalse &= Res2.isFalse();

1211 if

(AlwaysTrue || AlwaysFalse) {

1212 if

(!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&

1213

!RHSAlwaysFalse && BuildOpts.

Observer

)

1215 return

TryResult(AlwaysTrue);

1221

TryResult checkIncorrectBitwiseOrOperator(

const BinaryOperator

*B) {

1222 const Expr

*LHSConstant =

1224 const Expr

*RHSConstant =

1227 if

((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))

1230 const Expr

*Constant = LHSConstant ? LHSConstant : RHSConstant;

1236 if

(Result.Val.getInt() == 0)

1242 return

TryResult(

true

);

1249 return

!S->isTypeDependent() &&

1250

!S->isValueDependent() &&

1251

S->EvaluateAsRValue(outResult, *Context);

1256

TryResult tryEvaluateBool(

Expr

*S) {

1258

S->isTypeDependent() || S->isValueDependent())

1262 if

(Bop->isLogicalOp() || Bop->isEqualityOp()) {

1264

CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);

1265 if

(I != CachedBoolEvals.end())

1269

TryResult Result = evaluateAsBooleanConditionNoCache(S);

1270

CachedBoolEvals[S] = Result;

1274 switch

(Bop->getOpcode()) {

1283 if

(Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {

1284

llvm::APSInt IntVal = LHSResult.

Val

.

getInt

();

1285 if

(!IntVal.getBoolValue()) {

1286 return

TryResult(

false

);

1290 if

(Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {

1291

llvm::APSInt IntVal = RHSResult.

Val

.

getInt

();

1292 if

(!IntVal.getBoolValue()) {

1293 return

TryResult(

false

);

1302 return

evaluateAsBooleanConditionNoCache(S);

1306

TryResult evaluateAsBooleanConditionNoCache(

Expr

*

E

) {

1308 if

(Bop->isLogicalOp()) {

1309

TryResult LHS = tryEvaluateBool(Bop->getLHS());

1310 if

(LHS.isKnown()) {

1313 if

(LHS.isTrue() == (Bop->getOpcode() == BO_LOr))

1314 return

LHS.isTrue();

1316

TryResult RHS = tryEvaluateBool(Bop->getRHS());

1317 if

(RHS.isKnown()) {

1318 if

(Bop->getOpcode() == BO_LOr)

1319 return

LHS.isTrue() || RHS.isTrue();

1321 return

LHS.isTrue() && RHS.isTrue();

1324

TryResult RHS = tryEvaluateBool(Bop->getRHS());

1325 if

(RHS.isKnown()) {

1328 if

(RHS.isTrue() == (Bop->getOpcode() == BO_LOr))

1329 return

RHS.isTrue();

1331

TryResult BopRes = checkIncorrectLogicOperator(Bop);

1332 if

(BopRes.isKnown())

1333 return

BopRes.isTrue();

1338

}

else if

(Bop->isEqualityOp()) {

1339

TryResult BopRes = checkIncorrectEqualityOperator(Bop);

1340 if

(BopRes.isKnown())

1341 return

BopRes.isTrue();

1342

}

else if

(Bop->isRelationalOp()) {

1343

TryResult BopRes = checkIncorrectRelationalOperator(Bop);

1344 if

(BopRes.isKnown())

1345 return

BopRes.isTrue();

1346

}

else if

(Bop->getOpcode() == BO_Or) {

1347

TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);

1348 if

(BopRes.isKnown())

1349 return

BopRes.isTrue();

1360 bool

hasTrivialDestructor(

const VarDecl

*VD)

const

;

1361 bool

needsAutomaticDestruction(

const VarDecl

*VD)

const

;

1372 while

(

const auto

*

E

= dyn_cast<ArrayInitLoopExpr>(AILEInit))

1373

AILEInit =

E

->getSubExpr();

1378inline bool

AddStmtChoice::alwaysAdd(CFGBuilder &builder,

1380 return

builder.alwaysAdd(

stmt

) || kind == AlwaysAdd;

1383bool

CFGBuilder::alwaysAdd(

const Stmt

*

stmt

) {

1389 if

(lastLookup ==

stmt

) {

1391

assert(cachedEntry->first ==

stmt

);

1404

assert(!cachedEntry);

1408

CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(

stmt

);

1409 if

(itr == fb->end()) {

1410

cachedEntry =

nullptr

;

1414

cachedEntry = &*itr;

1421 while

(

const ArrayType

*vt = dyn_cast<ArrayType>(t)) {

1423 if

(vat->getSizeExpr())

1426

t = vt->getElementType().getTypePtr();

1432void

CFGBuilder::consumeConstructionContext(

1434

assert((isa<CXXConstructExpr>(

E

) || isa<CallExpr>(

E

) ||

1435

isa<ObjCMessageExpr>(

E

)) &&

"Expression cannot construct an object!"

);

1437

ConstructionContextMap.lookup(

E

)) {

1438

(void)PreviouslyStoredLayer;

1441

assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&

1442 "Already within a different construction context!"

);

1444

ConstructionContextMap[

E

] = Layer;

1448void

CFGBuilder::findConstructionContexts(

1461 switch

(Child->getStmtClass()) {

1462 case

Stmt::CXXConstructExprClass:

1463 case

Stmt::CXXTemporaryObjectExprClass: {

1465 auto

*CE = cast<CXXConstructExpr>(Child);

1467

findConstructionContexts(withExtraLayer(CE), CE->

getArg

(0));

1470

consumeConstructionContext(Layer, CE);

1476 case

Stmt::CallExprClass:

1477 case

Stmt::CXXMemberCallExprClass:

1478 case

Stmt::CXXOperatorCallExprClass:

1479 case

Stmt::UserDefinedLiteralClass:

1480 case

Stmt::ObjCMessageExprClass: {

1481 auto

*

E

= cast<Expr>(Child);

1483

consumeConstructionContext(Layer,

E

);

1486 case

Stmt::ExprWithCleanupsClass: {

1487 auto

*Cleanups = cast<ExprWithCleanups>(Child);

1488

findConstructionContexts(Layer, Cleanups->getSubExpr());

1491 case

Stmt::CXXFunctionalCastExprClass: {

1492 auto

*

Cast

= cast<CXXFunctionalCastExpr>(Child);

1493

findConstructionContexts(Layer,

Cast

->getSubExpr());

1496 case

Stmt::ImplicitCastExprClass: {

1497 auto

*

Cast

= cast<ImplicitCastExpr>(Child);

1499 switch

(

Cast

->getCastKind()) {

1501 case

CK_ConstructorConversion:

1502

findConstructionContexts(Layer,

Cast

->getSubExpr());

1509 case

Stmt::CXXBindTemporaryExprClass: {

1510 auto

*BTE = cast<CXXBindTemporaryExpr>(Child);

1511

findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());

1514 case

Stmt::MaterializeTemporaryExprClass: {

1521 auto

*MTE = cast<MaterializeTemporaryExpr>(Child);

1522

findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());

1526 case

Stmt::ConditionalOperatorClass: {

1527 auto

*CO = cast<ConditionalOperator>(Child);

1534

assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||

1538

findConstructionContexts(Layer, CO->getLHS());

1539

findConstructionContexts(Layer, CO->getRHS());

1542 case

Stmt::InitListExprClass: {

1543 auto

*ILE = cast<InitListExpr>(Child);

1544 if

(ILE->isTransparent()) {

1545

findConstructionContexts(Layer, ILE->getInit(0));

1551 case

Stmt::ParenExprClass: {

1554 auto

*PE = cast<ParenExpr>(Child);

1555

findConstructionContexts(Layer, PE->getSubExpr());

1563void

CFGBuilder::cleanupConstructionContext(

Expr

*

E

) {

1565 "We should not be managing construction contexts!"

);

1566

assert(ConstructionContextMap.count(

E

) &&

1567 "Cannot exit construction context without the context!"

);

1568

ConstructionContextMap.erase(

E

);

1576

std::unique_ptr<CFG> CFGBuilder::buildCFG(

const Decl

*

D

,

Stmt

*Statement) {

1584

Succ = createBlock();

1585

assert(Succ == &cfg->getExit());

1590

addImplicitDtorsForDestructor(DD);

1610 if

(

const auto

*CD = dyn_cast_or_null<CXXConstructorDecl>(

D

)) {

1612 for

(

auto

*I : llvm::reverse(CD->inits())) {

1614

I->isBaseInitializer() && I->isBaseVirtual()) {

1618

VBaseSucc = Succ = B ? B : &cfg->getExit();

1619 Block

= createBlock();

1621

B = addInitializer(I);

1631

addSuccessor(B,

Block

,

true

);

1640 for

(BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),

1641 E

= BackpatchBlocks.end(); I !=

E

; ++I ) {

1645

LabelMapTy::iterator LI = LabelMap.find(G->getLabel());

1648 if

(LI == LabelMap.end())

1650

JumpTarget JT = LI->second;

1652 CFGBlock

*SuccBlk = createScopeChangesHandlingBlock(

1653

I->scopePosition, B, JT.scopePosition, JT.block);

1654

addSuccessor(B, SuccBlk);

1655

}

else if

(

auto

*G = dyn_cast<GCCAsmStmt>(B->

getTerminator

())) {

1656 CFGBlock

*Successor = (I+1)->block;

1657 for

(

auto

*L : G->labels()) {

1658

LabelMapTy::iterator LI = LabelMap.find(L->getLabel());

1661 if

(LI == LabelMap.end())

1663

JumpTarget JT = LI->second;

1665 if

(JT.block == Successor)

1667

addSuccessor(B, JT.block);

1674 if

(

CFGBlock

*B = cfg->getIndirectGotoBlock())

1675 for

(LabelSetTy::iterator I = AddressTakenLabels.begin(),

1676 E

= AddressTakenLabels.end(); I !=

E

; ++I ) {

1678

LabelMapTy::iterator LI = LabelMap.find(*I);

1682 if

(LI == LabelMap.end())

continue

;

1684

addSuccessor(B, LI->second.block);

1688

cfg->setEntry(createBlock());

1691

assert(ConstructionContextMap.empty() &&

1692 "Not all construction contexts were cleaned up!"

);

1694 return

std::move(cfg);

1699CFGBlock

*CFGBuilder::createBlock(

bool

add_successor) {

1701 if

(add_successor && Succ)

1702

addSuccessor(B, Succ);

1709CFGBlock

*CFGBuilder::createNoReturnBlock() {

1710 CFGBlock

*B = createBlock(

false

);

1712

addSuccessor(B, &cfg->getExit(), Succ);

1721 bool

HasTemporaries =

false

;

1727

HasTemporaries = isa<ExprWithCleanups>(

Init

);

1731

TempDtorContext Context;

1732

VisitForTemporaryDtors(cast<ExprWithCleanups>(

Init

)->getSubExpr(),

1738

appendInitializer(

Block

, I);

1744

dyn_cast<ArrayInitLoopExpr>(

Init

));

1746

findConstructionContexts(

1748

AILEInit ? AILEInit :

Init

);

1750 if

(HasTemporaries) {

1753 return

Visit(cast<ExprWithCleanups>(

Init

)->getSubExpr());

1768 return

Visit(

Init

);

1777 bool

*FoundMTE =

nullptr

) {

1784 Init

= EWC->getSubExpr();

1790

= dyn_cast<MaterializeTemporaryExpr>(

Init

)) {

1791 Init

= MTE->getSubExpr();

1798 const Expr

*SkippedInit =

Init

->skipRValueSubobjectAdjustments();

1799 if

(SkippedInit !=

Init

) {

1807 return Init

->getType();

1812void

CFGBuilder::addLoopExit(

const Stmt

*LoopStmt){

1816

appendLoopExit(

Block

, LoopStmt);

1824void

CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,

1825

LocalScope::const_iterator

E

,

1835 if

(B.inSameLocalScope(

E

)) {

1836

addAutomaticObjDestruction(B,

E

, S);

1842

LocalScopeEndMarkers.push_back(B);

1843 for

(LocalScope::const_iterator I = B; I !=

E

; ++I) {

1844 if

(!I.inSameLocalScope(LocalScopeEndMarkers.back()))

1845

LocalScopeEndMarkers.push_back(I);

1847

LocalScopeEndMarkers.push_back(

E

);

1851

std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());

1853

llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));

1854 for

(

auto

[

E

, B] : Pairwise) {

1855 if

(!B.inSameLocalScope(

E

))

1856

addScopeExitHandling(B,

E

, S);

1857

addAutomaticObjDestruction(B,

E

, S);

1864void

CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,

1865

LocalScope::const_iterator

E

,

1874

DeclsNeedDestruction.reserve(B.distance(

E

));

1876 for

(

VarDecl

*

D

: llvm::make_range(B,

E

))

1877 if

(needsAutomaticDestruction(

D

))

1878

DeclsNeedDestruction.push_back(

D

);

1880 for

(

VarDecl

*VD : llvm::reverse(DeclsNeedDestruction)) {

1893 Block

= createNoReturnBlock();

1902

appendLifetimeEnds(

Block

, VD, S);

1904

appendAutomaticObjDtor(

Block

, VD, S);

1905 if

(VD->

hasAttr

<CleanupAttr>())

1906

appendCleanupFunction(

Block

, VD);

1915void

CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,

1916

LocalScope::const_iterator

E

,

Stmt

*S) {

1917

assert(!B.inSameLocalScope(

E

));

1923

appendScopeEnd(

Block

, B.getFirstVarInScope(), S);

1931

DeclsTrivial.reserve(B.distance(

E

));

1936 for

(

VarDecl

*

D

: llvm::make_range(B,

E

))

1937 if

(!needsAutomaticDestruction(

D

))

1938

DeclsTrivial.push_back(

D

);

1940 if

(DeclsTrivial.empty())

1944 for

(

VarDecl

*VD : llvm::reverse(DeclsTrivial))

1945

appendLifetimeEnds(

Block

, VD, S);

1953void

CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,

1954

LocalScope::const_iterator DstPos,

1956

assert(

Block

&&

"Source block should be always crated"

);

1962 if

(SrcPos == DstPos)

1967

LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);

1970 if

(BuildOpts.

AddScopes

&& !DstPos.inSameLocalScope(BasePos)) {

1971 for

(LocalScope::const_iterator I = DstPos; I != BasePos; ++I)

1972 if

(I.pointsToFirstDeclaredVar())

1973

appendScopeBegin(

Block

, *I, S);

1978

addAutomaticObjHandling(SrcPos, BasePos, S);

1986CFGBlock

*CFGBuilder::createScopeChangesHandlingBlock(

1987

LocalScope::const_iterator SrcPos,

CFGBlock

*SrcBlk,

1988

LocalScope::const_iterator DstPos,

CFGBlock

*DstBlk) {

1989 if

(SrcPos == DstPos)

1993

(!BuildOpts.

AddScopes

|| SrcPos.inSameLocalScope(DstPos)))

2001 Block

= createBlock(

false

);

2004

addSuccessor(

Block

, DstBlk);

2009

assert(

Block

&&

"There should be at least one scope changing Block"

);

2017 "Can be called only when dtors should be added"

);

2021 for

(

const auto

&VI : RD->

vbases

()) {

2025 const CXXRecordDecl

*CD = VI.getType()->getAsCXXRecordDecl();

2028

appendBaseDtor(

Block

, &VI);

2033 for

(

const auto

&BI : RD->

bases

()) {

2034 if

(!BI.isVirtual()) {

2035 const CXXRecordDecl

*CD = BI.getType()->getAsCXXRecordDecl();

2038

appendBaseDtor(

Block

, &BI);

2044 for

(

auto

*FI : RD->

fields

()) {

2049 if

(AT->isZeroSize())

2051

QT = AT->getElementType();

2057

appendMemberDtor(

Block

, FI);

2064

LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope*

Scope

) {

2067

llvm::BumpPtrAllocator &alloc = cfg->getAllocator();

2073void

CFGBuilder::addLocalScopeForStmt(

Stmt

*S) {

2078

LocalScope *

Scope

=

nullptr

;

2082 for

(

auto

*BI : CS->body()) {

2084 if

(

DeclStmt

*DS = dyn_cast<DeclStmt>(SI))

2085 Scope

= addLocalScopeForDeclStmt(DS,

Scope

);

2092 if

(

DeclStmt

*DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))

2093

addLocalScopeForDeclStmt(DS);

2098

LocalScope* CFGBuilder::addLocalScopeForDeclStmt(

DeclStmt

*DS,

2099

LocalScope*

Scope

) {

2104 for

(

auto

*DI : DS->

decls

())

2105 if

(

VarDecl

*VD = dyn_cast<VarDecl>(DI))

2110bool

CFGBuilder::needsAutomaticDestruction(

const VarDecl

*VD)

const

{

2111 return

!hasTrivialDestructor(VD) || VD->

hasAttr

<CleanupAttr>();

2114bool

CFGBuilder::hasTrivialDestructor(

const VarDecl

*VD)

const

{

2135 bool

FoundMTE =

false

;

2143 if

(AT->isZeroSize())

2145

QT = AT->getElementType();

2157

LocalScope* CFGBuilder::addLocalScopeForVarDecl(

VarDecl

*VD,

2158

LocalScope*

Scope

) {

2168

!needsAutomaticDestruction(VD)) {

2176

ScopePos =

Scope

->begin();

2182void

CFGBuilder::addLocalScopeAndDtors(

Stmt

*S) {

2183

LocalScope::const_iterator scopeBeginPos = ScopePos;

2184

addLocalScopeForStmt(S);

2185

addAutomaticObjHandling(ScopePos, scopeBeginPos, S);

2191CFGBlock

*CFGBuilder::Visit(

Stmt

* S, AddStmtChoice asc,

2192 bool

ExternallyDestructed) {

2198 if

(

Expr

*

E

= dyn_cast<Expr>(S))

2202 if

(

auto

*

D

= dyn_cast<OMPExecutableDirective>(S))

2203 return

VisitOMPExecutableDirective(

D

, asc);

2205 switch

(S->getStmtClass()) {

2207 return

VisitStmt(S, asc);

2209 case

Stmt::ImplicitValueInitExprClass:

2212 return

VisitStmt(S, asc);

2214 case

Stmt::InitListExprClass:

2215 return

VisitInitListExpr(cast<InitListExpr>(S), asc);

2217 case

Stmt::AttributedStmtClass:

2218 return

VisitAttributedStmt(cast<AttributedStmt>(S), asc);

2220 case

Stmt::AddrLabelExprClass:

2221 return

VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);

2223 case

Stmt::BinaryConditionalOperatorClass:

2224 return

VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);

2226 case

Stmt::BinaryOperatorClass:

2227 return

VisitBinaryOperator(cast<BinaryOperator>(S), asc);

2229 case

Stmt::BlockExprClass:

2230 return

VisitBlockExpr(cast<BlockExpr>(S), asc);

2232 case

Stmt::BreakStmtClass:

2233 return

VisitBreakStmt(cast<BreakStmt>(S));

2235 case

Stmt::CallExprClass:

2236 case

Stmt::CXXOperatorCallExprClass:

2237 case

Stmt::CXXMemberCallExprClass:

2238 case

Stmt::UserDefinedLiteralClass:

2239 return

VisitCallExpr(cast<CallExpr>(S), asc);

2241 case

Stmt::CaseStmtClass:

2242 return

VisitCaseStmt(cast<CaseStmt>(S));

2244 case

Stmt::ChooseExprClass:

2245 return

VisitChooseExpr(cast<ChooseExpr>(S), asc);

2247 case

Stmt::CompoundStmtClass:

2248 return

VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);

2250 case

Stmt::ConditionalOperatorClass:

2251 return

VisitConditionalOperator(cast<ConditionalOperator>(S), asc);

2253 case

Stmt::ContinueStmtClass:

2254 return

VisitContinueStmt(cast<ContinueStmt>(S));

2256 case

Stmt::CXXCatchStmtClass:

2257 return

VisitCXXCatchStmt(cast<CXXCatchStmt>(S));

2259 case

Stmt::ExprWithCleanupsClass:

2260 return

VisitExprWithCleanups(cast<ExprWithCleanups>(S),

2261

asc, ExternallyDestructed);

2263 case

Stmt::CXXDefaultArgExprClass:

2264 case

Stmt::CXXDefaultInitExprClass:

2273 return

VisitStmt(S, asc);

2275 case

Stmt::CXXBindTemporaryExprClass:

2276 return

VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);

2278 case

Stmt::CXXConstructExprClass:

2279 return

VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);

2281 case

Stmt::CXXNewExprClass:

2282 return

VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);

2284 case

Stmt::CXXDeleteExprClass:

2285 return

VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);

2287 case

Stmt::CXXFunctionalCastExprClass:

2288 return

VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);

2290 case

Stmt::CXXTemporaryObjectExprClass:

2291 return

VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);

2293 case

Stmt::CXXThrowExprClass:

2294 return

VisitCXXThrowExpr(cast<CXXThrowExpr>(S));

2296 case

Stmt::CXXTryStmtClass:

2297 return

VisitCXXTryStmt(cast<CXXTryStmt>(S));

2299 case

Stmt::CXXTypeidExprClass:

2300 return

VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);

2302 case

Stmt::CXXForRangeStmtClass:

2303 return

VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));

2305 case

Stmt::DeclStmtClass:

2306 return

VisitDeclStmt(cast<DeclStmt>(S));

2308 case

Stmt::DefaultStmtClass:

2309 return

VisitDefaultStmt(cast<DefaultStmt>(S));

2311 case

Stmt::DoStmtClass:

2312 return

VisitDoStmt(cast<DoStmt>(S));

2314 case

Stmt::ForStmtClass:

2315 return

VisitForStmt(cast<ForStmt>(S));

2317 case

Stmt::GotoStmtClass:

2318 return

VisitGotoStmt(cast<GotoStmt>(S));

2320 case

Stmt::GCCAsmStmtClass:

2321 return

VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);

2323 case

Stmt::IfStmtClass:

2324 return

VisitIfStmt(cast<IfStmt>(S));

2326 case

Stmt::ImplicitCastExprClass:

2327 return

VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);

2329 case

Stmt::ConstantExprClass:

2330 return

VisitConstantExpr(cast<ConstantExpr>(S), asc);

2332 case

Stmt::IndirectGotoStmtClass:

2333 return

VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));

2335 case

Stmt::LabelStmtClass:

2336 return

VisitLabelStmt(cast<LabelStmt>(S));

2338 case

Stmt::LambdaExprClass:

2339 return

VisitLambdaExpr(cast<LambdaExpr>(S), asc);

2341 case

Stmt::MaterializeTemporaryExprClass:

2342 return

VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),

2345 case

Stmt::MemberExprClass:

2346 return

VisitMemberExpr(cast<MemberExpr>(S), asc);

2348 case

Stmt::NullStmtClass:

2351 case

Stmt::ObjCAtCatchStmtClass:

2352 return

VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));

2354 case

Stmt::ObjCAutoreleasePoolStmtClass:

2355 return

VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));

2357 case

Stmt::ObjCAtSynchronizedStmtClass:

2358 return

VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));

2360 case

Stmt::ObjCAtThrowStmtClass:

2361 return

VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));

2363 case

Stmt::ObjCAtTryStmtClass:

2364 return

VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));

2366 case

Stmt::ObjCForCollectionStmtClass:

2367 return

VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));

2369 case

Stmt::ObjCMessageExprClass:

2370 return

VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);

2372 case

Stmt::OpaqueValueExprClass:

2375 case

Stmt::PseudoObjectExprClass:

2376 return

VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));

2378 case

Stmt::ReturnStmtClass:

2379 case

Stmt::CoreturnStmtClass:

2380 return

VisitReturnStmt(S);

2382 case

Stmt::CoyieldExprClass:

2383 case

Stmt::CoawaitExprClass:

2384 return

VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);

2386 case

Stmt::SEHExceptStmtClass:

2387 return

VisitSEHExceptStmt(cast<SEHExceptStmt>(S));

2389 case

Stmt::SEHFinallyStmtClass:

2390 return

VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));

2392 case

Stmt::SEHLeaveStmtClass:

2393 return

VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));

2395 case

Stmt::SEHTryStmtClass:

2396 return

VisitSEHTryStmt(cast<SEHTryStmt>(S));

2398 case

Stmt::UnaryExprOrTypeTraitExprClass:

2399 return

VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),

2402 case

Stmt::StmtExprClass:

2403 return

VisitStmtExpr(cast<StmtExpr>(S), asc);

2405 case

Stmt::SwitchStmtClass:

2406 return

VisitSwitchStmt(cast<SwitchStmt>(S));

2408 case

Stmt::UnaryOperatorClass:

2409 return

VisitUnaryOperator(cast<UnaryOperator>(S), asc);

2411 case

Stmt::WhileStmtClass:

2412 return

VisitWhileStmt(cast<WhileStmt>(S));

2414 case

Stmt::ArrayInitLoopExprClass:

2415 return

VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);

2419CFGBlock

*CFGBuilder::VisitStmt(

Stmt

*S, AddStmtChoice asc) {

2420 if

(asc.alwaysAdd(*

this

, S)) {

2422

appendStmt(

Block

, S);

2425 return

VisitChildren(S);

2434

reverse_children RChildren(S);

2435 for

(

Stmt

*Child : RChildren) {

2444 if

(asc.alwaysAdd(*

this

, ILE)) {

2446

appendStmt(

Block

, ILE);

2450

reverse_children RChildren(ILE);

2451 for

(

Stmt

*Child : RChildren) {

2457 if

(

auto

*DIE = dyn_cast<CXXDefaultInitExpr>(Child))

2458 if

(

Stmt

*Child = DIE->getExpr())

2467

AddStmtChoice asc) {

2468

AddressTakenLabels.insert(A->

getLabel

());

2470 if

(asc.alwaysAdd(*

this

, A)) {

2472

appendStmt(

Block

, A);

2479 bool

isFallthrough = hasSpecificAttr<FallThroughAttr>(A->

getAttrs

());

2480

assert((!isFallthrough || isa<NullStmt>(A->

getSubStmt

())) &&

2481 "expected fallthrough not to have children"

);

2482 return

isFallthrough;

2486

AddStmtChoice asc) {

2497

appendStmt(

Block

, A);

2500 return

VisitChildren(A);

2504 if

(asc.alwaysAdd(*

this

,

U

)) {

2509 if

(

U

->getOpcode() == UO_LNot)

2510

tryEvaluateBool(

U

->getSubExpr()->IgnoreParens());

2512 return

Visit(

U

->getSubExpr(), AddStmtChoice());

2517

appendStmt(ConfluenceBlock, B);

2522 return

VisitLogicalOperator(B,

nullptr

, ConfluenceBlock,

2523

ConfluenceBlock).first;

2526

std::pair<CFGBlock*, CFGBlock*>

2539 if

(B_RHS->isLogicalOp()) {

2540

std::tie(RHSBlock, ExitBlock) =

2541

VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);

2549

ExitBlock = RHSBlock = createBlock(

false

);

2554

TryResult KnownVal = tryEvaluateBool(RHS);

2555 if

(!KnownVal.isKnown())

2556

KnownVal = tryEvaluateBool(B);

2559

assert(TrueBlock == FalseBlock);

2560

addSuccessor(RHSBlock, TrueBlock);

2564

addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());

2565

addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());

2569

RHSBlock = addStmt(RHS);

2574 return

std::make_pair(

nullptr

,

nullptr

);

2580 if

(B_LHS->isLogicalOp()) {

2582

FalseBlock = RHSBlock;

2584

TrueBlock = RHSBlock;

2589 return

VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);

2594 CFGBlock

*LHSBlock = createBlock(

false

);

2598 CFGBlock

*EntryLHSBlock = addStmt(LHS);

2601 return

std::make_pair(

nullptr

,

nullptr

);

2604

TryResult KnownVal = tryEvaluateBool(LHS);

2608

addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());

2609

addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());

2612

addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());

2613

addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());

2616 return

std::make_pair(EntryLHSBlock, ExitBlock);

2620

AddStmtChoice asc) {

2623 return

VisitLogicalOperator(B);

2627

appendStmt(

Block

, B);

2629 return

addStmt(B->

getLHS

());

2633 if

(asc.alwaysAdd(*

this

, B)) {

2635

appendStmt(

Block

, B);

2638 return

Visit(B->

getRHS

());

2641 if

(asc.alwaysAdd(*

this

, B)) {

2643

appendStmt(

Block

, B);

2654 return

(LBlock ? LBlock : RBlock);

2657CFGBlock

*CFGBuilder::VisitNoRecurse(

Expr

*

E

, AddStmtChoice asc) {

2658 if

(asc.alwaysAdd(*

this

,

E

)) {

2672 Block

= createBlock(

false

);

2677 if

(BreakJumpTarget.block) {

2678

addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);

2679

addSuccessor(

Block

, BreakJumpTarget.block);

2703 QualType

calleeType =

C

->getCallee()->getType();

2709 if

(!boundType.

isNull

()) calleeType = boundType;

2715 bool

AddEHEdge =

false

;

2725 bool

OmitArguments =

false

;

2732 if

(!FD->isVariadic())

2733

findConstructionContextsForArguments(

C

);

2735 if

(FD->isNoReturn() ||

C

->isBuiltinAssumeFalse(*Context))

2737 if

(FD->

hasAttr

<NoThrowAttr>())

2739 if

(FD->getBuiltinID() == Builtin::BI__builtin_object_size ||

2740

FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)

2741

OmitArguments =

true

;

2744 if

(!

CanThrow

(

C

->getCallee(), *Context))

2747 if

(OmitArguments) {

2748

assert(!NoReturn &&

"noreturn calls with unevaluated args not implemented"

);

2749

assert(!AddEHEdge &&

"EH calls with unevaluated args not implemented"

);

2752 return

Visit(

C

->getCallee());

2755 if

(!NoReturn && !AddEHEdge) {

2759 return

VisitChildren(

C

);

2769 Block

= createNoReturnBlock();

2771 Block

= createBlock();

2777 if

(TryTerminatedBlock)

2778

addSuccessor(

Block

, TryTerminatedBlock);

2780

addSuccessor(

Block

, &cfg->getExit());

2783 return

VisitChildren(

C

);

2787

AddStmtChoice asc) {

2789

appendStmt(ConfluenceBlock,

C

);

2793

AddStmtChoice alwaysAdd = asc.withAlwaysAdd(

true

);

2794

Succ = ConfluenceBlock;

2796 CFGBlock

*LHSBlock = Visit(

C

->getLHS(), alwaysAdd);

2800

Succ = ConfluenceBlock;

2802 CFGBlock

*RHSBlock = Visit(

C

->getRHS(), alwaysAdd);

2806 Block

= createBlock(

false

);

2808 const

TryResult& KnownVal = tryEvaluateBool(

C

->getCond());

2809

addSuccessor(

Block

, KnownVal.isFalse() ?

nullptr

: LHSBlock);

2810

addSuccessor(

Block

, KnownVal.isTrue() ?

nullptr

: RHSBlock);

2812 return

addStmt(

C

->getCond());

2816 bool

ExternallyDestructed) {

2817

LocalScope::const_iterator scopeBeginPos = ScopePos;

2818

addLocalScopeForStmt(

C

);

2820 if

(!

C

->body_empty() && !isa<ReturnStmt>(*

C

->body_rbegin())) {

2823

addAutomaticObjHandling(ScopePos, scopeBeginPos,

C

);

2828 for

(

Stmt

*S : llvm::reverse(

C

->body())) {

2831 CFGBlock

*newBlock = Visit(S, AddStmtChoice::AlwaysAdd,

2832

ExternallyDestructed);

2835

LastBlock = newBlock;

2840

ExternallyDestructed =

false

;

2847

AddStmtChoice asc) {

2854

appendStmt(ConfluenceBlock,

C

);

2858

AddStmtChoice alwaysAdd = asc.withAlwaysAdd(

true

);

2864

Succ = ConfluenceBlock;

2867 const Expr

*trueExpr =

C

->getTrueExpr();

2868 if

(trueExpr != opaqueValue) {

2869

LHSBlock = Visit(

C

->getTrueExpr(), alwaysAdd);

2875

LHSBlock = ConfluenceBlock;

2878

Succ = ConfluenceBlock;

2879 CFGBlock

*RHSBlock = Visit(

C

->getFalseExpr(), alwaysAdd);

2885

dyn_cast<BinaryOperator>(

C

->getCond()->IgnoreParens()))

2886 if

(Cond->isLogicalOp())

2887 return

VisitLogicalOperator(Cond,

C

, LHSBlock, RHSBlock).first;

2890 Block

= createBlock(

false

);

2893 const

TryResult& KnownVal = tryEvaluateBool(

C

->getCond());

2894

addSuccessor(

Block

, LHSBlock, !KnownVal.isFalse());

2895

addSuccessor(

Block

, RHSBlock, !KnownVal.isTrue());

2897 Expr

*condExpr =

C

->getCond();

2902 if

(condExpr != opaqueValue)

2910 return

addStmt(condExpr);

2921 return

VisitDeclSubExpr(DS);

2935

cfg->addSyntheticDeclStmt(DSNew, DS);

2938

B = VisitDeclSubExpr(DSNew);

2947

assert(DS->

isSingleDecl

() &&

"Can handle single declarations only."

);

2949 if

(

const auto

*TND = dyn_cast<TypedefNameDecl>(DS->

getSingleDecl

())) {

2951 const Type

*

T

= TND->getUnderlyingType().getTypePtr();

2956

appendStmt(

Block

, DS);

2960

VA =

FindVA

(VA->getElementType().getTypePtr())) {

2961 if

(

CFGBlock

*NewBlock = addStmt(VA->getSizeExpr()))

2962

LastBlock = NewBlock;

2975 bool

HasTemporaries =

false

;

2978 CFGBlock

*blockAfterStaticInit =

nullptr

;

2989

blockAfterStaticInit = Succ;

2996

HasTemporaries = isa<ExprWithCleanups>(

Init

);

3000

TempDtorContext Context;

3001

VisitForTemporaryDtors(cast<ExprWithCleanups>(

Init

)->getSubExpr(),

3008 if

(

const auto

*DD = dyn_cast<DecompositionDecl>(VD)) {

3009 for

(

auto

*BD : llvm::reverse(DD->bindings())) {

3010 if

(

auto

*VD = BD->getHoldingVar()) {

3014

cfg->addSyntheticDeclStmt(DSNew, DS);

3015 Block

= VisitDeclSubExpr(DSNew);

3021

appendStmt(

Block

, DS);

3025 const auto

*AILE = dyn_cast_or_null<ArrayInitLoopExpr>(

Init

);

3027

findConstructionContexts(

3029

AILE ? AILE->getSubExpr() :

Init

);

3037 if

(HasTemporaries) {

3042

LastBlock = newBlock;

3046

LastBlock = newBlock;

3054

VA !=

nullptr

; VA =

FindVA

(VA->getElementType().getTypePtr())) {

3055 if

(

CFGBlock

*newBlock = addStmt(VA->getSizeExpr()))

3056

LastBlock = newBlock;

3059

maybeAddScopeBeginForVarDecl(

Block

, VD, DS);

3062 if

(ScopePos && VD == *ScopePos)

3066 if

(blockAfterStaticInit) {

3068 Block

= createBlock(

false

);

3070

addSuccessor(

Block

, blockAfterStaticInit);

3071

addSuccessor(

Block

, B);

3092

addLocalScopeForStmt(

Init

);

3097

addLocalScopeForVarDecl(VD);

3099

addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);

3121 if

(!isa<CompoundStmt>(Else))

3122

addLocalScopeAndDtors(Else);

3124

ElseBlock = addStmt(Else);

3127

ElseBlock = sv.get();

3144 if

(!isa<CompoundStmt>(Then))

3145

addLocalScopeAndDtors(Then);

3147

ThenBlock = addStmt(Then);

3153

ThenBlock = createBlock(

false

);

3154

addSuccessor(ThenBlock, sv.get());

3155

}

else if

(

Block

) {

3174

LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;

3177 Block

= createBlock(

false

);

3185

KnownVal = tryEvaluateBool(I->

getCond

());

3189

addSuccessor(

Block

, ThenBlock,

!KnownVal.isFalse());

3190

addSuccessor(

Block

, ElseBlock,

!KnownVal.isTrue());

3198

LastBlock = addStmt(I->

getCond

());

3204

LastBlock = addStmt(

const_cast<DeclStmt

*

>

(DS));

3211

LastBlock = addStmt(

Init

);

3224

assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));

3227 Block

= createBlock(

false

);

3229

addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);

3231 if

(

auto

*R = dyn_cast<ReturnStmt>(S))

3232

findConstructionContexts(

3239

addSuccessor(

Block

, &cfg->getExit());

3242

appendStmt(

Block

, S);

3245 if

(

ReturnStmt

*RS = dyn_cast<ReturnStmt>(S)) {

3246 if

(

Expr

*O = RS->getRetValue())

3247 return

Visit(O, AddStmtChoice::AlwaysAdd,

true

);

3257 if

(RV->getType()->isVoidType() && !isa<InitListExpr>(RV))

3266

AddStmtChoice asc) {

3270 if

(asc.alwaysAdd(*

this

,

E

)) {

3275 if

(

auto

*R = Visit(

E

->getResumeExpr()))

3277 if

(

auto

*R = Visit(

E

->getSuspendExpr()))

3279 if

(

auto

*R = Visit(

E

->getReadyExpr()))

3281 if

(

auto

*R = Visit(

E

->getCommonExpr()))

3296 if

(!SEHExceptBlock)

3297

SEHExceptBlock = createBlock();

3299

appendStmt(SEHExceptBlock, ES);

3311 return

SEHExceptBlock;

3315 return

VisitCompoundStmt(FS->getBlock(),

false

);

3325 Block

= createBlock(

false

);

3330 if

(SEHLeaveJumpTarget.block) {

3331

addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);

3332

addSuccessor(

Block

, SEHLeaveJumpTarget.block);

3342 CFGBlock

*SEHTrySuccessor =

nullptr

;

3347

SEHTrySuccessor =

Block

;

3348

}

else

SEHTrySuccessor = Succ;

3354 CFGBlock

*PrevSEHTryTerminatedBlock = TryTerminatedBlock;

3357 CFGBlock

*NewTryTerminatedBlock = createBlock(

false

);

3364

Succ = SEHTrySuccessor;

3366 CFGBlock

*ExceptBlock = VisitSEHExceptStmt(Except);

3371

addSuccessor(NewTryTerminatedBlock, ExceptBlock);

3373 if

(PrevSEHTryTerminatedBlock)

3374

addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);

3376

addSuccessor(NewTryTerminatedBlock, &cfg->getExit());

3379

Succ = SEHTrySuccessor;

3382 SaveAndRestore

SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);

3383

cfg->addTryDispatchBlock(TryTerminatedBlock);

3389

SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);

3391

assert(Terminator->

getTryBlock

() &&

"__try must contain a non-NULL body"

);

3402

LabelBlock = createBlock();

3404

assert(!LabelMap.contains(L->

getDecl

()) &&

"label already in map"

);

3405

LabelMap[L->

getDecl

()] = JumpTarget(LabelBlock, ScopePos);

3425 CFGBlock

*LastBlock = VisitNoRecurse(

E

, asc);

3427 if

(

Expr

*CopyExpr = CI.getCopyExpr()) {

3437 CFGBlock

*LastBlock = VisitNoRecurse(

E

, asc);

3441

et =

E

->capture_init_end();

3442

it != et; ++it, ++Idx) {

3447

dyn_cast<ArrayInitLoopExpr>(

Init

));

3450

cfg->getBumpVectorContext(), {E, Idx}),

3451

AILEInit ? AILEInit :

Init

);

3465 Block

= createBlock(

false

);

3469

LabelMapTy::iterator I = LabelMap.find(G->

getLabel

());

3471 if

(I == LabelMap.end())

3473

BackpatchBlocks.push_back(JumpSource(

Block

, ScopePos));

3475

JumpTarget JT = I->second;

3476

addSuccessor(

Block

, JT.block);

3477

addScopeChangesHandling(ScopePos, JT.scopePosition, G);

3488 return

VisitStmt(G, asc);

3495 Block

= createBlock();

3498

BackpatchBlocks.push_back(JumpSource(

Block

, ScopePos));

3501

BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));

3502 return

VisitChildren(G);

3506 CFGBlock

*LoopSuccessor =

nullptr

;

3516

addLocalScopeForStmt(

Init

);

3517

LocalScope::const_iterator LoopBeginScopePos = ScopePos;

3520

addLocalScopeForVarDecl(VD);

3521

LocalScope::const_iterator ContinueScopePos = ScopePos;

3523

addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);

3532

LoopSuccessor =

Block

;

3534

LoopSuccessor = Succ;

3539

BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

3541 CFGBlock

*BodyBlock =

nullptr

, *TransitionBlock =

nullptr

;

3554 Block

= Succ = TransitionBlock = createBlock(

false

);

3555

TransitionBlock->setLoopTarget(F);

3560

addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);

3570

assert(

Block

== Succ);

3578

ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);

3579

ContinueJumpTarget.block->setLoopTarget(F);

3584 if

(!isa<CompoundStmt>(F->

getBody

()))

3585

addLocalScopeAndDtors(F->

getBody

());

3589

BodyBlock = addStmt(F->

getBody

());

3594

BodyBlock = ContinueJumpTarget.block;

3603 CFGBlock

*EntryConditionBlock =

nullptr

, *ExitConditionBlock =

nullptr

;

3612

dyn_cast_or_null<BinaryOperator>(

C

?

C

->IgnoreParens() :

nullptr

))

3614

std::tie(EntryConditionBlock, ExitConditionBlock) =

3615

VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);

3620

EntryConditionBlock = ExitConditionBlock = createBlock(

false

);

3621

ExitConditionBlock->setTerminator(F);

3624

TryResult KnownVal(

true

);

3630 Block

= ExitConditionBlock;

3631

EntryConditionBlock = addStmt(

C

);

3640

findConstructionContexts(

3643

appendStmt(

Block

, DS);

3644

EntryConditionBlock = addStmt(

Init

);

3645

assert(

Block

== EntryConditionBlock);

3646

maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,

C

);

3650 if

(

Block

&& badCFG)

3653

KnownVal = tryEvaluateBool(

C

);

3657

addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?

nullptr

: BodyBlock);

3660

addSuccessor(ExitConditionBlock,

3661

KnownVal.isTrue() ?

nullptr

: LoopSuccessor);

3665

addSuccessor(TransitionBlock, EntryConditionBlock);

3668

Succ = EntryConditionBlock;

3674

ScopePos = LoopBeginScopePos;

3675 Block

= createBlock();

3682

Succ = EntryConditionBlock;

3683 return

EntryConditionBlock;

3688

AddStmtChoice asc) {

3689

findConstructionContexts(

3693 return

VisitStmt(MTE, asc);

3697 if

(asc.alwaysAdd(*

this

, M)) {

3699

appendStmt(

Block

, M);

3736 CFGBlock

*LoopSuccessor =

nullptr

;

3741

LoopSuccessor =

Block

;

3744

LoopSuccessor = Succ;

3747 CFGBlock

*ExitConditionBlock = createBlock(

false

);

3755

appendStmt(ExitConditionBlock, S);

3756 Block

= ExitConditionBlock;

3761 CFGBlock

*EntryConditionBlock = Visit(S->getElement(),

3762

AddStmtChoice::NotAlwaysAdd);

3771

Succ = EntryConditionBlock;

3778

save_break(BreakJumpTarget);

3783 CFGBlock

*LoopBackBlock =

nullptr

;

3784

Succ = LoopBackBlock = createBlock();

3787

BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

3788

ContinueJumpTarget = JumpTarget(Succ, ScopePos);

3790 CFGBlock

*BodyBlock = addStmt(S->getBody());

3793

BodyBlock = ContinueJumpTarget.block;

3800

addSuccessor(ExitConditionBlock, BodyBlock);

3805

addSuccessor(ExitConditionBlock, LoopSuccessor);

3808 Block

= createBlock();

3809 return

addStmt(S->getCollection());

3814 return

addStmt(S->getSubStmt());

3822 CFGBlock

*SyncBlock = addStmt(S->getSynchBody());

3836

appendStmt(

Block

, S);

3839 return

addStmt(S->getSynchExpr());

3852 for

(

unsigned

i =

E

->getNumSemanticExprs(); i != 0; ) {

3853 Expr

*Semantic =

E

->getSemanticExpr(--i);

3858

Semantic = OVE->getSourceExpr();

3860 if

(

CFGBlock

*B = Visit(Semantic))

3868 CFGBlock

*LoopSuccessor =

nullptr

;

3876

LocalScope::const_iterator LoopBeginScopePos = ScopePos;

3878

addLocalScopeForVarDecl(VD);

3879

addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);

3888

LoopSuccessor =

Block

;

3891

LoopSuccessor = Succ;

3894 CFGBlock

*BodyBlock =

nullptr

, *TransitionBlock =

nullptr

;

3903

save_break(BreakJumpTarget);

3907

Succ = TransitionBlock = createBlock(

false

);

3908

TransitionBlock->setLoopTarget(W);

3909

ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);

3912

BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

3915

addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);

3919 if

(!isa<CompoundStmt>(W->

getBody

()))

3920

addLocalScopeAndDtors(W->

getBody

());

3923

BodyBlock = addStmt(W->

getBody

());

3926

BodyBlock = ContinueJumpTarget.block;

3927 else if

(

Block

&& badCFG)

3934 CFGBlock

*EntryConditionBlock =

nullptr

, *ExitConditionBlock =

nullptr

;

3941 if

(

BinaryOperator

*Cond = dyn_cast<BinaryOperator>(

C

->IgnoreParens()))

3943

std::tie(EntryConditionBlock, ExitConditionBlock) =

3944

VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);

3949

ExitConditionBlock = createBlock(

false

);

3955 Block

= ExitConditionBlock;

3956 Block

= EntryConditionBlock = addStmt(

C

);

3965

findConstructionContexts(

3969

appendStmt(

Block

, DS);

3970

EntryConditionBlock = addStmt(

Init

);

3971

assert(

Block

== EntryConditionBlock);

3972

maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD,

C

);

3976 if

(

Block

&& badCFG)

3980 const

TryResult& KnownVal = tryEvaluateBool(

C

);

3983

addSuccessor(ExitConditionBlock, KnownVal.isFalse() ?

nullptr

: BodyBlock);

3986

addSuccessor(ExitConditionBlock,

3987

KnownVal.isTrue() ?

nullptr

: LoopSuccessor);

3991

addSuccessor(TransitionBlock, EntryConditionBlock);

3998

Succ = EntryConditionBlock;

3999 return

EntryConditionBlock;

4003

AddStmtChoice asc) {

4004 if

(asc.alwaysAdd(*

this

, A)) {

4006

appendStmt(

Block

, A);

4014 auto

*OVE = dyn_cast<OpaqueValueExpr>(A->

getCommonExpr

());

4015

assert(OVE &&

"ArrayInitLoopExpr->getCommonExpr() should be wrapped in an " 4016 "OpaqueValueExpr!"

);

4017 if

(

CFGBlock

*R = Visit(OVE->getSourceExpr()))

4036

CatchBlock = createBlock();

4038

appendStmt(CatchBlock, CS);

4059 Block

= createBlock(

false

);

4061 if

(TryTerminatedBlock)

4063

addSuccessor(

Block

, TryTerminatedBlock);

4066

addSuccessor(

Block

, &cfg->getExit());

4070 return

VisitStmt(S, AddStmtChoice::AlwaysAdd);

4081

TrySuccessor =

Block

;

4083

TrySuccessor = Succ;

4089 CFGBlock

*PrevTryTerminatedBlock = TryTerminatedBlock;

4092 CFGBlock

*NewTryTerminatedBlock = createBlock(

false

);

4096 bool

HasCatchAll =

false

;

4099

Succ = TrySuccessor;

4101

HasCatchAll =

true

;

4104 CFGBlock

*CatchBlock = VisitObjCAtCatchStmt(CS);

4109

addSuccessor(NewTryTerminatedBlock, CatchBlock);

4114 if

(PrevTryTerminatedBlock)

4115

addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);

4117

addSuccessor(NewTryTerminatedBlock, &cfg->getExit());

4121

Succ = TrySuccessor;

4124 SaveAndRestore

SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);

4125

cfg->addTryDispatchBlock(TryTerminatedBlock);

4127

assert(Terminator->

getTryBody

() &&

"try must contain a non-NULL body"

);

4133

AddStmtChoice asc) {

4134

findConstructionContextsForArguments(ME);

4137

appendObjCMessage(

Block

, ME);

4139 return

VisitChildren(ME);

4148 Block

= createBlock(

false

);

4150 if

(TryTerminatedBlock)

4152

addSuccessor(

Block

, TryTerminatedBlock);

4155

addSuccessor(

Block

, &cfg->getExit());

4159 return

VisitStmt(

T

, AddStmtChoice::AlwaysAdd);

4163 if

(asc.alwaysAdd(*

this

, S)) {

4165

appendStmt(

Block

, S);

4174 if

(!S->isTypeDependent() && S->isPotentiallyEvaluated())

4175 return

VisitChildren(S);

4182 CFGBlock

*LoopSuccessor =

nullptr

;

4191

LoopSuccessor =

Block

;

4193

LoopSuccessor = Succ;

4198 CFGBlock

*ExitConditionBlock = createBlock(

false

);

4199 CFGBlock

*EntryConditionBlock = ExitConditionBlock;

4206 if

(

Stmt

*

C

=

D

->getCond()) {

4207 Block

= ExitConditionBlock;

4208

EntryConditionBlock = addStmt(

C

);

4216

Succ = EntryConditionBlock;

4219 const

TryResult &KnownVal = tryEvaluateBool(

D

->getCond());

4229

save_break(BreakJumpTarget);

4232

ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);

4235

BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

4242 if

(!isa<CompoundStmt>(

D

->

getBody

()))

4243

addLocalScopeAndDtors(

D

->

getBody

());

4246

BodyBlock = addStmt(

D

->

getBody

());

4249

BodyBlock = EntryConditionBlock;

4262 CFGBlock

*LoopBackBlock = createBlock();

4265 if

(!KnownVal.isFalse())

4267

addSuccessor(ExitConditionBlock, LoopBackBlock);

4269

addSuccessor(ExitConditionBlock,

nullptr

);

4274

addSuccessor(ExitConditionBlock, KnownVal.isTrue() ?

nullptr

: LoopSuccessor);

4292 Block

= createBlock(

false

);

4297 if

(ContinueJumpTarget.block) {

4298

addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition,

C

);

4299

addSuccessor(

Block

, ContinueJumpTarget.block);

4307

AddStmtChoice asc) {

4308 if

(asc.alwaysAdd(*

this

,

E

)) {

4316 if

(

E

->getKind() != UETT_SizeOf)

4321 if

(

E

->isArgumentType()) {

4323

VA !=

nullptr

; VA =

FindVA

(VA->getElementType().getTypePtr()))

4324

lastBlock = addStmt(VA->getSizeExpr());

4332 if

(asc.alwaysAdd(*

this

, SE)) {

4334

appendStmt(

Block

, SE);

4336 return

VisitCompoundStmt(SE->

getSubStmt

(),

true

);

4342 CFGBlock

*SwitchSuccessor =

nullptr

;

4350

addLocalScopeForStmt(

Init

);

4355

addLocalScopeForVarDecl(VD);

4357

addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);

4362

SwitchSuccessor =

Block

;

4363

}

else

SwitchSuccessor = Succ;

4367

save_default(DefaultCaseBlock);

4373

DefaultCaseBlock = SwitchSuccessor;

4376

SwitchTerminatedBlock = createBlock(

false

);

4380

Succ = SwitchSuccessor;

4381

BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);

4386

assert(Terminator->

getBody

() &&

"switch must contain a non-NULL body"

);

4391 SaveAndRestore

save_switchExclusivelyCovered(switchExclusivelyCovered,

false

);

4394

assert(Terminator->

getCond

() &&

"switch condition must be non-NULL"

);

4396 bool b

= tryEvaluate(Terminator->

getCond

(), result);

4401 if

(!isa<CompoundStmt>(Terminator->

getBody

()))

4402

addLocalScopeAndDtors(Terminator->

getBody

());

4404

addStmt(Terminator->

getBody

());

4416 bool

SwitchAlwaysHasSuccessor =

false

;

4417

SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;

4420

addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,

4421

!SwitchAlwaysHasSuccessor);

4425 Block

= SwitchTerminatedBlock;

4434

LastBlock = addStmt(

Init

);

4435

maybeAddScopeBeginForVarDecl(LastBlock, VD,

Init

);

4442

LastBlock = addStmt(

Init

);

4455 bool

addCase =

false

;

4457 if

(!switchExclusivelyCovered) {

4461 const

llvm::APSInt &condInt = switchCond->

Val

.

getInt

();

4463 if

(condInt == lhsInt) {

4465

switchExclusivelyCovered =

true

;

4467 else if

(condInt > lhsInt) {

4471 if

(V2 >= condInt) {

4473

switchExclusivelyCovered =

true

;

4487 CFGBlock

*TopBlock =

nullptr

, *LastBlock =

nullptr

;

4493 while

(isa<CaseStmt>(Sub)) {

4494 CFGBlock

*currentBlock = createBlock(

false

);

4498

addSuccessor(LastBlock, currentBlock);

4500

TopBlock = currentBlock;

4502

addSuccessor(SwitchTerminatedBlock,

4505

? currentBlock :

nullptr

);

4507

LastBlock = currentBlock;

4508

CS = cast<CaseStmt>(Sub);

4517

CaseBlock = createBlock();

4528

assert(SwitchTerminatedBlock);

4529

addSuccessor(SwitchTerminatedBlock, CaseBlock,

4537

addSuccessor(LastBlock, CaseBlock);

4551

DefaultCaseBlock =

Block

;

4553 if

(!DefaultCaseBlock)

4554

DefaultCaseBlock = createBlock();

4558

DefaultCaseBlock->

setLabel

(Terminator);

4573

Succ = DefaultCaseBlock;

4575 return

DefaultCaseBlock;

4586

TrySuccessor =

Block

;

4588

TrySuccessor = Succ;

4590 CFGBlock

*PrevTryTerminatedBlock = TryTerminatedBlock;

4593 CFGBlock

*NewTryTerminatedBlock = createBlock(

false

);

4597 bool

HasCatchAll =

false

;

4600

Succ = TrySuccessor;

4603

HasCatchAll =

true

;

4606 CFGBlock

*CatchBlock = VisitCXXCatchStmt(CS);

4611

addSuccessor(NewTryTerminatedBlock, CatchBlock);

4614 if

(PrevTryTerminatedBlock)

4615

addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);

4617

addSuccessor(NewTryTerminatedBlock, &cfg->getExit());

4621

Succ = TrySuccessor;

4624 SaveAndRestore

SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);

4625

cfg->addTryDispatchBlock(TryTerminatedBlock);

4627

assert(Terminator->

getTryBlock

() &&

"try must contain a non-NULL body"

);

4643

LocalScope::const_iterator BeginScopePos = ScopePos;

4644

addLocalScopeForVarDecl(VD);

4645

addAutomaticObjHandling(ScopePos, BeginScopePos, CS);

4653

CatchBlock = createBlock();

4659

appendStmt(CatchBlock, CS);

4694

addLocalScopeForStmt(

Range

);

4696

addLocalScopeForStmt(

Begin

);

4697 if

(

Stmt

*End = S->getEndStmt())

4698

addLocalScopeForStmt(End);

4699

addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);

4701

LocalScope::const_iterator ContinueScopePos = ScopePos;

4705 CFGBlock

*LoopSuccessor =

nullptr

;

4709

LoopSuccessor =

Block

;

4711

LoopSuccessor = Succ;

4716

BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

4719 CFGBlock

*ConditionBlock = createBlock(

false

);

4723 if

(

Expr

*

C

= S->getCond()) {

4724 Block

= ConditionBlock;

4725 CFGBlock

*BeginConditionBlock = addStmt(

C

);

4728

assert(BeginConditionBlock == ConditionBlock &&

4729 "condition block in for-range was unexpectedly complex"

);

4730

(void)BeginConditionBlock;

4735

Succ = ConditionBlock;

4738

TryResult KnownVal(

true

);

4741

KnownVal = tryEvaluateBool(S->getCond());

4745

assert(S->getBody());

4754

Succ = addStmt(S->getInc());

4757

ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);

4761

ContinueJumpTarget.block->setLoopTarget(S);

4770

addLocalScopeAndDtors(S->getLoopVarStmt());

4774 if

(!isa<CompoundStmt>(S->getBody()))

4775

addLocalScopeAndDtors(S->getBody());

4778

addStmt(S->getBody());

4782 CFGBlock

*LoopVarStmtBlock = addStmt(S->getLoopVarStmt());

4787

addSuccessor(ConditionBlock,

4788

KnownVal.isFalse() ?

nullptr

: LoopVarStmtBlock);

4793

addSuccessor(ConditionBlock, KnownVal.isTrue() ?

nullptr

: LoopSuccessor);

4796 Block

= createBlock();

4797

addStmt(S->getBeginStmt());

4798

addStmt(S->getEndStmt());

4799 CFGBlock

*Head = addStmt(S->getRangeStmt());

4801

Head = addStmt(S->getInit());

4806

AddStmtChoice asc,

bool

ExternallyDestructed) {

4810

TempDtorContext Context;

4811

VisitForTemporaryDtors(

E

->getSubExpr(), ExternallyDestructed, Context);

4815

asc = asc.withAlwaysAdd(

true

);

4817 return

Visit(

E

->getSubExpr(), asc);

4821

AddStmtChoice asc) {

4822 if

(asc.alwaysAdd(*

this

,

E

)) {

4826

findConstructionContexts(

4831

asc = asc.withAlwaysAdd(

false

);

4833 return

Visit(

E

->getSubExpr(), asc);

4837

AddStmtChoice asc) {

4841

findConstructionContextsForArguments(

C

);

4842

appendConstructor(

C

);

4844 return

VisitChildren(

C

);

4848

AddStmtChoice asc) {

4850

appendStmt(

Block

, NE);

4852

findConstructionContexts(

4856 if

(

NE

->getInitializer())

4857 Block

= Visit(

NE

->getInitializer());

4860

appendNewAllocator(

Block

, NE);

4862 if

(

NE

->isArray() && *

NE

->getArraySize())

4863 Block

= Visit(*

NE

->getArraySize());

4866 E

=

NE

->placement_arg_end(); I !=

E

; ++I)

4873

AddStmtChoice asc) {

4875

appendStmt(

Block

, DE);

4882

appendDeleteDtor(

Block

, RD, DE);

4886 return

VisitChildren(DE);

4890

AddStmtChoice asc) {

4891 if

(asc.alwaysAdd(*

this

,

E

)) {

4895

asc = asc.withAlwaysAdd(

false

);

4897 return

Visit(

E

->getSubExpr(), asc);

4901

AddStmtChoice asc) {

4905

findConstructionContextsForArguments(

E

);

4906

appendConstructor(

E

);

4908 return

VisitChildren(

E

);

4912

AddStmtChoice asc) {

4913 if

(asc.alwaysAdd(*

this

,

E

)) {

4918 if

(

E

->getCastKind() == CK_IntegralToBoolean)

4921 return

Visit(

E

->getSubExpr(), AddStmtChoice());

4925 return

Visit(

E

->getSubExpr(), AddStmtChoice());

4930 CFGBlock

*IBlock = cfg->getIndirectGotoBlock();

4933

IBlock = createBlock(

false

);

4934

cfg->setIndirectGotoBlock(IBlock);

4942 Block

= createBlock(

false

);

4944

addSuccessor(

Block

, IBlock);

4948CFGBlock

*CFGBuilder::VisitForTemporaryDtors(

Stmt

*

E

,

bool

ExternallyDestructed,

4949

TempDtorContext &Context) {

4959 return

VisitChildrenForTemporaryDtors(

E

,

false

, Context);

4961 case

Stmt::InitListExprClass:

4962 return

VisitChildrenForTemporaryDtors(

E

, ExternallyDestructed, Context);

4964 case

Stmt::BinaryOperatorClass:

4965 return

VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(

E

),

4966

ExternallyDestructed,

4969 case

Stmt::CXXBindTemporaryExprClass:

4970 return

VisitCXXBindTemporaryExprForTemporaryDtors(

4971

cast<CXXBindTemporaryExpr>(

E

), ExternallyDestructed, Context);

4973 case

Stmt::BinaryConditionalOperatorClass:

4974 case

Stmt::ConditionalOperatorClass:

4975 return

VisitConditionalOperatorForTemporaryDtors(

4976

cast<AbstractConditionalOperator>(

E

), ExternallyDestructed, Context);

4978 case

Stmt::ImplicitCastExprClass:

4980 E

= cast<CastExpr>(

E

)->getSubExpr();

4983 case

Stmt::CXXFunctionalCastExprClass:

4985 E

= cast<CXXFunctionalCastExpr>(

E

)->getSubExpr();

4988 case

Stmt::ConstantExprClass:

4989 E

= cast<ConstantExpr>(

E

)->getSubExpr();

4992 case

Stmt::ParenExprClass:

4993 E

= cast<ParenExpr>(

E

)->getSubExpr();

4996 case

Stmt::MaterializeTemporaryExprClass: {

5002 E

=

const_cast<Expr

*

>

(

5003

cast<MaterializeTemporaryExpr>(

E

)

5005

->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));

5007 for

(

const Expr

*CommaLHS : CommaLHSs) {

5008

VisitForTemporaryDtors(

const_cast<Expr

*

>

(CommaLHS),

5014 case

Stmt::BlockExprClass:

5019 case

Stmt::LambdaExprClass: {

5022 auto

*

LE

= cast<LambdaExpr>(

E

);

5026 if

(

CFGBlock

*R = VisitForTemporaryDtors(

5027 Init

,

true

, Context))

5034 case

Stmt::StmtExprClass:

5039 case

Stmt::CXXDefaultArgExprClass:

5040 E

= cast<CXXDefaultArgExpr>(

E

)->getExpr();

5043 case

Stmt::CXXDefaultInitExprClass:

5044 E

= cast<CXXDefaultInitExpr>(

E

)->getExpr();

5049CFGBlock

*CFGBuilder::VisitChildrenForTemporaryDtors(

Stmt

*

E

,

5050 bool

ExternallyDestructed,

5051

TempDtorContext &Context) {

5052 if

(isa<LambdaExpr>(

E

)) {

5064 if

(

CFGBlock

*R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))

5070CFGBlock

*CFGBuilder::VisitBinaryOperatorForTemporaryDtors(

5071 BinaryOperator

*

E

,

bool

ExternallyDestructed, TempDtorContext &Context) {

5072 if

(

E

->isCommaOp()) {

5075 CFGBlock

*LHSBlock = VisitForTemporaryDtors(

E

->getLHS(),

false

, Context);

5076 CFGBlock

*RHSBlock = VisitForTemporaryDtors(

E

->getRHS(), ExternallyDestructed, Context);

5077 return

RHSBlock ? RHSBlock : LHSBlock;

5080 if

(

E

->isLogicalOp()) {

5081

VisitForTemporaryDtors(

E

->getLHS(),

false

, Context);

5082

TryResult RHSExecuted = tryEvaluateBool(

E

->getLHS());

5083 if

(RHSExecuted.isKnown() &&

E

->getOpcode() == BO_LOr)

5084

RHSExecuted.negate();

5089

TempDtorContext RHSContext(

5091

VisitForTemporaryDtors(

E

->getRHS(),

false

, RHSContext);

5092

InsertTempDtorDecisionBlock(RHSContext);

5097 if

(

E

->isAssignmentOp()) {

5100 CFGBlock

*RHSBlock = VisitForTemporaryDtors(

E

->getRHS(),

false

, Context);

5101 CFGBlock

*LHSBlock = VisitForTemporaryDtors(

E

->getLHS(),

false

, Context);

5102 return

LHSBlock ? LHSBlock : RHSBlock;

5106 return

VisitChildrenForTemporaryDtors(

E

, ExternallyDestructed, Context);

5109CFGBlock

*CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(

5113 CFGBlock

*B = VisitForTemporaryDtors(

E

->getSubExpr(),

true

, Context);

5114 if

(!ExternallyDestructed) {

5126 Block

= createNoReturnBlock();

5127

}

else if

(Context.needsTempDtorBranch()) {

5131 Block

= createBlock();

5135 if

(Context.needsTempDtorBranch()) {

5136

Context.setDecisionPoint(Succ,

E

);

5138

appendTemporaryDtor(

Block

,

E

);

5145void

CFGBuilder::InsertTempDtorDecisionBlock(

const

TempDtorContext &Context,

5147 if

(!Context.TerminatorExpr) {

5151

assert(Context.TerminatorExpr);

5152 CFGBlock

*Decision = createBlock(

false

);

5155

addSuccessor(Decision,

Block

, !Context.KnownExecuted.isFalse());

5156

addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,

5157

!Context.KnownExecuted.isTrue());

5161CFGBlock

*CFGBuilder::VisitConditionalOperatorForTemporaryDtors(

5163

TempDtorContext &Context) {

5164

VisitForTemporaryDtors(

E

->getCond(),

false

, Context);

5167

TryResult ConditionVal = tryEvaluateBool(

E

->getCond());

5168

TryResult NegatedVal = ConditionVal;

5169 if

(NegatedVal.isKnown()) NegatedVal.negate();

5171

TempDtorContext TrueContext(

5173

VisitForTemporaryDtors(

E

->getTrueExpr(), ExternallyDestructed, TrueContext);

5176 Block

= ConditionBlock;

5177

Succ = ConditionSucc;

5178

TempDtorContext FalseContext(

5180

VisitForTemporaryDtors(

E

->getFalseExpr(), ExternallyDestructed, FalseContext);

5182 if

(TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {

5183

InsertTempDtorDecisionBlock(FalseContext, TrueBlock);

5184

}

else if

(TrueContext.TerminatorExpr) {

5186

InsertTempDtorDecisionBlock(TrueContext);

5188

InsertTempDtorDecisionBlock(FalseContext);

5194

AddStmtChoice asc) {

5195 if

(asc.alwaysAdd(*

this

,

D

)) {

5207 for

(

Stmt

*S : llvm::reverse(

Used

)) {

5208

assert(S &&

"Expected non-null used-in-clause child."

);

5213 if

(!

D

->isStandaloneDirective()) {

5214 Stmt

*S =

D

->getRawStmt();

5215 if

(!isa<CompoundStmt>(S))

5216

addLocalScopeAndDtors(S);

5228 bool

first_block =

begin

() ==

end

();

5236

Entry = Exit = &

back

();

5245

CFGBuilder Builder(

C

, BO);

5246 return

Builder.buildCFG(

D

, Statement);

5261 auto

IteratorAndFlag =

Visited

.insert(B);

5262 if

(!IteratorAndFlag.second) {

5268 const CFGBlock

*FirstReachableB =

nullptr

;

5270 if

(!AB.isReachable())

5273 if

(FirstReachableB ==

nullptr

) {

5274

FirstReachableB = &*AB;

5281 if

(!FirstReachableB) {

5287

B = FirstReachableB;

5307

llvm_unreachable(

"getDestructorDecl should only be used with " 5310 const VarDecl

*var = castAs<CFGAutomaticObjDtor>().getVarDecl();

5318 if

(

const Expr

*

Init

= var->getInit()) {

5336 const CXXDeleteExpr

*DE = castAs<CFGDeleteDtor>().getDeleteExpr();

5345

castAs<CFGTemporaryDtor>().getBindTemporaryExpr();

5350 const FieldDecl

*field = castAs<CFGMemberDtor>().getFieldDecl();

5365

llvm_unreachable(

"getKind() returned bogus value"

);

5373

: ReachableBlock(IsReachable ? B : nullptr),

5374

UnreachableBlock(!IsReachable ? B : nullptr,

5375

B && IsReachable ? AB_Normal : AB_Unreachable) {}

5378

: ReachableBlock(B),

5379

UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,

5380

B == AlternateBlock ? AB_Alternate : AB_Normal) {}

5388

UnreachableB->Preds.push_back(

AdjacentBlock

(

this

,

false

),

C

);

5403 if

(S->isAllEnumCasesCovered()) {

5405 if

(!L || !isa<CaseStmt>(L))

5421 using

StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;

5422 using

DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;

5426 signed

currentBlock = 0;

5427 unsigned

currStmt = 0;

5438

BI != BEnd; ++BI, ++j ) {

5439 if

(std::optional<CFGStmt> SE = BI->getAs<

CFGStmt

>()) {

5441

std::pair<unsigned, unsigned>

P

((*I)->getBlockID(), j);

5442

StmtMap[

stmt

] =

P

;

5444 switch

(

stmt

->getStmtClass()) {

5445 case

Stmt::DeclStmtClass:

5446

DeclMap[cast<DeclStmt>(

stmt

)->getSingleDecl()] =

P

;

5448 case

Stmt::IfStmtClass: {

5449 const VarDecl

*var = cast<IfStmt>(

stmt

)->getConditionVariable();

5454 case

Stmt::ForStmtClass: {

5455 const VarDecl

*var = cast<ForStmt>(

stmt

)->getConditionVariable();

5460 case

Stmt::WhileStmtClass: {

5462

cast<WhileStmt>(

stmt

)->getConditionVariable();

5464

DeclMap[

var

] =

P

;

5467 case

Stmt::SwitchStmtClass: {

5469

cast<SwitchStmt>(

stmt

)->getConditionVariable();

5471

DeclMap[

var

] =

P

;

5474 case

Stmt::CXXCatchStmtClass: {

5476

cast<CXXCatchStmt>(

stmt

)->getExceptionDecl();

5478

DeclMap[

var

] =

P

;

5489

~StmtPrinterHelper()

override

=

default

;

5491 const LangOptions

&getLangOpts()

const

{

return

LangOpts; }

5492 void

setBlockID(

signed

i) { currentBlock = i; }

5493 void

setStmtID(

unsigned

i) { currStmt = i; }

5495 bool

handledStmt(

Stmt

*S, raw_ostream &OS)

override

{

5496

StmtMapTy::iterator I = StmtMap.find(S);

5498 if

(I == StmtMap.end())

5501 if

(currentBlock >= 0 && I->second.first == (

unsigned

) currentBlock

5502

&& I->second.second == currStmt) {

5506

OS <<

"[B"

<< I->second.first <<

"."

<< I->second.second <<

"]"

;

5510 bool

handleDecl(

const Decl

*

D

, raw_ostream &OS) {

5511

DeclMapTy::iterator I = DeclMap.find(

D

);

5513 if

(I == DeclMap.end())

5516 if

(currentBlock >= 0 && I->second.first == (

unsigned

) currentBlock

5517

&& I->second.second == currStmt) {

5521

OS <<

"[B"

<< I->second.first <<

"."

<< I->second.second <<

"]"

;

5526class

CFGBlockTerminatorPrint

5527

:

public StmtVisitor

<CFGBlockTerminatorPrint,void> {

5529

StmtPrinterHelper* Helper;

5533

CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,

5535

: OS(os), Helper(helper), Policy(Policy) {

5539 void

VisitIfStmt(

IfStmt

*I) {

5542 C

->printPretty(OS, Helper, Policy);

5546 void

VisitStmt(

Stmt

*Terminator) {

5550 void

VisitDeclStmt(

DeclStmt

*DS) {

5552

OS <<

"static init "

<< VD->

getName

();

5555 void

VisitForStmt(

ForStmt

*F) {

5561 C

->printPretty(OS, Helper, Policy);

5571 C

->printPretty(OS, Helper, Policy);

5574 void

VisitDoStmt(

DoStmt

*

D

) {

5575

OS <<

"do ... while "

;

5576 if

(

Stmt

*

C

=

D

->getCond())

5577 C

->printPretty(OS, Helper, Policy);

5580 void

VisitSwitchStmt(

SwitchStmt

*Terminator) {

5585 void

VisitCXXTryStmt(

CXXTryStmt

*) { OS <<

"try ..."

; }

5587 void

VisitObjCAtTryStmt(

ObjCAtTryStmt

*) { OS <<

"@try ..."

; }

5589 void

VisitSEHTryStmt(

SEHTryStmt

*CS) { OS <<

"__try ..."

; }

5592 if

(

Stmt

*Cond =

C

->getCond())

5594

OS <<

" ? ... : ..."

;

5598

OS <<

"__builtin_choose_expr( "

;

5599 if

(

Stmt

*Cond =

C

->getCond())

5607 T

->printPretty(OS, Helper, Policy);

5627

llvm_unreachable(

"Invalid logical operator."

);

5631 void

VisitExpr(

Expr

*

E

) {

5637 switch

(

T

.getKind()) {

5639

Visit(

T

.getStmt());

5642

OS <<

"(Temp Dtor) "

;

5643

Visit(

T

.getStmt());

5646

OS <<

"(See if most derived ctor has already initialized vbases)"

;

5664

IE->printPretty(OS, &Helper,

PrintingPolicy

(Helper.getLangOpts()));

5668

OS <<

" (Base initializer)"

;

5670

OS <<

" (Delegating initializer)"

;

5672

OS <<

" (Member initializer)"

;

5676

StmtPrinterHelper &Helper,

5682 const auto

*SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);

5689

cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);

5691

Stmts.push_back(CICC->getCXXBindTemporaryExpr());

5695 const auto

*SDSCC = cast<SimpleVariableConstructionContext>(CC);

5696

Stmts.push_back(SDSCC->getDeclStmt());

5700 const auto

*CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);

5701

Stmts.push_back(CDSCC->getDeclStmt());

5702

Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());

5706 const auto

*NECC = cast<NewAllocatedObjectConstructionContext>(CC);

5707

Stmts.push_back(NECC->getCXXNewExpr());

5711 const auto

*RSCC = cast<SimpleReturnedValueConstructionContext>(CC);

5712

Stmts.push_back(RSCC->getReturnStmt());

5717

cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);

5718

Stmts.push_back(RSCC->getReturnStmt());

5719

Stmts.push_back(RSCC->getCXXBindTemporaryExpr());

5723 const auto

*TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);

5724

Stmts.push_back(TOCC->getCXXBindTemporaryExpr());

5725

Stmts.push_back(TOCC->getMaterializedTemporaryExpr());

5729 const auto

*TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);

5730

Stmts.push_back(TOCC->getCXXBindTemporaryExpr());

5731

Stmts.push_back(TOCC->getMaterializedTemporaryExpr());

5732

Stmts.push_back(TOCC->getConstructorAfterElision());

5736 const auto

*LCC = cast<LambdaCaptureConstructionContext>(CC);

5737

Helper.handledStmt(

const_cast<LambdaExpr

*

>

(LCC->getLambdaExpr()), OS);

5738

OS <<

"+"

<< LCC->getIndex();

5742 const auto

*ACC = cast<ArgumentConstructionContext>(CC);

5743 if

(

const Stmt

*BTE = ACC->getCXXBindTemporaryExpr()) {

5745

Helper.handledStmt(

const_cast<Stmt

*

>

(BTE), OS);

5748

Helper.handledStmt(

const_cast<Expr

*

>

(ACC->getCallLikeExpr()), OS);

5749

OS <<

"+"

<< ACC->getIndex();

5753 for

(

auto

I: Stmts)

5756

Helper.handledStmt(

const_cast<Stmt

*

>

(I), OS);

5760static void print_elem

(raw_ostream &OS, StmtPrinterHelper &Helper,

5765

StmtPrinterHelper Helper(

nullptr

, LangOpts);

5769static void print_elem

(raw_ostream &OS, StmtPrinterHelper &Helper,

5771 switch

(

E

.getKind()) {

5777

assert(S !=

nullptr

&&

"Expecting non-null Stmt"

);

5780 if

(

const StmtExpr

*SE = dyn_cast<StmtExpr>(S)) {

5783 auto

Children = Sub->children();

5784 if

(Children.begin() != Children.end()) {

5795

Helper.handledStmt(B->

getRHS

(),OS);

5800

S->printPretty(OS, &Helper,

PrintingPolicy

(Helper.getLangOpts()));

5803 if

(isa<CXXOperatorCallExpr>(S))

5804

OS <<

" (OperatorCall)"

;

5805

OS <<

" (CXXRecordTypedCall"

;

5808

}

else if

(isa<CXXOperatorCallExpr>(S)) {

5809

OS <<

" (OperatorCall)"

;

5810

}

else if

(isa<CXXBindTemporaryExpr>(S)) {

5811

OS <<

" (BindTemporary)"

;

5813

OS <<

" (CXXConstructExpr"

;

5814 if

(std::optional<CFGConstructor> CE =

E

.getAs<

CFGConstructor

>()) {

5817

OS <<

", "

<< CCE->getType() <<

")"

;

5818

}

else if

(

const CastExpr

*CE = dyn_cast<CastExpr>(S)) {

5820

<<

", "

<< CE->

getType

() <<

")"

;

5838

Helper.handleDecl(VD, OS);

5845 T

.getUnqualifiedType().print(OS,

PrintingPolicy

(Helper.getLangOpts()));

5846

OS <<

"() (Implicit destructor)\n"

;

5851

OS <<

"CleanupFunction (" 5857

OS <<

" (Lifetime ends)\n"

;

5861

OS <<

E

.castAs<

CFGLoopExit

>().getLoopStmt()->getStmtClassName() <<

" (LoopExit)\n"

;

5865

OS <<

"CFGScopeBegin("

;

5872

OS <<

"CFGScopeEnd("

;

5879

OS <<

"CFGNewAllocator("

;

5881

AllocExpr->getType().print(OS,

PrintingPolicy

(Helper.getLangOpts()));

5892

Helper.handledStmt(cast<Stmt>(DelExpr->

getArgument

()), OS);

5893

OS <<

"->~"

<< RD->getName().str() <<

"()"

;

5894

OS <<

" (Implicit destructor)\n"

;

5901

OS <<

" (Base object destructor)\n"

;

5908

OS <<

"this->"

<< FD->

getName

();

5910

OS <<

" (Member object destructor)\n"

;

5919

OS <<

"() (Temporary object destructor)\n"

;

5927

StmtPrinterHelper &Helper,

bool

print_edges,

5933

OS.changeColor(raw_ostream::YELLOW,

true

);

5938

OS <<

" (ENTRY)]\n"

;

5939 else if

(&B == &cfg->

getExit

())

5940

OS <<

" (EXIT)]\n"

;

5942

OS <<

" (INDIRECT GOTO DISPATCH)]\n"

;

5944

OS <<

" (NORETURN)]\n"

;

5960 if

(

const Expr

*LHS =

C

->getLHS())

5962 if

(

const Expr

*RHS =

C

->getRHS()) {

5966

}

else if

(isa<DefaultStmt>(

Label

))

5977 if

(

const VarDecl

*PD = CS->getCatchParamDecl())

5983

OS <<

"__except ("

;

5988

llvm_unreachable(

"Invalid label statement in CFGBlock."

);

5997

I !=

E

; ++I, ++j ) {

6002

OS << llvm::format(

"%3d"

, j) <<

": "

;

6004

Helper.setStmtID(j);

6012

OS.changeColor(raw_ostream::GREEN);

6016

Helper.setBlockID(-1);

6019

CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);

6030 const

raw_ostream::Colors Color = raw_ostream::BLUE;

6032

OS.changeColor(Color);

6040

OS.changeColor(Color);

6043

I !=

E

; ++I, ++i) {

6048 bool

Reachable =

true

;

6051

B = I->getPossiblyUnreachableBlock();

6056

OS <<

"(Unreachable)"

;

6067 const

raw_ostream::Colors Color = raw_ostream::MAGENTA;

6069

OS.changeColor(Color);

6077

OS.changeColor(Color);

6080

I !=

E

; ++I, ++i) {

6086 bool

Reachable =

true

;

6089

B = I->getPossiblyUnreachableBlock();

6095

OS <<

"(Unreachable)"

;

6116

StmtPrinterHelper Helper(

this

, LO);

6122 for

(

const_iterator

I = Blocks.begin(),

E

= Blocks.end() ; I !=

E

; ++I) {

6124 if

(&(**I) == &getEntry() || &(**I) == &getExit())

6154

StmtPrinterHelper Helper(cfg, LO);

6162

CFGBlockTerminatorPrint TPrinter(OS,

nullptr

,

PrintingPolicy

(LO));

6168 bool

AddQuotes)

const

{

6170

llvm::raw_string_ostream TempOut(Buf);

6193 if

(llvm::any_of(*Blk, [](

const CFGElement

&Elm) {

6194 if

(std::optional<CFGStmt> StmtElm = Elm.

getAs

<

CFGStmt

>())

6195 if

(isa<CXXThrowExpr>(StmtElm->getStmt()))

6214

DFSWorkList.push_back(StartBlk);

6215 while

(!DFSWorkList.empty()) {

6216 const CFGBlock

*Blk = DFSWorkList.back();

6217

DFSWorkList.pop_back();

6227 for

(

const auto

&Succ : Blk->

succs

()) {

6228 if

(

const CFGBlock

*SuccBlk = Succ.getReachableBlock()) {

6232

DFSWorkList.push_back(SuccBlk);

6261 const Stmt

*Cond = StmtElem->getStmt();

6262 if

(isa<ObjCForCollectionStmt>(Cond) || isa<DeclStmt>(Cond))

6275 Expr

*

E

=

nullptr

;

6281 case

Stmt::CXXForRangeStmtClass:

6282 E

= cast<CXXForRangeStmt>(

Terminator

)->getCond();

6285 case

Stmt::ForStmtClass:

6289 case

Stmt::WhileStmtClass:

6293 case

Stmt::DoStmtClass:

6297 case

Stmt::IfStmtClass:

6301 case

Stmt::ChooseExprClass:

6305 case

Stmt::IndirectGotoStmtClass:

6306 E

= cast<IndirectGotoStmt>(

Terminator

)->getTarget();

6309 case

Stmt::SwitchStmtClass:

6313 case

Stmt::BinaryConditionalOperatorClass:

6314 E

= cast<BinaryConditionalOperator>(

Terminator

)->getCond();

6317 case

Stmt::ConditionalOperatorClass:

6318 E

= cast<ConditionalOperator>(

Terminator

)->getCond();

6321 case

Stmt::BinaryOperatorClass:

6325 case

Stmt::ObjCForCollectionStmtClass:

6342

StmtPrinterHelper H(

this

, LO);

6344

llvm::ViewGraph(

this

,

"CFG"

);

6356

llvm::raw_string_ostream Out(OutStr);

6359 if

(OutStr[0] ==

'\n'

) OutStr.erase(OutStr.begin());

6362 for

(

unsigned

i = 0; i != OutStr.length(); ++i)

6363 if

(OutStr[i] ==

'\n'

) {

6365

OutStr.insert(OutStr.begin()+i+1,

'l'

);

Defines the clang::ASTContext interface.

Defines enum values for all the target-independent builtin functions.

static StmtPrinterHelper * GraphHelper

static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E)

static const Expr * tryTransformToIntOrEnumConstant(const Expr *E)

Helper for tryNormalizeBinaryOperator.

static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXCtorInitializer *I)

static bool IsIntegerLiteralConstantExpr(const Expr *E)

Returns true on constant values based around a single IntegerLiteral.

static SourceLocation GetEndLoc(Decl *D)

static bool CanThrow(Expr *E, ASTContext &Ctx)

static bool isFallthroughStatement(const AttributedStmt *A)

static void print_block(raw_ostream &OS, const CFG *cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors)

static bool isImmediateSinkBlock(const CFGBlock *Blk)

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...

static const VariableArrayType * FindVA(const Type *t)

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...

static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC)

static bool shouldAddCase(bool &switchExclusivelyCovered, const Expr::EvalResult *switchCond, const CaseStmt *CS, ASTContext &Ctx)

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...

static TryResult bothKnownTrue(TryResult R1, TryResult R2)

clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the ExceptionSpecificationType enumeration and various utility functions.

Defines the clang::Expr interface and subclasses for C++ expressions.

llvm::DenseSet< const void * > Visited

static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::LangOptions interface.

Defines the clang::SourceLocation class and associated facilities.

Defines various enumerations that describe declaration and type specifiers.

Defines the Objective-C statement AST node classes.

C Language Family Type Representation.

llvm::APInt getValue() const

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

const ConstantArrayType * getAsConstantArrayType(QualType T) const

const LangOptions & getLangOpts() const

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

CanQualType BoundMemberTy

const ArrayType * getAsArrayType(QualType T) const

Type Query functions.

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...

AddrLabelExpr - The GNU address of label extension, representing &&label.

LabelDecl * getLabel() const

Represents a loop initializing the elements of an array.

OpaqueValueExpr * getCommonExpr() const

Get the common subexpression shared by all initializations (the source array).

Expr * getSubExpr() const

Get the initializer to use for each array element.

Represents an array type, per C99 6.7.5.2 - Array Declarators.

Represents an attribute applied to a statement.

ArrayRef< const Attr * > getAttrs() const

BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...

OpaqueValueExpr * getOpaqueValue() const

getOpaqueValue - Return the opaque value placeholder.

Expr * getCommon() const

getCommon - Return the common expression, written to the left of the condition.

A builtin binary operation expression such as "x + y" or "x <= y".

static bool isLogicalOp(Opcode Opc)

static bool isRelationalOp(Opcode Opc)

static bool isAssignmentOp(Opcode Opc)

static bool isEqualityOp(Opcode Opc)

A class which contains all the information about a particular captured value.

BlockExpr - Adaptor class for mixing a BlockDecl with expressions.

BreakStmt - This represents a break.

void push_back(const_reference Elt, BumpVectorContext &C)

Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...

const VarDecl * getVarDecl() const

Represents C++ object destructor implicitly generated for base object in destructor.

This class represents a potential adjacent block in the CFG.

AdjacentBlock(CFGBlock *B, bool IsReachable)

Construct an AdjacentBlock with a possibly unreachable block.

CFGBlock * getReachableBlock() const

Get the reachable block, if one exists.

CFGBlock * getPossiblyUnreachableBlock() const

Get the potentially unreachable block.

unsigned IgnoreNullPredecessors

unsigned IgnoreDefaultsWithCoveredEnums

Represents a single basic block in a source-level CFG.

void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)

void printTerminator(raw_ostream &OS, const LangOptions &LO) const

printTerminator - A simple pretty printer of the terminator of a CFGBlock.

void setLoopTarget(const Stmt *loopTarget)

bool isInevitablySinking() const

Returns true if the block would eventually end with a sink (a noreturn node).

size_t getIndexInCFG() const

void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)

static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)

reverse_iterator rbegin()

void setTerminator(CFGTerminator Term)

void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)

void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)

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.

ElementList::const_iterator const_iterator

bool hasNoReturnElement() const

void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)

void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)

void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)

void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const

printTerminatorJson - Pretty-prints the terminator in JSON format.

void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)

Stmt * Label

An (optional) label that prefixes the executable statements in the block.

CFGTerminator getTerminator() const

succ_iterator succ_begin()

Stmt * getTerminatorStmt()

void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)

AdjacentBlocks::const_iterator const_pred_iterator

unsigned pred_size() const

void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)

void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)

pred_iterator pred_begin()

void appendCleanupFunction(const VarDecl *VD, BumpVectorContext &C)

void setLabel(Stmt *Statement)

unsigned getBlockID() const

void appendStmt(Stmt *statement, BumpVectorContext &C)

void setHasNoReturnElement()

const Expr * getLastCondition() const

void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, BumpVectorContext &C)

Stmt * getTerminatorCondition(bool StripParens=true)

void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)

Adds a (potentially unreachable) successor block to the current block.

void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)

AdjacentBlocks::const_iterator const_succ_iterator

CFGTerminator Terminator

The terminator for a basic block that indicates the type of control-flow that occurs between a block ...

unsigned succ_size() const

Represents a function call that returns a C++ object by value.

static bool isCXXRecordTypedCall(const Expr *E)

Returns true when call expression CE needs to be represented by CFGCXXRecordTypedCall,...

virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)

virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)

virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)

virtual void compareBitwiseOr(const BinaryOperator *B)

Represents C++ constructor call.

Represents C++ object destructor generated from a call to delete.

const CXXDeleteExpr * getDeleteExpr() const

const CXXRecordDecl * getCXXRecordDecl() const

Represents a top-level expression in a basic block.

void dumpToStream(llvm::raw_ostream &OS) const

std::optional< T > getAs() const

Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...

const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const

Represents C++ base or member initializer from constructor's initialization list.

CXXCtorInitializer * getInitializer() const

Represents the point where the lifetime of an automatic object ends.

const VarDecl * getVarDecl() const

Represents the point where a loop ends.

Represents C++ object destructor implicitly generated for member object in destructor.

Represents C++ allocator call.

const CXXNewExpr * getAllocatorExpr() const

Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt.

const VarDecl * getVarDecl() const

Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...

const VarDecl * getVarDecl() const

const Stmt * getStmt() const

Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...

Represents CFGBlock terminator statement.

@ TemporaryDtorsBranch

A branch in control flow of destructors of temporaries.

@ VirtualBaseBranch

A shortcut around virtual base initializers.

@ StmtBranch

A branch that corresponds to a statement in the code, such as an if-statement.

bool PruneTriviallyFalseEdges

bool AddStaticInitBranches

bool OmitImplicitValueInitializers

ForcedBlkExprs ** forcedBlkExprs

bool AddCXXDefaultInitExprInAggregates

bool AddCXXDefaultInitExprInCtors

bool alwaysAdd(const Stmt *stmt) const

bool AddRichCXXConstructors

bool AddVirtualBaseBranches

llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs

bool MarkElidedCXXConstructors

Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.

unsigned size() const

Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...

void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const

print - A simple pretty printer of a CFG that outputs to an ostream.

bool isLinear() const

Returns true if the CFG has no branches.

static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)

Builds a CFG from an AST.

llvm::BumpPtrAllocator & getAllocator()

CFGBlock * createBlock()

Create a new block in the CFG.

CFGBlock * getIndirectGotoBlock()

void dump(const LangOptions &LO, bool ShowColors) const

dump - A simple pretty printer of a CFG that outputs to stderr.

void viewCFG(const LangOptions &LO) const

Represents a base class of a C++ class.

QualType getType() const

Retrieves the type of the base class.

Represents binding an expression to a temporary.

CXXTemporary * getTemporary()

CXXCatchStmt - This represents a C++ catch block.

Stmt * getHandlerBlock() const

VarDecl * getExceptionDecl() const

Represents a call to a C++ constructor.

CXXConstructorDecl * getConstructor() const

Get the constructor that this expression will (ultimately) call.

Represents a C++ constructor within a class.

Represents a C++ base or member initializer.

bool isDelegatingInitializer() const

Determine whether this initializer is creating a delegating constructor.

Expr * getInit() const

Get the initializer.

TypeSourceInfo * getTypeSourceInfo() const

Returns the declarator information for a base class or delegating initializer.

bool isBaseInitializer() const

Determine whether this initializer is initializing a base class.

const Type * getBaseClass() const

If this is a base class initializer, returns the type of the base class.

FieldDecl * getAnyMember() const

A use of a default initializer in a constructor or in aggregate initialization.

Represents a delete expression for memory deallocation and destructor calls, e.g.

QualType getDestroyedType() const

Retrieve the type being destroyed.

Represents a C++ destructor within a class.

CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...

Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr....

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".

Represents a C++ struct/union/class.

bool hasTrivialDestructor() const

Determine whether this class has a trivial destructor (C++ [class.dtor]p3)

base_class_range vbases()

bool hasDefinition() const

CXXDestructorDecl * getDestructor() const

Returns the destructor decl for this class.

bool isAnyDestructorNoReturn() const

Returns true if the class destructor, or any implicitly invoked destructors are marked noreturn.

Represents a C++ functional cast expression that builds a temporary object.

Represents a C++ temporary.

const CXXDestructorDecl * getDestructor() const

A C++ throw-expression (C++ [except.throw]).

CXXTryStmt - A C++ try block, including all handlers.

CXXCatchStmt * getHandler(unsigned i)

unsigned getNumHandlers() const

CompoundStmt * getTryBlock()

A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

CaseStmt - Represent a case statement.

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

ChooseExpr - GNU builtin-in function __builtin_choose_expr.

CompoundStmt - This represents a group of statements like { stmt stmt }.

reverse_body_iterator body_rbegin()

Represents the canonical version of C arrays with a specified constant size.

ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...

Represents a single point (AST node) in the program that requires attention during construction of an...

@ ElidableConstructorKind

Construction context can be seen as a linked list of multiple layers.

static const ConstructionContextLayer * create(BumpVectorContext &C, const ConstructionContextItem &Item, const ConstructionContextLayer *Parent=nullptr)

const ConstructionContextItem & getItem() const

ConstructionContext's subclasses describe different ways of constructing an object in C++.

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...

@ CXX17ElidedCopyVariableKind

@ ElidedTemporaryObjectKind

@ SimpleTemporaryObjectKind

@ CXX17ElidedCopyConstructorInitializerKind

@ SimpleConstructorInitializerKind

@ SimpleReturnedValueKind

@ CXX17ElidedCopyReturnedValueKind

ContinueStmt - This represents a continue.

Represents a 'co_return' statement in the C++ Coroutines TS.

Expr * getOperand() const

Retrieve the operand of the 'co_return' statement.

Expr * getPromiseCall() const

Retrieve the promise call that results from this 'co_return' statement.

Represents an expression that might suspend coroutine execution; either a co_await or co_yield expres...

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

std::reverse_iterator< decl_iterator > reverse_decl_iterator

bool isSingleDecl() const

isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.

decl_iterator decl_begin()

const Decl * getSingleDecl() const

reverse_decl_iterator decl_rend()

reverse_decl_iterator decl_rbegin()

Decl - This represents one declaration (or definition), e.g.

virtual Stmt * getBody() const

getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...

SourceLocation getLocation() const

DoStmt - This represents a 'do/while' stmt.

Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...

This represents one expression.

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,...

static QualType findBoundMemberType(const Expr *expr)

Given an expression of bound-member type, find the type of the member.

llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const

EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

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...

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.

bool isKnownToHaveBooleanValue(bool Semantic=true) const

isKnownToHaveBooleanValue - Return true if this is an integer expression that is known to return 0 or...

Represents a member of a struct/union/class.

ForStmt - This represents a 'for (init;cond;inc)' stmt.

VarDecl * getConditionVariable() const

Retrieve the variable declared in this "for" statement, if any.

DeclStmt * getConditionVariableDeclStmt()

If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...

const Expr * getSubExpr() const

Represents a function declaration or definition.

Represents a prototype with parameter type info, e.g.

FunctionType - C99 6.7.5.3 - Function Declarators.

This represents a GCC inline-assembly statement extension.

GotoStmt - This represents a direct goto.

LabelDecl * getLabel() const

IfStmt - This represents an if/then/else.

DeclStmt * getConditionVariableDeclStmt()

If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...

VarDecl * getConditionVariable()

Retrieve the variable declared in this "if" statement, if any.

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

IndirectGotoStmt - This represents an indirect goto.

Describes an C or C++ initializer list.

unsigned getNumInits() const

Expr ** getInits()

Retrieve the set of initializers.

LabelStmt - Represents a label, which has a substatement.

LabelDecl * getDecl() const

const char * getName() const

A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

Represents a prvalue temporary that is written into memory so that a reference can bind to it.

StorageDuration getStorageDuration() const

Retrieve the storage duration for the materialized temporary.

Expr * getSubExpr() const

Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

std::string getQualifiedNameAsString() const

This is a basic class for representing single OpenMP executable directive.

static llvm::iterator_range< used_clauses_child_iterator > used_clauses_children(ArrayRef< OMPClause * > Clauses)

Represents Objective-C's @catch statement.

const Stmt * getCatchBody() const

Represents Objective-C's @synchronized statement.

Represents Objective-C's @throw statement.

Represents Objective-C's @try ... @catch ... @finally statement.

const ObjCAtFinallyStmt * getFinallyStmt() const

Retrieve the @finally statement, if any.

const Stmt * getTryBody() const

Retrieve the @try body.

catch_range catch_stmts()

Represents Objective-C's @autoreleasepool Statement.

Represents Objective-C's collection statement.

An expression that sends a message to the given Objective-C object or class.

OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.

PseudoObjectExpr - An expression which accesses a pseudo-object l-value.

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const

QualType getNonReferenceType() const

If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...

field_range fields() const

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

CompoundStmt * getBlock() const

Expr * getFilterExpr() const

Represents a __leave statement.

CompoundStmt * getTryBlock() const

SEHFinallyStmt * getFinallyHandler() const

SEHExceptStmt * getExceptHandler() const

Returns 0 if not defined.

Scope - A scope is a transient data structure that is used while parsing the program.

Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag)

Encodes a location in the source.

StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).

CompoundStmt * getSubStmt()

StmtVisitor - This class implements a simple visitor for Stmt subclasses.

Stmt - This represents one statement.

void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const

const Stmt * stripLabelLikeStatements() const

Strip off all label-like statements.

StmtClass getStmtClass() const

const char * getStmtClassName() const

SwitchStmt - This represents a 'switch' stmt.

bool isAllEnumCasesCovered() const

Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...

VarDecl * getConditionVariable()

Retrieve the variable declared in this "switch" statement, if any.

SwitchCase * getSwitchCaseList()

DeclStmt * getConditionVariableDeclStmt()

If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

QualType getType() const

Return the type wrapped by this type source info.

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isBlockPointerType() const

bool isFunctionPointerType() const

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

const Type * getBaseElementTypeUnsafe() const

Get the base element type of this type, potentially discarding type qualifiers.

bool isVariablyModifiedType() const

Whether this type is a variably-modified type (C99 6.7.5).

bool isUnsignedIntegerType() const

Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...

const T * getAs() const

Member-template getAs<specific type>'.

UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.

UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...

Represents a variable declaration or definition.

bool isStaticLocal() const

Returns true if a variable with function scope is a static local variable.

const Expr * getInit() const

bool hasLocalStorage() const

Returns true if a variable with function scope is a non-static local variable.

Represents a C array with a specified size that is not an integer-constant-expression.

WhileStmt - This represents a 'while' stmt.

DeclStmt * getConditionVariableDeclStmt()

If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...

VarDecl * getConditionVariable()

Retrieve the variable declared in this "while" statement, if any.

const AstTypeMatcher< ArrayType > arrayType

Matches all kinds of arrays.

const internal::VariadicAllOfMatcher< Stmt > stmt

Matches statements.

constexpr Variable var(Literal L)

Returns the variable of L.

unsigned kind

All of the diagnostics that can be emitted by the frontend.

bool Sub(InterpState &S, CodePtr OpPC)

bool NE(InterpState &S, CodePtr OpPC)

bool LE(InterpState &S, CodePtr OpPC)

bool Cast(InterpState &S, CodePtr OpPC)

The JSON file list parser is used to communicate input to InstallAPI.

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

FunctionType::ExtInfo getFunctionExtInfo(const Type &t)

bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)

bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)

@ SD_FullExpression

Full-expression storage duration (for temporaries).

std::string JsonFormat(StringRef RawSR, bool AddQuotes)

bool operator!=(CanQual< T > x, CanQual< U > y)

const FunctionProtoType * T

Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)

Diagnostic wrappers for TextAPI types for error reporting.

float __ovld __cnfn distance(float, float)

Returns the distance between p0 and p1.

EvalResult is a struct with detailed info about an evaluated expression.

APValue Val

Val - This is the value the expression can be folded to.

Describes how types, statements, expressions, and declarations should be printed.

unsigned IncludeNewlines

When true, include newlines after statements like "break", etc.

Iterator for iterating over Stmt * arrays that contain only T *.

DOTGraphTraits(bool isSimple=false)

static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph)


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4