clang: lib/Analysis/CFG.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

39#include "llvm/ADT/APFloat.h"

40#include "llvm/ADT/APInt.h"

41#include "llvm/ADT/APSInt.h"

42#include "llvm/ADT/ArrayRef.h"

43#include "llvm/ADT/DenseMap.h"

44#include "llvm/ADT/STLExtras.h"

45#include "llvm/ADT/SetVector.h"

46#include "llvm/ADT/SmallPtrSet.h"

47#include "llvm/ADT/SmallVector.h"

48#include "llvm/Support/Allocator.h"

49#include "llvm/Support/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"

56#include

57#include

58#include

59#include

60#include

61#include

62#include

63

64using namespace clang;

65

67 if (VarDecl *VD = dyn_cast(D))

68 if (Expr *Ex = VD->getInit())

69 return Ex->getSourceRange().getEnd();

71}

72

73

74

75

76

78

80

81

82

83 if (const auto *CE = dyn_cast(E)) {

84 if (CE->getCastKind() != CK_IntegralCast &&

85 CE->getCastKind() != CK_IntegralToFloating)

86 return false;

87 E = CE->getSubExpr();

88 }

89

90

91 if (const auto *UO = dyn_cast(E)) {

92 if (UO->getOpcode() != UO_Minus)

93 return false;

94 E = UO->getSubExpr();

95 }

97}

98

99

100

101

105 return E;

108 return nullptr;

109}

110

111

112

113

114

115

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

119

122

123 if (Constant == nullptr) {

124

125 if (Op == BO_GT)

126 Op = BO_LT;

127 else if (Op == BO_GE)

128 Op = BO_LE;

129 else if (Op == BO_LT)

130 Op = BO_GT;

131 else if (Op == BO_LE)

132 Op = BO_GE;

133

134 MaybeDecl = B->getRHS();

136 }

137

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

139}

140

141

142

143

144

145

146

148

149

151 return false;

152

153

155 return true;

156

157

158

162

164 const DeclContext *DC1 = Decl1->getDeclContext();

165 const DeclContext *DC2 = Decl2->getDeclContext();

166

168 return DC1 == DC2;

169}

170

171namespace {

172

173class CFGBuilder;

174

175

176

177

178

179

180

181

182

183

184

185

186

187class AddStmtChoice {

188public:

189 enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };

190

191 AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}

192

193 bool alwaysAdd(CFGBuilder &builder,

194 const Stmt *stmt) const;

195

196

197

198 AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {

199 return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);

200 }

201

202private:

203 Kind kind;

204};

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227class LocalScope {

228public:

229 using AutomaticVarsTy = BumpVector<VarDecl *>;

230

231

232

233 class const_iterator {

234 const LocalScope* Scope = nullptr;

235

236

237

238 unsigned VarIter = 0;

239

240 public:

241

242

243

244 const_iterator() = default;

245

246

247

248 const_iterator(const LocalScope& S, unsigned I)

249 : Scope(&S), VarIter(I) {

250

251

252 if (VarIter == 0 && Scope)

253 *this = Scope->Prev;

254 }

255

256 VarDecl *const* operator->() const {

257 assert(Scope && "Dereferencing invalid iterator is not allowed");

258 assert(VarIter != 0 && "Iterator has invalid value of VarIter member");

259 return &Scope->Vars[VarIter - 1];

260 }

261

262 const VarDecl *getFirstVarInScope() const {

263 assert(Scope && "Dereferencing invalid iterator is not allowed");

264 assert(VarIter != 0 && "Iterator has invalid value of VarIter member");

265 return Scope->Vars[0];

266 }

267

269 return *this->operator->();

270 }

271

272 const_iterator &operator++() {

273 if (!Scope)

274 return *this;

275

276 assert(VarIter != 0 && "Iterator has invalid value of VarIter member");

277 --VarIter;

278 if (VarIter == 0)

279 *this = Scope->Prev;

280 return *this;

281 }

282 const_iterator operator++(int) {

283 const_iterator P = *this;

284 ++*this;

285 return P;

286 }

287

288 bool operator==(const const_iterator &rhs) const {

289 return Scope == rhs.Scope && VarIter == rhs.VarIter;

290 }

291 bool operator!=(const const_iterator &rhs) const {

292 return !(*this == rhs);

293 }

294

295 explicit operator bool() const {

296 return *this != const_iterator();

297 }

298

299 int distance(const_iterator L);

300 const_iterator shared_parent(const_iterator L);

301 bool pointsToFirstDeclaredVar() { return VarIter == 1; }

302 bool inSameLocalScope(const_iterator rhs) { return Scope == rhs.Scope; }

303 };

304

305private:

306 BumpVectorContext ctx;

307

308

309 AutomaticVarsTy Vars;

310

311

312

313 const_iterator Prev;

314

315public:

316

317 LocalScope(BumpVectorContext ctx, const_iterator P)

318 : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}

319

320

321 const_iterator begin() const { return const_iterator(*this, Vars.size()); }

322

323 void addVar(VarDecl *VD) {

324 Vars.push_back(VD, ctx);

325 }

326};

327

328}

329

330

331

332

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

334 int D = 0;

335 const_iterator F = *this;

336 while (F.Scope != L.Scope) {

337 assert(F != const_iterator() &&

338 "L iterator is not reachable from F iterator.");

339 D += F.VarIter;

340 F = F.Scope->Prev;

341 }

342 D += F.VarIter - L.VarIter;

343 return D;

344}

345

346

347

348

349

350LocalScope::const_iterator

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

352

353

354 if ((*this == const_iterator()) || (L == const_iterator())) {

355 return const_iterator();

356 }

357

358 const_iterator F = *this;

359 if (F.inSameLocalScope(L)) {

360

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

362 return F;

363 }

364

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

366 while (true) {

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

368 if (L == const_iterator())

369 break;

370 L = L.Scope->Prev;

371 }

372

373 while (true) {

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

375

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

377 return F;

378 }

379 assert(F != const_iterator() &&

380 "L iterator is not reachable from F iterator.");

381 F = F.Scope->Prev;

382 }

383}

384

385namespace {

386

387

388

389

390struct BlockScopePosPair {

391 CFGBlock *block = nullptr;

392 LocalScope::const_iterator scopePosition;

393

394 BlockScopePosPair() = default;

395 BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)

396 : block(b), scopePosition(scopePos) {}

397};

398

399

400

401

402

403class TryResult {

404 int X = -1;

405

406public:

407 TryResult() = default;

408 TryResult(bool b) : X(b ? 1 : 0) {}

409

410 bool isTrue() const { return X == 1; }

411 bool isFalse() const { return X == 0; }

412 bool isKnown() const { return X >= 0; }

413

414 void negate() {

415 assert(isKnown());

416 X ^= 0x1;

417 }

418};

419

420}

421

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

424 return TryResult();

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

426}

427

428namespace {

429

430class reverse_children {

431 llvm::SmallVector<Stmt *, 12> childrenBuf;

432 ArrayRef<Stmt *> children;

433

434public:

435 reverse_children(Stmt *S, ASTContext &Ctx);

436

437 using iterator = ArrayRef<Stmt *>::reverse_iterator;

438

439 iterator begin() const { return children.rbegin(); }

440 iterator end() const { return children.rend(); }

441};

442

443}

444

445reverse_children::reverse_children(Stmt *S, ASTContext &Ctx) {

446 if (CallExpr *CE = dyn_cast(S)) {

447 children = CE->getRawSubExprs();

448 return;

449 }

450

452

453 case Stmt::InitListExprClass: {

455 children = llvm::ArrayRef(reinterpret_cast<Stmt **>(IE->getInits()),

457 return;

458 }

459

460 case Stmt::AttributedStmtClass: {

461

462

463

464

466 for (const auto *Attr : AS->getAttrs()) {

467 if (const auto *AssumeAttr = dyn_cast(Attr)) {

468 Expr *AssumeExpr = AssumeAttr->getAssumption();

470 childrenBuf.push_back(AssumeExpr);

471 }

472 }

473 }

474

475

476

477 llvm::append_range(childrenBuf, AS->children());

478 children = childrenBuf;

479 return;

480 }

481 default:

482 break;

483 }

484

485

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

487

488

489 children = childrenBuf;

490}

491

492namespace {

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507class CFGBuilder {

508 using JumpTarget = BlockScopePosPair;

509 using JumpSource = BlockScopePosPair;

510

511 ASTContext *Context;

512 std::unique_ptr cfg;

513

514

515 CFGBlock *Block = nullptr;

516

517

518 CFGBlock *Succ = nullptr;

519

520 JumpTarget ContinueJumpTarget;

521 JumpTarget BreakJumpTarget;

522 JumpTarget SEHLeaveJumpTarget;

523 CFGBlock *SwitchTerminatedBlock = nullptr;

524 CFGBlock *DefaultCaseBlock = nullptr;

525

526

527

528

529

530 CFGBlock *TryTerminatedBlock = nullptr;

531

532

533 LocalScope::const_iterator ScopePos;

534

535

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

537 LabelMapTy LabelMap;

538

539

540

541 using BackpatchBlocksTy = std::vector;

542 BackpatchBlocksTy BackpatchBlocks;

543

544

545 using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;

546 LabelSetTy AddressTakenLabels;

547

548

549

550

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

552 ConstructionContextMap;

553

554 bool badCFG = false;

555 const CFG::BuildOptions &BuildOpts;

556

557

558 bool switchExclusivelyCovered = false;

559 Expr::EvalResult *switchCond = nullptr;

560

561 CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;

562 const Stmt *lastLookup = nullptr;

563

564

565

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

567 CachedBoolEvalsTy CachedBoolEvals;

568

569public:

570 explicit CFGBuilder(ASTContext *astContext,

571 const CFG::BuildOptions &buildOpts)

572 : Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}

573

574

575 std::unique_ptr buildCFG(const Decl *D, Stmt *Statement);

576

577 bool alwaysAdd(const Stmt *stmt);

578

579private:

580

581 CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);

582 CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);

583 CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);

584 CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);

585 CFGBlock *VisitBreakStmt(BreakStmt *B);

586 CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);

587 CFGBlock *VisitCaseStmt(CaseStmt *C);

588 CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);

589 CFGBlock *VisitCompoundStmt(CompoundStmt *C, bool ExternallyDestructed);

590 CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,

591 AddStmtChoice asc);

592 CFGBlock *VisitContinueStmt(ContinueStmt *C);

593 CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,

594 AddStmtChoice asc);

595 CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);

596 CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);

597 CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);

598 CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);

599 CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);

600 CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,

601 AddStmtChoice asc);

602 CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,

603 AddStmtChoice asc);

604 CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);

605 CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);

606 CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);

607 CFGBlock *VisitDeclStmt(DeclStmt *DS);

608 CFGBlock *VisitDeclSubExpr(DeclStmt *DS);

609 CFGBlock *VisitDefaultStmt(DefaultStmt *D);

610 CFGBlock *VisitDoStmt(DoStmt *D);

611 CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,

612 AddStmtChoice asc, bool ExternallyDestructed);

613 CFGBlock *VisitForStmt(ForStmt *F);

614 CFGBlock *VisitGotoStmt(GotoStmt *G);

615 CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);

616 CFGBlock *VisitIfStmt(IfStmt *I);

617 CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);

618 CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);

619 CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);

620 CFGBlock *VisitLabelStmt(LabelStmt *L);

621 CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);

622 CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);

623 CFGBlock *VisitLogicalOperator(BinaryOperator *B);

624 std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,

625 Stmt *Term,

626 CFGBlock *TrueBlock,

627 CFGBlock *FalseBlock);

628 CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,

629 AddStmtChoice asc);

630 CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);

631 CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);

632 CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);

633 CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);

634 CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);

635 CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);

636 CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);

637 CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);

638 CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);

639 CFGBlock *VisitReturnStmt(Stmt *S);

640 CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,

641 AddStmtChoice asc);

642 CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);

643 CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);

644 CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);

645 CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);

646 CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);

647 CFGBlock *VisitSwitchStmt(SwitchStmt *S);

648 CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,

649 AddStmtChoice asc);

650 CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);

651 CFGBlock *VisitWhileStmt(WhileStmt *W);

652 CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);

653

654 CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,

655 bool ExternallyDestructed = false);

656 CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);

657 CFGBlock *VisitChildren(Stmt *S);

658 CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);

659 CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,

660 AddStmtChoice asc);

661

662 void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,

663 const Stmt *S) {

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

665 appendScopeBegin(B, VD, S);

666 }

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696 struct TempDtorContext {

697 TempDtorContext() = default;

698 TempDtorContext(TryResult KnownExecuted)

699 : IsConditional(true), KnownExecuted(KnownExecuted) {}

700

701

702

703

704

705

706

707 bool needsTempDtorBranch() const {

708 return IsConditional && !TerminatorExpr;

709 }

710

711

712

713 void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {

714 Succ = S;

715 TerminatorExpr = E;

716 }

717

718 const bool IsConditional = false;

719 const TryResult KnownExecuted = true;

720 CFGBlock *Succ = nullptr;

721 CXXBindTemporaryExpr *TerminatorExpr = nullptr;

722 };

723

724

725

726 CFGBlock *VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,

727 TempDtorContext &Context);

728 CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E, bool ExternallyDestructed,

729 TempDtorContext &Context);

730 CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E,

731 bool ExternallyDestructed,

732 TempDtorContext &Context);

733 CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(

734 CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context);

735 CFGBlock *VisitConditionalOperatorForTemporaryDtors(

736 AbstractConditionalOperator *E, bool ExternallyDestructed,

737 TempDtorContext &Context);

738 void InsertTempDtorDecisionBlock(const TempDtorContext &Context,

739 CFGBlock *FalseSucc = nullptr);

740

741

742 CFGBlock *NYS() {

743 badCFG = true;

745 }

746

747

748

749 void consumeConstructionContext(const ConstructionContextLayer *Layer,

750 Expr *E);

751

752

753

754

755

756

757 void findConstructionContexts(const ConstructionContextLayer *Layer,

758 Stmt *Child);

759

760

761

762

763 template <typename CallLikeExpr,

764 typename = std::enable_if_t<

765 std::is_base_of_v<CallExpr, CallLikeExpr> ||

766 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||

767 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>

768 void findConstructionContextsForArguments(CallLikeExpr *E) {

769 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {

770 Expr *Arg = E->getArg(i);

772 findConstructionContexts(

774 ConstructionContextItem(E, i)),

775 Arg);

776 }

777 }

778

779

780

781

782 void cleanupConstructionContext(Expr *E);

783

784 void autoCreateBlock() { if (Block) Block = createBlock(); }

785

786 CFGBlock *createBlock(bool add_successor = true);

787 CFGBlock *createNoReturnBlock();

788

789 CFGBlock *addStmt(Stmt *S) {

790 return Visit(S, AddStmtChoice::AlwaysAdd);

791 }

792

793 CFGBlock *addInitializer(CXXCtorInitializer *I);

794 void addLoopExit(const Stmt *LoopStmt);

795 void addAutomaticObjHandling(LocalScope::const_iterator B,

796 LocalScope::const_iterator E, Stmt *S);

797 void addAutomaticObjDestruction(LocalScope::const_iterator B,

798 LocalScope::const_iterator E, Stmt *S);

799 void addScopeExitHandling(LocalScope::const_iterator B,

800 LocalScope::const_iterator E, Stmt *S);

801 void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);

802 void addScopeChangesHandling(LocalScope::const_iterator SrcPos,

803 LocalScope::const_iterator DstPos,

804 Stmt *S);

805 CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,

806 CFGBlock *SrcBlk,

807 LocalScope::const_iterator DstPost,

808 CFGBlock *DstBlk);

809

810

811 LocalScope* createOrReuseLocalScope(LocalScope* Scope);

812

813 void addLocalScopeForStmt(Stmt *S);

814 LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,

815 LocalScope* Scope = nullptr);

816 LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);

817

818 void addLocalScopeAndDtors(Stmt *S);

819

820 const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {

822 return nullptr;

823

824 const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);

825 if (!Layer)

826 return nullptr;

827

828 cleanupConstructionContext(E);

830 Layer);

831 }

832

833

834

835 void appendStmt(CFGBlock *B, const Stmt *S) {

836 if (alwaysAdd(S) && cachedEntry)

837 cachedEntry->second = B;

838

839

841 B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());

842 }

843

844 void appendConstructor(CXXConstructExpr *CE) {

846 if (C && C->isNoReturn())

847 Block = createNoReturnBlock();

848 else

849 autoCreateBlock();

850

851 if (const ConstructionContext *CC =

852 retrieveAndCleanupConstructionContext(CE)) {

853 Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());

854 return;

855 }

856

857

858 Block->appendStmt(CE, cfg->getBumpVectorContext());

859 }

860

861 void appendCall(CFGBlock *B, CallExpr *CE) {

862 if (alwaysAdd(CE) && cachedEntry)

863 cachedEntry->second = B;

864

865 if (const ConstructionContext *CC =

866 retrieveAndCleanupConstructionContext(CE)) {

868 return;

869 }

870

871

872 B->appendStmt(CE, cfg->getBumpVectorContext());

873 }

874

875 void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {

877 }

878

879 void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {

881 }

882

883 void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {

885 }

886

887 void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {

889 }

890

891 void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {

892 if (alwaysAdd(ME) && cachedEntry)

893 cachedEntry->second = B;

894

895 if (const ConstructionContext *CC =

896 retrieveAndCleanupConstructionContext(ME)) {

898 return;

899 }

900

901 B->appendStmt(ME, cfg->getBumpVectorContext());

902 }

903

904 void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {

906 }

907

908 void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {

910 }

911

912 void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {

914 }

915

916 void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {

918 }

919

920 void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) {

921 B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());

922 }

923

924 void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {

926 }

927

928 void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {

929 B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),

930 cfg->getBumpVectorContext());

931 }

932

933

934

935 void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {

936 B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),

937 cfg->getBumpVectorContext());

938 }

939

940 void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {

943 }

944

945 void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {

947 B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());

948 }

949

950

951

952

953 TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {

956

957 const IntegerLiteral *IntLiteral = dyn_cast(LHSExpr);

958 const Expr *BoolExpr = RHSExpr;

959 bool IntFirst = true;

960 if (!IntLiteral) {

961 IntLiteral = dyn_cast(RHSExpr);

962 BoolExpr = LHSExpr;

963 IntFirst = false;

964 }

965

967 return TryResult();

968

969 llvm::APInt IntValue = IntLiteral->getValue();

970 if ((IntValue == 1) || (IntValue == 0))

971 return TryResult();

972

974 !IntValue.isNegative();

975

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

978

979

980 return TryResult(IntFirst == IntLarger);

981 } else {

982

983

984 return TryResult(IntFirst != IntLarger);

985 }

986 }

987

988

989

990

991

992 TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {

995

996 std::optionalllvm::APInt IntLiteral1 =

997 getIntegerLiteralSubexpressionValue(LHSExpr);

998 const Expr *BoolExpr = RHSExpr;

999

1000 if (!IntLiteral1) {

1001 IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);

1002 BoolExpr = LHSExpr;

1003 }

1004

1005 if (!IntLiteral1)

1006 return TryResult();

1007

1008 const BinaryOperator *BitOp = dyn_cast(BoolExpr);

1009 if (BitOp && (BitOp->getOpcode() == BO_And ||

1013

1014 std::optionalllvm::APInt IntLiteral2 =

1015 getIntegerLiteralSubexpressionValue(LHSExpr2);

1016

1017 if (!IntLiteral2)

1018 IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);

1019

1020 if (!IntLiteral2)

1021 return TryResult();

1022

1023 if ((BitOp->getOpcode() == BO_And &&

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

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

1030 return TryResult(B->getOpcode() != BO_EQ);

1031 }

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

1034 return TryResult();

1035 }

1036 return TryResult(B->getOpcode() != BO_EQ);

1037 }

1038

1039 return TryResult();

1040 }

1041

1042

1043

1044

1045

1046

1047

1048 std::optionalllvm::APInt

1049 getIntegerLiteralSubexpressionValue(const Expr *E) {

1050

1051

1052 if (const auto *UnOp = dyn_cast(E->IgnoreParens())) {

1053

1054

1055 const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();

1056

1057 if (const auto *IntLiteral = dyn_cast(SubExpr)) {

1058

1060

1061

1062 switch (UnOp->getOpcode()) {

1063 case UO_Plus:

1065 case UO_Minus:

1067 case UO_Not:

1068 return ~Value;

1069 case UO_LNot:

1071 default:

1072 assert(false && "Unexpected unary operator!");

1073 return std::nullopt;

1074 }

1075 }

1076 } else if (const auto *IntLiteral =

1077 dyn_cast(E->IgnoreParens()))

1078 return IntLiteral->getValue();

1079

1080 return std::nullopt;

1081 }

1082

1083 template

1084 TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,

1085 const APFloatOrInt &Value1,

1086 const APFloatOrInt &Value2) {

1087 switch (Relation) {

1088 default:

1089 return TryResult();

1090 case BO_EQ:

1091 return TryResult(Value1 == Value2);

1092 case BO_NE:

1093 return TryResult(Value1 != Value2);

1094 case BO_LT:

1095 return TryResult(Value1 < Value2);

1096 case BO_LE:

1097 return TryResult(Value1 <= Value2);

1098 case BO_GT:

1099 return TryResult(Value1 > Value2);

1100 case BO_GE:

1101 return TryResult(Value1 >= Value2);

1102 }

1103 }

1104

1105

1106

1107

1108

1109

1110

1111

1112 TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {

1116

1117 auto CheckLogicalOpWithNegatedVariable = [this, B](const Expr *E1,

1118 const Expr *E2) {

1119 if (const auto *Negate = dyn_cast(E1)) {

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

1122 bool AlwaysTrue = B->getOpcode() == BO_LOr;

1125 return TryResult(AlwaysTrue);

1126 }

1127 }

1128 return TryResult();

1129 };

1130

1131 TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);

1132 if (Result.isKnown())

1134 Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);

1135 if (Result.isKnown())

1137

1138 const auto *LHS = dyn_cast(LHSExpr);

1139 const auto *RHS = dyn_cast(RHSExpr);

1140 if (!LHS || !RHS)

1141 return {};

1142

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

1144 return {};

1145

1146 const Expr *DeclExpr1;

1147 const Expr *NumExpr1;

1150

1151 if (!DeclExpr1 || !NumExpr1)

1152 return {};

1153

1154 const Expr *DeclExpr2;

1155 const Expr *NumExpr2;

1158

1159 if (!DeclExpr2 || !NumExpr2)

1160 return {};

1161

1162

1164 return {};

1165

1166

1167

1169 return {};

1170

1171

1172 Expr::EvalResult L1Result, L2Result;

1175 return {};

1176

1177

1178

1179

1180

1181

1182

1183

1184

1185

1186

1187 auto AnalyzeConditions = [&](const auto &Values,

1190 bool AlwaysTrue = true, AlwaysFalse = true;

1191

1192

1193 bool LHSAlwaysTrue = true, LHSAlwaysFalse = true;

1194 bool RHSAlwaysTrue = true, RHSAlwaysFalse = true;

1195

1196 for (const auto &Value : Values) {

1197 TryResult Res1 =

1198 analyzeLogicOperatorCondition(*BO1, Value, Values[1] );

1199 TryResult Res2 =

1200 analyzeLogicOperatorCondition(*BO2, Value, Values[3] );

1201

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

1203 return {};

1204

1205 const bool IsAnd = B->getOpcode() == BO_LAnd;

1206 const bool Combine = IsAnd ? (Res1.isTrue() && Res2.isTrue())

1207 : (Res1.isTrue() || Res2.isTrue());

1208

1209 AlwaysTrue &= Combine;

1210 AlwaysFalse &= !Combine;

1211

1212 LHSAlwaysTrue &= Res1.isTrue();

1213 LHSAlwaysFalse &= Res1.isFalse();

1214 RHSAlwaysTrue &= Res2.isTrue();

1215 RHSAlwaysFalse &= Res2.isFalse();

1216 }

1217

1218 if (AlwaysTrue || AlwaysFalse) {

1219 if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&

1220 !RHSAlwaysFalse && BuildOpts.Observer) {

1222 }

1223 return TryResult(AlwaysTrue);

1224 }

1225 return {};

1226 };

1227

1228

1231 llvm::APSInt L1 = L1Result.Val.getInt();

1232 llvm::APSInt L2 = L2Result.Val.getInt();

1233

1234

1235 if (L1.isSigned() != L2.isSigned() ||

1236 L1.getBitWidth() != L2.getBitWidth())

1237 return {};

1238

1239

1240

1241 const llvm::APSInt Values[] = {

1242

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

1244

1245 L1,

1246

1247 ((L1 < L2) ? L1 : L2) +

1248 llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1), L1.isUnsigned()),

1249

1250 L2,

1251

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

1253 };

1254

1255 return AnalyzeConditions(Values, &BO1, &BO2);

1256 }

1257

1258

1261 llvm::APFloat L1 = L1Result.Val.getFloat();

1262 llvm::APFloat L2 = L2Result.Val.getFloat();

1263

1264

1265

1266

1267

1271

1272 if (Order > 0) {

1273

1274 if (llvm::APFloat::opOK !=

1275 L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven,

1276 &Ignored))

1277 return {};

1278 } else if (Order < 0)

1279

1280 if (llvm::APFloat::opOK !=

1281 L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven,

1282 &Ignored))

1283 return {};

1284

1285 llvm::APFloat MidValue = L1;

1286 MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven);

1287 MidValue.divide(llvm::APFloat(MidValue.getSemantics(), "2.0"),

1288 llvm::APFloat::rmNearestTiesToEven);

1289

1290 const llvm::APFloat Values[] = {

1291 llvm::APFloat::getSmallest(L1.getSemantics(), true), L1, MidValue, L2,

1292 llvm::APFloat::getLargest(L2.getSemantics(), false),

1293 };

1294

1295 return AnalyzeConditions(Values, &BO1, &BO2);

1296 }

1297

1298 return {};

1299 }

1300

1301

1302 TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) {

1303 const Expr *LHSConstant =

1305 const Expr *RHSConstant =

1307

1308 if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))

1309 return {};

1310

1311 const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;

1312

1313 Expr::EvalResult Result;

1315 return {};

1316

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

1318 return {};

1319

1322

1323 return TryResult(true);

1324 }

1325

1326

1327 bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {

1329 return false;

1333 }

1334

1335

1336

1337 TryResult tryEvaluateBool(Expr *S) {

1340 return {};

1341

1342 if (BinaryOperator *Bop = dyn_cast(S)) {

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

1344

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

1346 if (I != CachedBoolEvals.end())

1347 return I->second;

1348

1349

1350 TryResult Result = evaluateAsBooleanConditionNoCache(S);

1351 CachedBoolEvals[S] = Result;

1353 }

1354 else {

1355 switch (Bop->getOpcode()) {

1356 default: break;

1357

1358

1359 case BO_Mul:

1360 case BO_And: {

1361

1362

1363 Expr::EvalResult LHSResult;

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

1365 llvm::APSInt IntVal = LHSResult.Val.getInt();

1366 if (!IntVal.getBoolValue()) {

1367 return TryResult(false);

1368 }

1369 }

1370 Expr::EvalResult RHSResult;

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

1372 llvm::APSInt IntVal = RHSResult.Val.getInt();

1373 if (!IntVal.getBoolValue()) {

1374 return TryResult(false);

1375 }

1376 }

1377 }

1378 break;

1379 }

1380 }

1381 }

1382

1383 return evaluateAsBooleanConditionNoCache(S);

1384 }

1385

1386

1387 TryResult evaluateAsBooleanConditionNoCache(Expr *E) {

1388 if (BinaryOperator *Bop = dyn_cast(E)) {

1389 if (Bop->isLogicalOp()) {

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

1391 if (LHS.isKnown()) {

1392

1393

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

1395 return LHS.isTrue();

1396

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

1398 if (RHS.isKnown()) {

1399 if (Bop->getOpcode() == BO_LOr)

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

1401 else

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

1403 }

1404 } else {

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

1406 if (RHS.isKnown()) {

1407

1408

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

1410 return RHS.isTrue();

1411 } else {

1412 TryResult BopRes = checkIncorrectLogicOperator(Bop);

1413 if (BopRes.isKnown())

1414 return BopRes.isTrue();

1415 }

1416 }

1417

1418 return {};

1419 } else if (Bop->isEqualityOp()) {

1420 TryResult BopRes = checkIncorrectEqualityOperator(Bop);

1421 if (BopRes.isKnown())

1422 return BopRes.isTrue();

1423 } else if (Bop->isRelationalOp()) {

1424 TryResult BopRes = checkIncorrectRelationalOperator(Bop);

1425 if (BopRes.isKnown())

1426 return BopRes.isTrue();

1427 } else if (Bop->getOpcode() == BO_Or) {

1428 TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);

1429 if (BopRes.isKnown())

1430 return BopRes.isTrue();

1431 }

1432 }

1433

1437

1438 return {};

1439 }

1440

1441 bool hasTrivialDestructor(const VarDecl *VD) const;

1442 bool needsAutomaticDestruction(const VarDecl *VD) const;

1443};

1444

1445}

1446

1447Expr *

1449 if (!AILE)

1450 return nullptr;

1451

1453 while (const auto *E = dyn_cast(AILEInit))

1454 AILEInit = E->getSubExpr();

1455

1456 return AILEInit;

1457}

1458

1459inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,

1461 return builder.alwaysAdd(stmt) || kind == AlwaysAdd;

1462}

1463

1464bool CFGBuilder::alwaysAdd(const Stmt *stmt) {

1466

1468 return shouldAdd;

1469

1470 if (lastLookup == stmt) {

1471 if (cachedEntry) {

1472 assert(cachedEntry->first == stmt);

1473 return true;

1474 }

1475 return shouldAdd;

1476 }

1477

1478 lastLookup = stmt;

1479

1480

1482

1483 if (!fb) {

1484

1485 assert(!cachedEntry);

1486 return shouldAdd;

1487 }

1488

1489 CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);

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

1491 cachedEntry = nullptr;

1492 return shouldAdd;

1493 }

1494

1495 cachedEntry = &*itr;

1496 return true;

1497}

1498

1499

1500

1502 while (const ArrayType *vt = dyn_cast(t)) {

1503 if (const VariableArrayType *vat = dyn_cast(vt))

1504 if (vat->getSizeExpr())

1505 return vat;

1506

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

1508 }

1509

1510 return nullptr;

1511}

1512

1513void CFGBuilder::consumeConstructionContext(

1514 const ConstructionContextLayer *Layer, Expr *E) {

1517 if (const ConstructionContextLayer *PreviouslyStoredLayer =

1518 ConstructionContextMap.lookup(E)) {

1519 (void)PreviouslyStoredLayer;

1520

1521

1522 assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&

1523 "Already within a different construction context!");

1524 } else {

1525 ConstructionContextMap[E] = Layer;

1526 }

1527}

1528

1529void CFGBuilder::findConstructionContexts(

1530 const ConstructionContextLayer *Layer, Stmt *Child) {

1532 return;

1533

1534 if (!Child)

1535 return;

1536

1537 auto withExtraLayer = [this, Layer](const ConstructionContextItem &Item) {

1539 Layer);

1540 };

1541

1542 switch(Child->getStmtClass()) {

1543 case Stmt::CXXConstructExprClass:

1544 case Stmt::CXXTemporaryObjectExprClass: {

1545

1548 findConstructionContexts(withExtraLayer(CE), CE->getArg(0));

1549 }

1550

1551 consumeConstructionContext(Layer, CE);

1552 break;

1553 }

1554

1555

1556

1557 case Stmt::CallExprClass:

1558 case Stmt::CXXMemberCallExprClass:

1559 case Stmt::CXXOperatorCallExprClass:

1560 case Stmt::UserDefinedLiteralClass:

1561 case Stmt::ObjCMessageExprClass: {

1564 consumeConstructionContext(Layer, E);

1565 break;

1566 }

1567 case Stmt::ExprWithCleanupsClass: {

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

1570 break;

1571 }

1572 case Stmt::CXXFunctionalCastExprClass: {

1574 findConstructionContexts(Layer, Cast->getSubExpr());

1575 break;

1576 }

1577 case Stmt::ImplicitCastExprClass: {

1579

1580 switch (Cast->getCastKind()) {

1581 case CK_NoOp:

1582 case CK_ConstructorConversion:

1583 findConstructionContexts(Layer, Cast->getSubExpr());

1584 break;

1585 default:

1586 break;

1587 }

1588 break;

1589 }

1590 case Stmt::CXXBindTemporaryExprClass: {

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

1593 break;

1594 }

1595 case Stmt::MaterializeTemporaryExprClass: {

1596

1597

1598

1599

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

1604 }

1605 break;

1606 }

1607 case Stmt::ConditionalOperatorClass: {

1611

1612

1613

1614

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

1617 break;

1618 }

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

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

1621 break;

1622 }

1623 case Stmt::InitListExprClass: {

1625 if (ILE->isTransparent()) {

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

1627 break;

1628 }

1629

1630 break;

1631 }

1632 case Stmt::ParenExprClass: {

1633

1634

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

1637 break;

1638 }

1639 default:

1640 break;

1641 }

1642}

1643

1644void CFGBuilder::cleanupConstructionContext(Expr *E) {

1646 "We should not be managing construction contexts!");

1647 assert(ConstructionContextMap.count(E) &&

1648 "Cannot exit construction context without the context!");

1649 ConstructionContextMap.erase(E);

1650}

1651

1652

1653

1654

1655

1656

1657std::unique_ptr CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {

1658 assert(cfg.get());

1659 if (!Statement)

1660 return nullptr;

1661

1662

1663

1664

1665 Succ = createBlock();

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

1667 Block = nullptr;

1668

1669

1670 LocalScope *paramScope = nullptr;

1671 if (const auto *FD = dyn_cast_or_null(D))

1672 for (ParmVarDecl *PD : FD->parameters())

1673 paramScope = addLocalScopeForVarDecl(PD, paramScope);

1674

1676 if (const CXXDestructorDecl *DD = dyn_cast_or_null(D))

1677 addImplicitDtorsForDestructor(DD);

1678

1679

1680 CFGBlock *B = addStmt(Statement);

1681

1682 if (badCFG)

1683 return nullptr;

1684

1685

1686

1687

1688

1689

1690

1691

1692

1693

1694

1695

1696

1697 if (const auto *CD = dyn_cast_or_null(D)) {

1698 CFGBlock *VBaseSucc = nullptr;

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

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

1702

1703

1704

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

1706 Block = createBlock();

1707 }

1708 B = addInitializer(I);

1709 if (badCFG)

1710 return nullptr;

1711 }

1712 if (VBaseSucc) {

1713

1714 Succ = VBaseSucc;

1715 B = createBlock();

1718 addSuccessor(B, Block, true);

1719 }

1720 }

1721

1722 if (B)

1723 Succ = B;

1724

1725

1726

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

1728 E = BackpatchBlocks.end(); I != E; ++I ) {

1729

1730 CFGBlock *B = I->block;

1731 if (auto *G = dyn_cast(B->getTerminator())) {

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

1733

1734

1735 if (LI == LabelMap.end())

1736 continue;

1737 JumpTarget JT = LI->second;

1738

1739 CFGBlock *SuccBlk = createScopeChangesHandlingBlock(

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

1741 addSuccessor(B, SuccBlk);

1742 } else if (auto *G = dyn_cast(B->getTerminator())) {

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

1744 for (auto *L : G->labels()) {

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

1746

1747

1748 if (LI == LabelMap.end())

1749 continue;

1750 JumpTarget JT = LI->second;

1751

1752 if (JT.block == Successor)

1753 continue;

1754 addSuccessor(B, JT.block);

1755 }

1756 I++;

1757 }

1758 }

1759

1760

1761 if (CFGBlock *B = cfg->getIndirectGotoBlock())

1762 for (LabelDecl *LD : AddressTakenLabels) {

1763

1764 LabelMapTy::iterator LI = LabelMap.find(LD);

1765

1766

1767

1768 if (LI == LabelMap.end()) continue;

1769

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

1771 }

1772

1773

1774 cfg->setEntry(createBlock());

1775

1777 assert(ConstructionContextMap.empty() &&

1778 "Not all construction contexts were cleaned up!");

1779

1780 return std::move(cfg);

1781}

1782

1783

1784

1785CFGBlock *CFGBuilder::createBlock(bool add_successor) {

1786 CFGBlock *B = cfg->createBlock();

1787 if (add_successor && Succ)

1788 addSuccessor(B, Succ);

1789 return B;

1790}

1791

1792

1793

1794

1795CFGBlock *CFGBuilder::createNoReturnBlock() {

1796 CFGBlock *B = createBlock(false);

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

1799 return B;

1800}

1801

1802

1803CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {

1806

1807 bool HasTemporaries = false;

1808

1809

1810

1814

1816

1817 TempDtorContext Context;

1819 false, Context);

1820 }

1821 }

1822

1823 autoCreateBlock();

1824 appendInitializer(Block, I);

1825

1827

1828

1830 dyn_cast(Init));

1831

1832 findConstructionContexts(

1834 AILEInit ? AILEInit : Init);

1835

1836 if (HasTemporaries) {

1837

1838

1840 }

1842 if (CXXDefaultInitExpr *Default = dyn_cast(Init)) {

1843

1844

1845

1846 autoCreateBlock();

1848 if (Stmt *Child = Default->getExpr())

1849 if (CFGBlock *R = Visit(Child))

1852 }

1853 }

1854 return Visit(Init);

1855 }

1856

1858}

1859

1860

1861

1863 bool *FoundMTE = nullptr) {

1864 while (true) {

1865

1866 Init = Init->IgnoreParens();

1867

1868

1870 Init = EWC->getSubExpr();

1871 continue;

1872 }

1873

1874

1876 = dyn_cast(Init)) {

1877 Init = MTE->getSubExpr();

1878 if (FoundMTE)

1879 *FoundMTE = true;

1880 continue;

1881 }

1882

1883

1884 const Expr *SkippedInit = Init->skipRValueSubobjectAdjustments();

1885 if (SkippedInit != Init) {

1886 Init = SkippedInit;

1887 continue;

1888 }

1889

1890 break;

1891 }

1892

1893 return Init->getType();

1894}

1895

1896

1897

1898void CFGBuilder::addLoopExit(const Stmt *LoopStmt){

1900 return;

1901 autoCreateBlock();

1902 appendLoopExit(Block, LoopStmt);

1903}

1904

1905

1906

1907

1908

1909

1910void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,

1911 LocalScope::const_iterator E,

1912 Stmt *S) {

1915 return;

1916

1917 if (B == E)

1918 return;

1919

1920

1921 if (B.inSameLocalScope(E)) {

1922 addAutomaticObjDestruction(B, E, S);

1923 return;

1924 }

1925

1926

1927 SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;

1928 LocalScopeEndMarkers.push_back(B);

1929 for (LocalScope::const_iterator I = B; I != E; ++I) {

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

1931 LocalScopeEndMarkers.push_back(I);

1932 }

1933 LocalScopeEndMarkers.push_back(E);

1934

1935

1936

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

1938 auto Pairwise =

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

1940 for (auto [E, B] : Pairwise) {

1941 if (!B.inSameLocalScope(E))

1942 addScopeExitHandling(B, E, S);

1943 addAutomaticObjDestruction(B, E, S);

1944 }

1945}

1946

1947

1948

1949

1950void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,

1951 LocalScope::const_iterator E,

1952 Stmt *S) {

1954 return;

1955

1956 if (B == E)

1957 return;

1958

1959 SmallVector<VarDecl *, 10> DeclsNeedDestruction;

1960 DeclsNeedDestruction.reserve(B.distance(E));

1961

1962 for (VarDecl* D : llvm::make_range(B, E))

1963 if (needsAutomaticDestruction(D))

1964 DeclsNeedDestruction.push_back(D);

1965

1966 for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {

1968

1969

1970

1971

1972 QualType Ty = VD->getType();

1976

1979 Block = createNoReturnBlock();

1980 }

1981

1982 autoCreateBlock();

1983

1984

1985

1986

1988 appendLifetimeEnds(Block, VD, S);

1989 if (BuildOpts.AddImplicitDtors && !hasTrivialDestructor(VD))

1990 appendAutomaticObjDtor(Block, VD, S);

1991 if (VD->hasAttr())

1992 appendCleanupFunction(Block, VD);

1993 }

1994}

1995

1996

1997

1998

1999

2000

2001void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,

2002 LocalScope::const_iterator E, Stmt *S) {

2003 assert(!B.inSameLocalScope(E));

2005 return;

2006

2008 autoCreateBlock();

2009 appendScopeEnd(Block, B.getFirstVarInScope(), S);

2010 }

2011

2013 return;

2014

2015

2016 SmallVector<VarDecl *, 10> DeclsTrivial;

2017 DeclsTrivial.reserve(B.distance(E));

2018

2019

2020

2021

2022 for (VarDecl* D : llvm::make_range(B, E))

2023 if (!needsAutomaticDestruction(D))

2024 DeclsTrivial.push_back(D);

2025

2026 if (DeclsTrivial.empty())

2027 return;

2028

2029 autoCreateBlock();

2030 for (VarDecl *VD : llvm::reverse(DeclsTrivial))

2031 appendLifetimeEnds(Block, VD, S);

2032}

2033

2034

2035

2036

2037

2038

2039void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,

2040 LocalScope::const_iterator DstPos,

2041 Stmt *S) {

2042 assert(Block && "Source block should be always crated");

2045 return;

2046 }

2047

2048 if (SrcPos == DstPos)

2049 return;

2050

2051

2052

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

2054

2055

2056 if (BuildOpts.AddScopes && !DstPos.inSameLocalScope(BasePos)) {

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

2058 if (I.pointsToFirstDeclaredVar())

2059 appendScopeBegin(Block, *I, S);

2060 }

2061

2062

2063

2064 addAutomaticObjHandling(SrcPos, BasePos, S);

2065}

2066

2067

2068

2069

2070

2071

2072CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(

2073 LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,

2074 LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {

2075 if (SrcPos == DstPos)

2076 return DstBlk;

2077

2079 (!BuildOpts.AddScopes || SrcPos.inSameLocalScope(DstPos)))

2080 return DstBlk;

2081

2082

2083

2084 SaveAndRestore save_Block(Block), save_Succ(Succ);

2085

2086

2087 Block = createBlock(false);

2090 addSuccessor(Block, DstBlk);

2091

2092

2093 addScopeChangesHandling(SrcPos, DstPos, Block->getTerminatorStmt());

2094

2095 assert(Block && "There should be at least one scope changing Block");

2097}

2098

2099

2100

2101void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {

2103 "Can be called only when dtors should be added");

2104 const CXXRecordDecl *RD = DD->getParent();

2105

2106

2107 for (const auto &VI : RD->vbases()) {

2108

2109

2110

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

2113 autoCreateBlock();

2114 appendBaseDtor(Block, &VI);

2115 }

2116 }

2117

2118

2119 for (const auto &BI : RD->bases()) {

2120 if (!BI.isVirtual()) {

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

2123 autoCreateBlock();

2124 appendBaseDtor(Block, &BI);

2125 }

2126 }

2127 }

2128

2129

2131 return;

2132 for (auto *FI : RD->fields()) {

2133

2134 QualType QT = FI->getType();

2135

2137 if (AT->isZeroSize())

2138 break;

2139 QT = AT->getElementType();

2140 }

2141

2144 autoCreateBlock();

2145 appendMemberDtor(Block, FI);

2146 }

2147 }

2148}

2149

2150

2151

2152LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {

2153 if (Scope)

2154 return Scope;

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

2156 return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);

2157}

2158

2159

2160

2161void CFGBuilder::addLocalScopeForStmt(Stmt *S) {

2164 return;

2165

2166 LocalScope *Scope = nullptr;

2167

2168

2169 if (CompoundStmt *CS = dyn_cast(S)) {

2170 for (auto *BI : CS->body()) {

2171 Stmt *SI = BI->stripLabelLikeStatements();

2172 if (DeclStmt *DS = dyn_cast(SI))

2173 Scope = addLocalScopeForDeclStmt(DS, Scope);

2174 }

2175 return;

2176 }

2177

2178

2179

2181 addLocalScopeForDeclStmt(DS);

2182}

2183

2184

2185

2186LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,

2187 LocalScope* Scope) {

2190 return Scope;

2191

2192 for (auto *DI : DS->decls())

2193 if (VarDecl *VD = dyn_cast(DI))

2194 Scope = addLocalScopeForVarDecl(VD, Scope);

2195 return Scope;

2196}

2197

2198bool CFGBuilder::needsAutomaticDestruction(const VarDecl *VD) const {

2199 return !hasTrivialDestructor(VD) || VD->hasAttr();

2200}

2201

2202bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const {

2203

2204 QualType QT = VD->getType();

2206

2207

2208

2209

2210

2211

2212

2213

2215 if (Init) {

2216

2217

2218

2219 return true;

2220 }

2221

2222

2223 bool FoundMTE = false;

2225 if (!FoundMTE)

2226 return true;

2227 }

2228

2229

2231 if (AT->isZeroSize())

2232 return true;

2233 QT = AT->getElementType();

2234 }

2235

2236

2239 return true;

2240}

2241

2242

2243

2244

2245LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,

2246 LocalScope* Scope) {

2249 return Scope;

2250

2251

2253 return Scope;

2254

2255

2256

2258 return Scope;

2259

2261 !needsAutomaticDestruction(VD)) {

2263 return Scope;

2264 }

2265

2266

2267 Scope = createOrReuseLocalScope(Scope);

2268 Scope->addVar(VD);

2269 ScopePos = Scope->begin();

2270 return Scope;

2271}

2272

2273

2274

2275void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {

2276 LocalScope::const_iterator scopeBeginPos = ScopePos;

2277 addLocalScopeForStmt(S);

2278 addAutomaticObjHandling(ScopePos, scopeBeginPos, S);

2279}

2280

2281

2282

2283

2284CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,

2285 bool ExternallyDestructed) {

2286 if (!S) {

2287 badCFG = true;

2288 return nullptr;

2289 }

2290

2291 if (Expr *E = dyn_cast(S))

2292 S = E->IgnoreParens();

2293

2295 if (auto *D = dyn_cast(S))

2296 return VisitOMPExecutableDirective(D, asc);

2297

2299 default:

2300 return VisitStmt(S, asc);

2301

2302 case Stmt::ImplicitValueInitExprClass:

2305 return VisitStmt(S, asc);

2306

2307 case Stmt::InitListExprClass:

2309

2310 case Stmt::AttributedStmtClass:

2312

2313 case Stmt::AddrLabelExprClass:

2315

2316 case Stmt::BinaryConditionalOperatorClass:

2318

2319 case Stmt::BinaryOperatorClass:

2321

2322 case Stmt::BlockExprClass:

2324

2325 case Stmt::BreakStmtClass:

2327

2328 case Stmt::CallExprClass:

2329 case Stmt::CXXOperatorCallExprClass:

2330 case Stmt::CXXMemberCallExprClass:

2331 case Stmt::UserDefinedLiteralClass:

2333

2334 case Stmt::CaseStmtClass:

2336

2337 case Stmt::ChooseExprClass:

2339

2340 case Stmt::CompoundStmtClass:

2341 return VisitCompoundStmt(cast(S), ExternallyDestructed);

2342

2343 case Stmt::ConditionalOperatorClass:

2345

2346 case Stmt::ContinueStmtClass:

2348

2349 case Stmt::CXXCatchStmtClass:

2351

2352 case Stmt::ExprWithCleanupsClass:

2354 asc, ExternallyDestructed);

2355

2356 case Stmt::CXXDefaultArgExprClass:

2357 case Stmt::CXXDefaultInitExprClass:

2358

2359

2360

2361

2362

2363

2364

2365

2366 return VisitStmt(S, asc);

2367

2368 case Stmt::CXXBindTemporaryExprClass:

2370

2371 case Stmt::CXXConstructExprClass:

2373

2374 case Stmt::CXXNewExprClass:

2376

2377 case Stmt::CXXDeleteExprClass:

2379

2380 case Stmt::CXXFunctionalCastExprClass:

2382

2383 case Stmt::CXXTemporaryObjectExprClass:

2385

2386 case Stmt::CXXThrowExprClass:

2388

2389 case Stmt::CXXTryStmtClass:

2391

2392 case Stmt::CXXTypeidExprClass:

2394

2395 case Stmt::CXXForRangeStmtClass:

2397

2398 case Stmt::DeclStmtClass:

2400

2401 case Stmt::DefaultStmtClass:

2403

2404 case Stmt::DoStmtClass:

2406

2407 case Stmt::ForStmtClass:

2409

2410 case Stmt::GotoStmtClass:

2412

2413 case Stmt::GCCAsmStmtClass:

2415

2416 case Stmt::IfStmtClass:

2418

2419 case Stmt::ImplicitCastExprClass:

2421

2422 case Stmt::ConstantExprClass:

2424

2425 case Stmt::IndirectGotoStmtClass:

2427

2428 case Stmt::LabelStmtClass:

2430

2431 case Stmt::LambdaExprClass:

2433

2434 case Stmt::MaterializeTemporaryExprClass:

2436 asc);

2437

2438 case Stmt::MemberExprClass:

2440

2441 case Stmt::NullStmtClass:

2443

2444 case Stmt::ObjCAtCatchStmtClass:

2446

2447 case Stmt::ObjCAutoreleasePoolStmtClass:

2449

2450 case Stmt::ObjCAtSynchronizedStmtClass:

2452

2453 case Stmt::ObjCAtThrowStmtClass:

2455

2456 case Stmt::ObjCAtTryStmtClass:

2458

2459 case Stmt::ObjCForCollectionStmtClass:

2461

2462 case Stmt::ObjCMessageExprClass:

2464

2465 case Stmt::OpaqueValueExprClass:

2467

2468 case Stmt::PseudoObjectExprClass:

2470

2471 case Stmt::ReturnStmtClass:

2472 case Stmt::CoreturnStmtClass:

2473 return VisitReturnStmt(S);

2474

2475 case Stmt::CoyieldExprClass:

2476 case Stmt::CoawaitExprClass:

2478

2479 case Stmt::SEHExceptStmtClass:

2481

2482 case Stmt::SEHFinallyStmtClass:

2484

2485 case Stmt::SEHLeaveStmtClass:

2487

2488 case Stmt::SEHTryStmtClass:

2490

2491 case Stmt::UnaryExprOrTypeTraitExprClass:

2493 asc);

2494

2495 case Stmt::StmtExprClass:

2497

2498 case Stmt::SwitchStmtClass:

2500

2501 case Stmt::UnaryOperatorClass:

2503

2504 case Stmt::WhileStmtClass:

2506

2507 case Stmt::ArrayInitLoopExprClass:

2509 }

2510}

2511

2512CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {

2513 if (asc.alwaysAdd(*this, S)) {

2514 autoCreateBlock();

2515 appendStmt(Block, S);

2516 }

2517

2518 return VisitChildren(S);

2519}

2520

2521

2522CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {

2523 CFGBlock *B = Block;

2524

2525

2526

2527 reverse_children RChildren(S, *Context);

2528 for (Stmt *Child : RChildren) {

2529 if (Child)

2530 if (CFGBlock *R = Visit(Child))

2531 B = R;

2532 }

2533 return B;

2534}

2535

2536CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {

2537 if (asc.alwaysAdd(*this, ILE)) {

2538 autoCreateBlock();

2539 appendStmt(Block, ILE);

2540 }

2541 CFGBlock *B = Block;

2542

2543 reverse_children RChildren(ILE, *Context);

2544 for (Stmt *Child : RChildren) {

2545 if (!Child)

2546 continue;

2547 if (CFGBlock *R = Visit(Child))

2548 B = R;

2550 if (auto *DIE = dyn_cast(Child))

2551 if (Stmt *Child = DIE->getExpr())

2552 if (CFGBlock *R = Visit(Child))

2553 B = R;

2554 }

2555 }

2556 return B;

2557}

2558

2559CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,

2560 AddStmtChoice asc) {

2561 AddressTakenLabels.insert(A->getLabel());

2562

2563 if (asc.alwaysAdd(*this, A)) {

2564 autoCreateBlock();

2565 appendStmt(Block, A);

2566 }

2567

2569}

2570

2574 "expected fallthrough not to have children");

2575 return isFallthrough;

2576}

2577

2580

2582 "expected [[assume]] not to have children");

2583 return hasAssumeAttr;

2584}

2585

2586CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,

2587 AddStmtChoice asc) {

2588

2589

2590

2591

2592

2593

2594

2595

2597 if (isInterestingAttribute && asc.alwaysAdd(*this, A)) {

2598 autoCreateBlock();

2599 appendStmt(Block, A);

2600 }

2601

2602 return VisitChildren(A);

2603}

2604

2605CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {

2606 if (asc.alwaysAdd(*this, U)) {

2607 autoCreateBlock();

2608 appendStmt(Block, U);

2609 }

2610

2613

2614 return Visit(U->getSubExpr(), AddStmtChoice());

2615}

2616

2617CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {

2618 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();

2619 appendStmt(ConfluenceBlock, B);

2620

2621 if (badCFG)

2622 return nullptr;

2623

2624 return VisitLogicalOperator(B, nullptr, ConfluenceBlock,

2625 ConfluenceBlock).first;

2626}

2627

2628std::pair<CFGBlock*, CFGBlock*>

2629CFGBuilder::VisitLogicalOperator(BinaryOperator *B,

2630 Stmt *Term,

2631 CFGBlock *TrueBlock,

2632 CFGBlock *FalseBlock) {

2633

2634

2635

2637 CFGBlock *RHSBlock, *ExitBlock;

2638

2639 do {

2640 if (BinaryOperator *B_RHS = dyn_cast(RHS))

2641 if (B_RHS->isLogicalOp()) {

2642 std::tie(RHSBlock, ExitBlock) =

2643 VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);

2644 break;

2645 }

2646

2647

2648

2649

2650

2651 ExitBlock = RHSBlock = createBlock(false);

2652

2653

2654

2655

2656 TryResult KnownVal = tryEvaluateBool(RHS);

2657 if (!KnownVal.isKnown())

2658 KnownVal = tryEvaluateBool(B);

2659

2660 if (!Term) {

2661 assert(TrueBlock == FalseBlock);

2662 addSuccessor(RHSBlock, TrueBlock);

2663 }

2664 else {

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

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

2668 }

2669

2670 Block = RHSBlock;

2671 RHSBlock = addStmt(RHS);

2672 }

2673 while (false);

2674

2675 if (badCFG)

2676 return std::make_pair(nullptr, nullptr);

2677

2678

2680

2681 if (BinaryOperator *B_LHS = dyn_cast(LHS))

2682 if (B_LHS->isLogicalOp()) {

2684 FalseBlock = RHSBlock;

2685 else

2686 TrueBlock = RHSBlock;

2687

2688

2689

2690

2691 return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);

2692 }

2693

2694

2695

2696 CFGBlock *LHSBlock = createBlock(false);

2698

2699 Block = LHSBlock;

2700 CFGBlock *EntryLHSBlock = addStmt(LHS);

2701

2702 if (badCFG)

2703 return std::make_pair(nullptr, nullptr);

2704

2705

2706 TryResult KnownVal = tryEvaluateBool(LHS);

2707

2708

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

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

2712 } else {

2713 assert(B->getOpcode() == BO_LAnd);

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

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

2716 }

2717

2718 return std::make_pair(EntryLHSBlock, ExitBlock);

2719}

2720

2721CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,

2722 AddStmtChoice asc) {

2723

2725 return VisitLogicalOperator(B);

2726

2727 if (B->getOpcode() == BO_Comma) {

2728 autoCreateBlock();

2729 appendStmt(Block, B);

2730 addStmt(B->getRHS());

2731 return addStmt(B->getLHS());

2732 }

2733

2735 if (asc.alwaysAdd(*this, B)) {

2736 autoCreateBlock();

2737 appendStmt(Block, B);

2738 }

2740 return Visit(B->getRHS());

2741 }

2742

2743 if (asc.alwaysAdd(*this, B)) {

2744 autoCreateBlock();

2745 appendStmt(Block, B);

2746 }

2747

2749 tryEvaluateBool(B);

2750

2751 CFGBlock *RBlock = Visit(B->getRHS());

2752 CFGBlock *LBlock = Visit(B->getLHS());

2753

2754

2755

2756 return (LBlock ? LBlock : RBlock);

2757}

2758

2759CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {

2760 if (asc.alwaysAdd(*this, E)) {

2761 autoCreateBlock();

2762 appendStmt(Block, E);

2763 }

2765}

2766

2767CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {

2768

2769

2770 if (badCFG)

2771 return nullptr;

2772

2773

2774 Block = createBlock(false);

2775 Block->setTerminator(B);

2776

2777

2778

2779 if (BreakJumpTarget.block) {

2780 addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);

2781 addSuccessor(Block, BreakJumpTarget.block);

2782 } else

2783 badCFG = true;

2784

2786}

2787

2792

2794 if (FT) {

2795 if (const FunctionProtoType *Proto = dyn_cast(FT))

2797 Proto->isNothrow())

2798 return false;

2799 }

2800 return true;

2801}

2802

2806 if (BuiltinID != Builtin::BI__assume &&

2807 BuiltinID != Builtin::BI__builtin_assume)

2808 return false;

2809

2811}

2812

2813CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {

2814

2815 QualType calleeType = C->getCallee()->getType();

2818

2819

2820

2821 if (!boundType.isNull()) calleeType = boundType;

2822 }

2823

2824

2826

2827 bool AddEHEdge = false;

2828

2829

2830 if (Context->getLangOpts().Exceptions) {

2832 AddEHEdge = true;

2833 }

2834

2835

2836

2837 bool OmitArguments = false;

2838

2839 if (FunctionDecl *FD = C->getDirectCallee()) {

2840

2841

2842

2843

2844 if (!FD->isVariadic())

2845 findConstructionContextsForArguments(C);

2846

2847 if (FD->isNoReturn() || FD->isAnalyzerNoReturn() ||

2848 C->isBuiltinAssumeFalse(*Context))

2849 NoReturn = true;

2850 if (FD->hasAttr())

2851 AddEHEdge = false;

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

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

2855 OmitArguments = true;

2856 }

2857

2858 if (CanThrow(C->getCallee(), *Context))

2859 AddEHEdge = false;

2860

2861 if (OmitArguments) {

2862 assert(!NoReturn && "noreturn calls with unevaluated args not implemented");

2863 assert(!AddEHEdge && "EH calls with unevaluated args not implemented");

2864 autoCreateBlock();

2865 appendStmt(Block, C);

2866 return Visit(C->getCallee());

2867 }

2868

2869 if (!NoReturn && !AddEHEdge) {

2870 autoCreateBlock();

2871 appendCall(Block, C);

2872

2873 return VisitChildren(C);

2874 }

2875

2878 if (badCFG)

2879 return nullptr;

2880 }

2881

2882 if (NoReturn)

2883 Block = createNoReturnBlock();

2884 else

2885 Block = createBlock();

2886

2887 appendCall(Block, C);

2888

2889 if (AddEHEdge) {

2890

2891 if (TryTerminatedBlock)

2892 addSuccessor(Block, TryTerminatedBlock);

2893 else

2894 addSuccessor(Block, &cfg->getExit());

2895 }

2896

2897 return VisitChildren(C);

2898}

2899

2900CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,

2901 AddStmtChoice asc) {

2902 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();

2903 appendStmt(ConfluenceBlock, C);

2904 if (badCFG)

2905 return nullptr;

2906

2907 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);

2908 Succ = ConfluenceBlock;

2909 Block = nullptr;

2910 CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);

2911 if (badCFG)

2912 return nullptr;

2913

2914 Succ = ConfluenceBlock;

2915 Block = nullptr;

2916 CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);

2917 if (badCFG)

2918 return nullptr;

2919

2920 Block = createBlock(false);

2921

2922 const TryResult& KnownVal = tryEvaluateBool(C->getCond());

2923 addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);

2924 addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);

2925 Block->setTerminator(C);

2926 return addStmt(C->getCond());

2927}

2928

2929CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C,

2930 bool ExternallyDestructed) {

2931 LocalScope::const_iterator scopeBeginPos = ScopePos;

2932 addLocalScopeForStmt(C);

2933

2935

2936

2937 addAutomaticObjHandling(ScopePos, scopeBeginPos, C);

2938 }

2939

2940 CFGBlock *LastBlock = Block;

2941

2942 for (Stmt *S : llvm::reverse(C->body())) {

2943

2944

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

2946 ExternallyDestructed);

2947

2948 if (newBlock)

2949 LastBlock = newBlock;

2950

2951 if (badCFG)

2952 return nullptr;

2953

2954 ExternallyDestructed = false;

2955 }

2956

2957 return LastBlock;

2958}

2959

2960CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,

2961 AddStmtChoice asc) {

2962 const BinaryConditionalOperator *BCO = dyn_cast(C);

2963 const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);

2964

2965

2966

2967 CFGBlock *ConfluenceBlock = Block ? Block : createBlock();

2968 appendStmt(ConfluenceBlock, C);

2969 if (badCFG)

2970 return nullptr;

2971

2972 AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);

2973

2974

2975

2976

2977

2978 Succ = ConfluenceBlock;

2979 Block = nullptr;

2980 CFGBlock *LHSBlock = nullptr;

2981 const Expr *trueExpr = C->getTrueExpr();

2982 if (trueExpr != opaqueValue) {

2983 LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);

2984 if (badCFG)

2985 return nullptr;

2986 Block = nullptr;

2987 }

2988 else

2989 LHSBlock = ConfluenceBlock;

2990

2991

2992 Succ = ConfluenceBlock;

2993 CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);

2994 if (badCFG)

2995 return nullptr;

2996

2997

2998 if (BinaryOperator *Cond =

2999 dyn_cast(C->getCond()->IgnoreParens()))

3000 if (Cond->isLogicalOp())

3001 return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;

3002

3003

3004 Block = createBlock(false);

3005

3006

3007 const TryResult& KnownVal = tryEvaluateBool(C->getCond());

3008 addSuccessor(Block, LHSBlock, !KnownVal.isFalse());

3009 addSuccessor(Block, RHSBlock, !KnownVal.isTrue());

3010 Block->setTerminator(C);

3011 Expr *condExpr = C->getCond();

3012

3013 if (opaqueValue) {

3014

3015

3016 if (condExpr != opaqueValue)

3017 addStmt(condExpr);

3018

3019

3020

3021 return addStmt(BCO->getCommon());

3022 }

3023

3024 return addStmt(condExpr);

3025}

3026

3027CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {

3028

3029

3032

3033

3035 return VisitDeclSubExpr(DS);

3036

3037 CFGBlock *B = nullptr;

3038

3039

3042 I != E; ++I) {

3043

3044

3045

3046 DeclGroupRef DG(*I);

3047 Decl *D = *I;

3048 DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D));

3049 cfg->addSyntheticDeclStmt(DSNew, DS);

3050

3051

3052 B = VisitDeclSubExpr(DSNew);

3053 }

3054

3055 return B;

3056}

3057

3058

3059

3060CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {

3061 assert(DS->isSingleDecl() && "Can handle single declarations only.");

3062

3063 if (const auto *TND = dyn_cast(DS->getSingleDecl())) {

3064

3065 const Type *T = TND->getUnderlyingType().getTypePtr();

3068

3069 autoCreateBlock();

3070 appendStmt(Block, DS);

3071

3072 CFGBlock *LastBlock = Block;

3073 for (const VariableArrayType *VA = FindVA(T); VA != nullptr;

3074 VA = FindVA(VA->getElementType().getTypePtr())) {

3075 if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))

3076 LastBlock = NewBlock;

3077 }

3078 return LastBlock;

3079 }

3080

3081 VarDecl *VD = dyn_cast(DS->getSingleDecl());

3082

3083 if (!VD) {

3084

3085

3087 }

3088

3089 bool HasTemporaries = false;

3090

3091

3092 CFGBlock *blockAfterStaticInit = nullptr;

3093

3095

3096

3099 Block = nullptr;

3100 if (badCFG)

3101 return nullptr;

3102 }

3103 blockAfterStaticInit = Succ;

3104 }

3105

3106

3107

3111

3113

3114 TempDtorContext Context;

3116 true, Context);

3117 }

3118 }

3119

3120

3121

3122 if (const auto *DD = dyn_cast(VD)) {

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

3124 if (auto *VD = BD->getHoldingVar()) {

3125 DeclGroupRef DG(VD);

3126 DeclStmt *DSNew =

3128 cfg->addSyntheticDeclStmt(DSNew, DS);

3129 Block = VisitDeclSubExpr(DSNew);

3130 }

3131 }

3132 }

3133

3134 autoCreateBlock();

3135 appendStmt(Block, DS);

3136

3137

3138

3139 const auto *AILE = dyn_cast_or_null(Init);

3140

3141 findConstructionContexts(

3143 AILE ? AILE->getSubExpr() : Init);

3144

3145

3146

3147

3148 CFGBlock *LastBlock = Block;

3149

3151 if (HasTemporaries) {

3152

3153

3155 if (CFGBlock *newBlock = Visit(EC->getSubExpr()))

3156 LastBlock = newBlock;

3157 }

3158 else {

3159 if (CFGBlock *newBlock = Visit(Init))

3160 LastBlock = newBlock;

3161 }

3162 }

3163

3164

3165

3166

3168 VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {

3169 if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))

3170 LastBlock = newBlock;

3171 }

3172

3173 maybeAddScopeBeginForVarDecl(Block, VD, DS);

3174

3175

3176 if (ScopePos && VD == *ScopePos)

3177 ++ScopePos;

3178

3179 CFGBlock *B = LastBlock;

3180 if (blockAfterStaticInit) {

3181 Succ = B;

3182 Block = createBlock(false);

3183 Block->setTerminator(DS);

3184 addSuccessor(Block, blockAfterStaticInit);

3185 addSuccessor(Block, B);

3187 }

3188

3189 return B;

3190}

3191

3192CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {

3193

3194

3195

3196

3197

3198

3199

3200

3201

3202 SaveAndRestore save_scope_pos(ScopePos);

3203

3204

3206 addLocalScopeForStmt(Init);

3207

3208

3209

3211 addLocalScopeForVarDecl(VD);

3212

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

3214

3215

3216

3219 if (badCFG)

3220 return nullptr;

3221 }

3222

3223

3224 CFGBlock *ElseBlock = Succ;

3225

3226 if (Stmt *Else = I->getElse()) {

3227 SaveAndRestore sv(Succ);

3228

3229

3230

3231 Block = nullptr;

3232

3233

3234

3236 addLocalScopeAndDtors(Else);

3237

3238 ElseBlock = addStmt(Else);

3239

3240 if (!ElseBlock)

3241 ElseBlock = sv.get();

3242 else if (Block) {

3243 if (badCFG)

3244 return nullptr;

3245 }

3246 }

3247

3248

3249 CFGBlock *ThenBlock;

3250 {

3251 Stmt *Then = I->getThen();

3252 assert(Then);

3253 SaveAndRestore sv(Succ);

3254 Block = nullptr;

3255

3256

3257

3259 addLocalScopeAndDtors(Then);

3260

3261 ThenBlock = addStmt(Then);

3262

3263 if (!ThenBlock) {

3264

3265

3266

3267 ThenBlock = createBlock(false);

3268 addSuccessor(ThenBlock, sv.get());

3269 } else if (Block) {

3270 if (badCFG)

3271 return nullptr;

3272 }

3273 }

3274

3275

3276

3277

3278

3279

3280

3281

3282 BinaryOperator *Cond =

3286 CFGBlock *LastBlock;

3287 if (Cond && Cond->isLogicalOp())

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

3289 else {

3290

3291 Block = createBlock(false);

3292

3293

3294 Block->setTerminator(I);

3295

3296

3297 TryResult KnownVal;

3299 KnownVal = tryEvaluateBool(I->getCond());

3300

3301

3302

3303 addSuccessor(Block, ThenBlock, !KnownVal.isFalse());

3304 addSuccessor(Block, ElseBlock, !KnownVal.isTrue());

3305

3308

3309

3310

3311

3312 LastBlock = addStmt(I->getCond());

3313

3314

3315

3317 autoCreateBlock();

3318 LastBlock = addStmt(const_cast<DeclStmt *>(DS));

3319 }

3320 }

3321

3322

3324 autoCreateBlock();

3325 LastBlock = addStmt(Init);

3326 }

3327

3328 return LastBlock;

3329}

3330

3331CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {

3332

3333

3334

3335

3336

3337

3339

3340

3341 Block = createBlock(false);

3342

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

3344

3345 if (auto *R = dyn_cast(S))

3346 findConstructionContexts(

3348 R->getRetValue());

3349

3350

3351

3352 if (Block->hasNoReturnElement())

3353 addSuccessor(Block, &cfg->getExit());

3354

3355

3356 appendStmt(Block, S);

3357

3358

3359 if (ReturnStmt *RS = dyn_cast(S)) {

3360 if (Expr *O = RS->getRetValue())

3361 return Visit(O, AddStmtChoice::AlwaysAdd, true);

3363 }

3364

3366 auto *B = Block;

3368 B = R;

3369

3372

3373 if (CFGBlock *R = Visit(RV))

3374 B = R;

3375

3376 return B;

3377}

3378

3379CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,

3380 AddStmtChoice asc) {

3381

3382

3383

3384 if (asc.alwaysAdd(*this, E)) {

3385 autoCreateBlock();

3386 appendStmt(Block, E);

3387 }

3388 CFGBlock *B = Block;

3390 B = R;

3392 B = R;

3394 B = R;

3396 B = R;

3397 return B;

3398}

3399

3400CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {

3401

3402

3403

3404

3405

3406 SaveAndRestore save_scope_pos(ScopePos);

3407

3409 CFGBlock *SEHExceptBlock = Block;

3410 if (!SEHExceptBlock)

3411 SEHExceptBlock = createBlock();

3412

3413 appendStmt(SEHExceptBlock, ES);

3414

3415

3416 SEHExceptBlock->setLabel(ES);

3417

3418

3419 if (badCFG)

3420 return nullptr;

3421

3422

3423 Block = nullptr;

3424

3425 return SEHExceptBlock;

3426}

3427

3428CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {

3429 return VisitCompoundStmt(FS->getBlock(), false);

3430}

3431

3432CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {

3433

3434

3435 if (badCFG)

3436 return nullptr;

3437

3438

3439 Block = createBlock(false);

3440 Block->setTerminator(LS);

3441

3442

3443

3444 if (SEHLeaveJumpTarget.block) {

3445 addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);

3446 addSuccessor(Block, SEHLeaveJumpTarget.block);

3447 } else

3448 badCFG = true;

3449

3451}

3452

3453CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {

3454

3455

3456 CFGBlock *SEHTrySuccessor = nullptr;

3457

3459 if (badCFG)

3460 return nullptr;

3461 SEHTrySuccessor = Block;

3462 } else SEHTrySuccessor = Succ;

3463

3464

3466 return NYS();

3467

3468 CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;

3469

3470

3471 CFGBlock *NewTryTerminatedBlock = createBlock(false);

3472

3473

3474 NewTryTerminatedBlock->setTerminator(Terminator);

3475

3476 if (SEHExceptStmt *Except = Terminator->getExceptHandler()) {

3477

3478 Succ = SEHTrySuccessor;

3479 Block = nullptr;

3480 CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);

3481 if (!ExceptBlock)

3482 return nullptr;

3483

3484

3485 addSuccessor(NewTryTerminatedBlock, ExceptBlock);

3486 }

3487 if (PrevSEHTryTerminatedBlock)

3488 addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);

3489 else

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

3491

3492

3493 Succ = SEHTrySuccessor;

3494

3495

3496 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);

3497 cfg->addTryDispatchBlock(TryTerminatedBlock);

3498

3499

3500

3501

3502 SaveAndRestore save_break(SEHLeaveJumpTarget);

3503 SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);

3504

3505 assert(Terminator->getTryBlock() && "__try must contain a non-NULL body");

3506 Block = nullptr;

3507 return addStmt(Terminator->getTryBlock());

3508}

3509

3510CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {

3511

3513 CFGBlock *LabelBlock = Block;

3514

3515 if (!LabelBlock)

3516 LabelBlock = createBlock();

3517

3518 assert(!LabelMap.contains(L->getDecl()) && "label already in map");

3519 LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);

3520

3521

3522

3523

3524

3526 if (badCFG)

3527 return nullptr;

3528

3529

3530 Block = nullptr;

3531

3532

3533 Succ = LabelBlock;

3534

3535 return LabelBlock;

3536}

3537

3538CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {

3539 CFGBlock *LastBlock = VisitNoRecurse(E, asc);

3541 if (Expr *CopyExpr = CI.getCopyExpr()) {

3542 CFGBlock *Tmp = Visit(CopyExpr);

3543 if (Tmp)

3544 LastBlock = Tmp;

3545 }

3546 }

3547 return LastBlock;

3548}

3549

3550CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {

3551 CFGBlock *LastBlock = VisitNoRecurse(E, asc);

3552

3553 unsigned Idx = 0;

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

3557 if (Expr *Init = *it) {

3558

3559

3561 dyn_cast(Init));

3562

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

3565 AILEInit ? AILEInit : Init);

3566

3567 CFGBlock *Tmp = Visit(Init);

3568 if (Tmp)

3569 LastBlock = Tmp;

3570 }

3571 }

3572 return LastBlock;

3573}

3574

3575CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {

3576

3577

3578

3579 Block = createBlock(false);

3580 Block->setTerminator(G);

3581

3582

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

3584

3585 if (I == LabelMap.end())

3586

3587 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));

3588 else {

3589 JumpTarget JT = I->second;

3590 addSuccessor(Block, JT.block);

3591 addScopeChangesHandling(ScopePos, JT.scopePosition, G);

3592 }

3593

3595}

3596

3597CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {

3598

3599

3600

3602 return VisitStmt(G, asc);

3603

3606 if (badCFG)

3607 return nullptr;

3608 }

3609 Block = createBlock();

3610 Block->setTerminator(G);

3611

3612 BackpatchBlocks.push_back(JumpSource(Block, ScopePos));

3613

3614

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

3616 return VisitChildren(G);

3617}

3618

3619CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {

3620 CFGBlock *LoopSuccessor = nullptr;

3621

3622

3623

3624 SaveAndRestore save_scope_pos(ScopePos);

3625

3626

3627

3628

3630 addLocalScopeForStmt(Init);

3631 LocalScope::const_iterator LoopBeginScopePos = ScopePos;

3632

3634 addLocalScopeForVarDecl(VD);

3635 LocalScope::const_iterator ContinueScopePos = ScopePos;

3636

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

3638

3639 addLoopExit(F);

3640

3641

3642

3644 if (badCFG)

3645 return nullptr;

3646 LoopSuccessor = Block;

3647 } else

3648 LoopSuccessor = Succ;

3649

3650

3651

3652 SaveAndRestore save_break(BreakJumpTarget);

3653 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

3654

3655 CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;

3656

3657

3658 {

3660

3661

3662 SaveAndRestore save_Block(Block), save_Succ(Succ);

3663 SaveAndRestore save_continue(ContinueJumpTarget);

3664

3665

3666

3667

3668 Block = Succ = TransitionBlock = createBlock(false);

3669 TransitionBlock->setLoopTarget(F);

3670

3671

3672

3673

3674 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);

3675

3676 if (Stmt *I = F->getInc()) {

3677

3678

3679 Succ = addStmt(I);

3680 }

3681

3682

3684 assert(Block == Succ);

3685 if (badCFG)

3686 return nullptr;

3687 Block = nullptr;

3688 }

3689

3690

3691

3692 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);

3693 ContinueJumpTarget.block->setLoopTarget(F);

3694

3695

3696

3697

3699 addLocalScopeAndDtors(F->getBody());

3700

3701

3702

3703 BodyBlock = addStmt(F->getBody());

3704

3705 if (!BodyBlock) {

3706

3707

3708 BodyBlock = ContinueJumpTarget.block;

3709 }

3710 else if (badCFG)

3711 return nullptr;

3712 }

3713

3714

3715

3716

3717 CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;

3718

3719 do {

3721 SaveAndRestore save_scope_pos(ScopePos);

3722

3723

3724

3725 if (BinaryOperator *Cond =

3726 dyn_cast_or_null(C ? C->IgnoreParens() : nullptr))

3727 if (Cond->isLogicalOp()) {

3728 std::tie(EntryConditionBlock, ExitConditionBlock) =

3729 VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);

3730 break;

3731 }

3732

3733

3734 EntryConditionBlock = ExitConditionBlock = createBlock(false);

3735 ExitConditionBlock->setTerminator(F);

3736

3737

3738 TryResult KnownVal(true);

3739

3740 if (C) {

3741

3742

3743

3744 Block = ExitConditionBlock;

3745 EntryConditionBlock = addStmt(C);

3746

3747

3748

3751 autoCreateBlock();

3754 findConstructionContexts(

3757 appendStmt(Block, DS);

3758 EntryConditionBlock = addStmt(Init);

3759 assert(Block == EntryConditionBlock);

3760 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);

3761 }

3762 }

3763

3764 if (Block && badCFG)

3765 return nullptr;

3766

3767 KnownVal = tryEvaluateBool(C);

3768 }

3769

3770

3771 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);

3772

3773

3774 addSuccessor(ExitConditionBlock,

3775 KnownVal.isTrue() ? nullptr : LoopSuccessor);

3776 } while (false);

3777

3778

3779 addSuccessor(TransitionBlock, EntryConditionBlock);

3780

3781

3782 Succ = EntryConditionBlock;

3783

3784

3785

3786 if (Stmt *I = F->getInit()) {

3787 SaveAndRestore save_scope_pos(ScopePos);

3788 ScopePos = LoopBeginScopePos;

3789 Block = createBlock();

3790 return addStmt(I);

3791 }

3792

3793

3794

3795 Block = nullptr;

3796 Succ = EntryConditionBlock;

3797 return EntryConditionBlock;

3798}

3799

3800CFGBlock *

3801CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,

3802 AddStmtChoice asc) {

3803 findConstructionContexts(

3806

3807 return VisitStmt(MTE, asc);

3808}

3809

3810CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {

3811 if (asc.alwaysAdd(*this, M)) {

3812 autoCreateBlock();

3813 appendStmt(Block, M);

3814 }

3815 return Visit(M->getBase());

3816}

3817

3818CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {

3819

3820

3821

3822

3823

3824

3825

3826

3827

3828

3829

3830

3831

3832

3833

3834

3835

3836

3837

3838

3839

3840

3841

3842

3843

3844

3845

3846

3847

3848

3849

3850 CFGBlock *LoopSuccessor = nullptr;

3851

3853 if (badCFG)

3854 return nullptr;

3855 LoopSuccessor = Block;

3856 Block = nullptr;

3857 } else

3858 LoopSuccessor = Succ;

3859

3860

3861 CFGBlock *ExitConditionBlock = createBlock(false);

3862

3863

3865

3866

3867

3868

3869 appendStmt(ExitConditionBlock, S);

3870 Block = ExitConditionBlock;

3871

3872

3873

3874

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

3876 AddStmtChoice::NotAlwaysAdd);

3878 if (badCFG)

3879 return nullptr;

3880 Block = nullptr;

3881 }

3882

3883

3884

3885 Succ = EntryConditionBlock;

3886

3887

3888 {

3889

3890 SaveAndRestore save_Block(Block), save_Succ(Succ);

3891 SaveAndRestore save_continue(ContinueJumpTarget),

3892 save_break(BreakJumpTarget);

3893

3894

3895

3896

3897 CFGBlock *LoopBackBlock = nullptr;

3898 Succ = LoopBackBlock = createBlock();

3900

3901 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

3902 ContinueJumpTarget = JumpTarget(Succ, ScopePos);

3903

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

3905

3906 if (!BodyBlock)

3907 BodyBlock = ContinueJumpTarget.block;

3908 else if (Block) {

3909 if (badCFG)

3910 return nullptr;

3911 }

3912

3913

3914 addSuccessor(ExitConditionBlock, BodyBlock);

3915 }

3916

3917

3918

3919 addSuccessor(ExitConditionBlock, LoopSuccessor);

3920

3921

3922 Block = createBlock();

3924}

3925

3926CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {

3927

3929

3930}

3931

3932CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {

3933

3934

3935

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

3937

3938

3939

3940 if (SyncBlock) {

3941 if (badCFG)

3942 return nullptr;

3943

3944 Block = nullptr;

3945 Succ = SyncBlock;

3946 }

3947

3948

3949 autoCreateBlock();

3950 appendStmt(Block, S);

3951

3952

3954}

3955

3956CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {

3957 autoCreateBlock();

3958

3959

3960 appendStmt(Block, E);

3961

3962 CFGBlock *lastBlock = Block;

3963

3964

3965

3968

3969

3970

3971 if (OpaqueValueExpr *OVE = dyn_cast(Semantic))

3972 Semantic = OVE->getSourceExpr();

3973

3974 if (CFGBlock *B = Visit(Semantic))

3975 lastBlock = B;

3976 }

3977

3978 return lastBlock;

3979}

3980

3981CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {

3982 CFGBlock *LoopSuccessor = nullptr;

3983

3984

3985

3986 SaveAndRestore save_scope_pos(ScopePos);

3987

3988

3989

3990 LocalScope::const_iterator LoopBeginScopePos = ScopePos;

3992 addLocalScopeForVarDecl(VD);

3993 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);

3994 }

3995 addLoopExit(W);

3996

3997

3998

4000 if (badCFG)

4001 return nullptr;

4002 LoopSuccessor = Block;

4003 Block = nullptr;

4004 } else {

4005 LoopSuccessor = Succ;

4006 }

4007

4008 CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;

4009

4010

4011 {

4013

4014

4015 SaveAndRestore save_Block(Block), save_Succ(Succ);

4016 SaveAndRestore save_continue(ContinueJumpTarget),

4017 save_break(BreakJumpTarget);

4018

4019

4020

4021 Succ = TransitionBlock = createBlock(false);

4022 TransitionBlock->setLoopTarget(W);

4023 ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);

4024

4025

4026 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

4027

4028

4029 addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);

4030

4031

4032

4034 addLocalScopeAndDtors(W->getBody());

4035

4036

4037 BodyBlock = addStmt(W->getBody());

4038

4039 if (!BodyBlock)

4040 BodyBlock = ContinueJumpTarget.block;

4041 else if (Block && badCFG)

4042 return nullptr;

4043 }

4044

4045

4046

4047

4048 CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;

4049

4050 do {

4052

4053

4054

4055 if (BinaryOperator *Cond = dyn_cast(C->IgnoreParens()))

4056 if (Cond->isLogicalOp()) {

4057 std::tie(EntryConditionBlock, ExitConditionBlock) =

4058 VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);

4059 break;

4060 }

4061

4062

4063 ExitConditionBlock = createBlock(false);

4065

4066

4067

4068

4069 Block = ExitConditionBlock;

4070 Block = EntryConditionBlock = addStmt(C);

4071

4072

4073

4076 autoCreateBlock();

4079 findConstructionContexts(

4081 const_cast<DeclStmt *>(DS)),

4083 appendStmt(Block, DS);

4084 EntryConditionBlock = addStmt(Init);

4085 assert(Block == EntryConditionBlock);

4086 maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);

4087 }

4088 }

4089

4090 if (Block && badCFG)

4091 return nullptr;

4092

4093

4094 const TryResult& KnownVal = tryEvaluateBool(C);

4095

4096

4097 addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);

4098

4099

4100 addSuccessor(ExitConditionBlock,

4101 KnownVal.isTrue() ? nullptr : LoopSuccessor);

4102 } while(false);

4103

4104

4105 addSuccessor(TransitionBlock, EntryConditionBlock);

4106

4107

4108

4109 Block = nullptr;

4110

4111

4112 Succ = EntryConditionBlock;

4113 return EntryConditionBlock;

4114}

4115

4116CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,

4117 AddStmtChoice asc) {

4118 if (asc.alwaysAdd(*this, A)) {

4119 autoCreateBlock();

4120 appendStmt(Block, A);

4121 }

4122

4123 CFGBlock *B = Block;

4124

4125 if (CFGBlock *R = Visit(A->getSubExpr()))

4126 B = R;

4127

4128 auto *OVE = dyn_cast(A->getCommonExpr());

4129 assert(OVE && "ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "

4130 "OpaqueValueExpr!");

4131 if (CFGBlock *R = Visit(OVE->getSourceExpr()))

4132 B = R;

4133

4134 return B;

4135}

4136

4137CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {

4138

4139

4140

4141

4142

4143 SaveAndRestore save_scope_pos(ScopePos);

4144

4147

4148 CFGBlock *CatchBlock = Block;

4149 if (!CatchBlock)

4150 CatchBlock = createBlock();

4151

4152 appendStmt(CatchBlock, CS);

4153

4154

4156

4157

4158 if (badCFG)

4159 return nullptr;

4160

4161

4162 Block = nullptr;

4163

4164 return CatchBlock;

4165}

4166

4167CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {

4168

4169 if (badCFG)

4170 return nullptr;

4171

4172

4173 Block = createBlock(false);

4174

4175 if (TryTerminatedBlock)

4176

4177 addSuccessor(Block, TryTerminatedBlock);

4178 else

4179

4180 addSuccessor(Block, &cfg->getExit());

4181

4182

4183

4184 return VisitStmt(S, AddStmtChoice::AlwaysAdd);

4185}

4186

4187CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {

4188

4189

4190 CFGBlock *TrySuccessor = nullptr;

4191

4193 if (badCFG)

4194 return nullptr;

4195 TrySuccessor = Block;

4196 } else

4197 TrySuccessor = Succ;

4198

4199

4201 return NYS();

4202

4203 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;

4204

4205

4206 CFGBlock *NewTryTerminatedBlock = createBlock(false);

4207

4208 NewTryTerminatedBlock->setTerminator(Terminator);

4209

4210 bool HasCatchAll = false;

4211 for (ObjCAtCatchStmt *CS : Terminator->catch_stmts()) {

4212

4213 Succ = TrySuccessor;

4215 HasCatchAll = true;

4216 }

4217 Block = nullptr;

4218 CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);

4219 if (!CatchBlock)

4220 return nullptr;

4221

4222

4223 addSuccessor(NewTryTerminatedBlock, CatchBlock);

4224 }

4225

4226

4227 if (!HasCatchAll) {

4228 if (PrevTryTerminatedBlock)

4229 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);

4230 else

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

4232 }

4233

4234

4235 Succ = TrySuccessor;

4236

4237

4238 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);

4239 cfg->addTryDispatchBlock(TryTerminatedBlock);

4240

4241 assert(Terminator->getTryBody() && "try must contain a non-NULL body");

4242 Block = nullptr;

4243 return addStmt(Terminator->getTryBody());

4244}

4245

4246CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,

4247 AddStmtChoice asc) {

4248 findConstructionContextsForArguments(ME);

4249

4250 autoCreateBlock();

4251 appendObjCMessage(Block, ME);

4252

4253 return VisitChildren(ME);

4254}

4255

4256CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {

4257

4258 if (badCFG)

4259 return nullptr;

4260

4261

4262 Block = createBlock(false);

4263

4264 if (TryTerminatedBlock)

4265

4266 addSuccessor(Block, TryTerminatedBlock);

4267 else

4268

4269 addSuccessor(Block, &cfg->getExit());

4270

4271

4272

4273 return VisitStmt(T, AddStmtChoice::AlwaysAdd);

4274}

4275

4276CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {

4277 if (asc.alwaysAdd(*this, S)) {

4278 autoCreateBlock();

4279 appendStmt(Block, S);

4280 }

4281

4282

4283

4284

4285

4286

4287

4289 return VisitChildren(S);

4290

4291

4293}

4294

4295CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {

4296 CFGBlock *LoopSuccessor = nullptr;

4297

4298 addLoopExit(D);

4299

4300

4301

4303 if (badCFG)

4304 return nullptr;

4305 LoopSuccessor = Block;

4306 } else

4307 LoopSuccessor = Succ;

4308

4309

4310

4311

4312 CFGBlock *ExitConditionBlock = createBlock(false);

4313 CFGBlock *EntryConditionBlock = ExitConditionBlock;

4314

4315

4317

4318

4319

4320 if (Stmt *C = D->getCond()) {

4321 Block = ExitConditionBlock;

4322 EntryConditionBlock = addStmt(C);

4324 if (badCFG)

4325 return nullptr;

4326 }

4327 }

4328

4329

4330 Succ = EntryConditionBlock;

4331

4332

4333 const TryResult &KnownVal = tryEvaluateBool(D->getCond());

4334

4335

4336 CFGBlock *BodyBlock = nullptr;

4337 {

4339

4340

4341 SaveAndRestore save_Block(Block), save_Succ(Succ);

4342 SaveAndRestore save_continue(ContinueJumpTarget),

4343 save_break(BreakJumpTarget);

4344

4345

4346 ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);

4347

4348

4349 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

4350

4351

4352 Block = nullptr;

4353

4354

4355

4357 addLocalScopeAndDtors(D->getBody());

4358

4359

4360 BodyBlock = addStmt(D->getBody());

4361

4362 if (!BodyBlock)

4363 BodyBlock = EntryConditionBlock;

4364 else if (Block) {

4365 if (badCFG)

4366 return nullptr;

4367 }

4368

4369

4370

4371

4372

4373

4374 Block = nullptr;

4375 Succ = BodyBlock;

4376 CFGBlock *LoopBackBlock = createBlock();

4378

4379 if (!KnownVal.isFalse())

4380

4381 addSuccessor(ExitConditionBlock, LoopBackBlock);

4382 else

4383 addSuccessor(ExitConditionBlock, nullptr);

4384 }

4385

4386

4387

4388 addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);

4389

4390

4391

4392 Block = nullptr;

4393

4394

4395 Succ = BodyBlock;

4396 return BodyBlock;

4397}

4398

4399CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {

4400

4401

4402 if (badCFG)

4403 return nullptr;

4404

4405

4406 Block = createBlock(false);

4407 Block->setTerminator(C);

4408

4409

4410

4411 if (ContinueJumpTarget.block) {

4412 addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);

4413 addSuccessor(Block, ContinueJumpTarget.block);

4414 } else

4415 badCFG = true;

4416

4418}

4419

4420CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,

4421 AddStmtChoice asc) {

4422 if (asc.alwaysAdd(*this, E)) {

4423 autoCreateBlock();

4424 appendStmt(Block, E);

4425 }

4426

4427

4428

4429

4430 if (E->getKind() != UETT_SizeOf)

4432

4433 CFGBlock *lastBlock = Block;

4434

4437 VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))

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

4439 }

4440 return lastBlock;

4441}

4442

4443

4444

4445CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {

4446 if (asc.alwaysAdd(*this, SE)) {

4447 autoCreateBlock();

4448 appendStmt(Block, SE);

4449 }

4450 return VisitCompoundStmt(SE->getSubStmt(), true);

4451}

4452

4453CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {

4454

4455

4456 CFGBlock *SwitchSuccessor = nullptr;

4457

4458

4459

4460 SaveAndRestore save_scope_pos(ScopePos);

4461

4462

4464 addLocalScopeForStmt(Init);

4465

4466

4467

4469 addLocalScopeForVarDecl(VD);

4470

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

4472

4474 if (badCFG)

4475 return nullptr;

4476 SwitchSuccessor = Block;

4477 } else SwitchSuccessor = Succ;

4478

4479

4480 SaveAndRestore save_switch(SwitchTerminatedBlock),

4481 save_default(DefaultCaseBlock);

4482 SaveAndRestore save_break(BreakJumpTarget);

4483

4484

4485

4486

4487 DefaultCaseBlock = SwitchSuccessor;

4488

4489

4490 SwitchTerminatedBlock = createBlock(false);

4491

4492

4493

4494 Succ = SwitchSuccessor;

4495 BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);

4496

4497

4498

4499

4500 assert(Terminator->getBody() && "switch must contain a non-NULL body");

4501 Block = nullptr;

4502

4503

4504

4505 SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered, false);

4506

4507

4508 assert(Terminator->getCond() && "switch condition must be non-NULL");

4509 Expr::EvalResult result;

4510 bool b = tryEvaluate(Terminator->getCond(), result);

4511 SaveAndRestore save_switchCond(switchCond, b ? &result : nullptr);

4512

4513

4514

4516 addLocalScopeAndDtors(Terminator->getBody());

4517

4518 addStmt(Terminator->getBody());

4520 if (badCFG)

4521 return nullptr;

4522 }

4523

4524

4525

4526

4527

4528

4529

4530

4531

4532 bool SwitchAlwaysHasSuccessor = false;

4533 SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;

4534 SwitchAlwaysHasSuccessor |=

4537 addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,

4538 !SwitchAlwaysHasSuccessor);

4539

4540

4541 SwitchTerminatedBlock->setTerminator(Terminator);

4542 Block = SwitchTerminatedBlock;

4543 CFGBlock *LastBlock = addStmt(Terminator->getCond());

4544

4545

4546

4549 autoCreateBlock();

4551 LastBlock = addStmt(Init);

4552 maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);

4553 }

4554 }

4555

4556

4557 if (Stmt *Init = Terminator->getInit()) {

4558 autoCreateBlock();

4559 LastBlock = addStmt(Init);

4560 }

4561

4562 return LastBlock;

4563}

4564

4569 if (!switchCond)

4570 return true;

4571

4572 bool addCase = false;

4573

4574 if (!switchExclusivelyCovered) {

4575 if (switchCond->Val.isInt()) {

4576

4578 const llvm::APSInt &condInt = switchCond->Val.getInt();

4579

4580 if (condInt == lhsInt) {

4581 addCase = true;

4582 switchExclusivelyCovered = true;

4583 }

4584 else if (condInt > lhsInt) {

4585 if (const Expr *RHS = CS->getRHS()) {

4586

4588 if (V2 >= condInt) {

4589 addCase = true;

4590 switchExclusivelyCovered = true;

4591 }

4592 }

4593 }

4594 }

4595 else

4596 addCase = true;

4597 }

4598 return addCase;

4599}

4600

4601CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {

4602

4603

4604 CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;

4605

4607

4608

4609

4611 CFGBlock *currentBlock = createBlock(false);

4613

4614 if (TopBlock)

4615 addSuccessor(LastBlock, currentBlock);

4616 else

4617 TopBlock = currentBlock;

4618

4619 addSuccessor(SwitchTerminatedBlock,

4620 shouldAddCase(switchExclusivelyCovered, switchCond,

4621 CS, *Context)

4622 ? currentBlock : nullptr);

4623

4624 LastBlock = currentBlock;

4627 }

4628

4629 addStmt(Sub);

4630 }

4631

4632 CFGBlock *CaseBlock = Block;

4633 if (!CaseBlock)

4634 CaseBlock = createBlock();

4635

4636

4637

4639

4640 if (badCFG)

4641 return nullptr;

4642

4643

4644

4645 assert(SwitchTerminatedBlock);

4646 addSuccessor(SwitchTerminatedBlock, CaseBlock,

4647 shouldAddCase(switchExclusivelyCovered, switchCond,

4648 CS, *Context));

4649

4650

4651 Block = nullptr;

4652

4653 if (TopBlock) {

4654 addSuccessor(LastBlock, CaseBlock);

4655 Succ = TopBlock;

4656 } else {

4657

4658 Succ = CaseBlock;

4659 }

4660

4661 return Succ;

4662}

4663

4664CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {

4667

4668 DefaultCaseBlock = Block;

4669

4670 if (!DefaultCaseBlock)

4671 DefaultCaseBlock = createBlock();

4672

4673

4674

4675 DefaultCaseBlock->setLabel(Terminator);

4676

4677 if (badCFG)

4678 return nullptr;

4679

4680

4681

4682

4683

4684

4685

4686

4687 Block = nullptr;

4688

4689

4690 Succ = DefaultCaseBlock;

4691

4692 return DefaultCaseBlock;

4693}

4694

4695CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {

4696

4697

4698 CFGBlock *TrySuccessor = nullptr;

4699

4701 if (badCFG)

4702 return nullptr;

4703 TrySuccessor = Block;

4704 } else

4705 TrySuccessor = Succ;

4706

4707 CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;

4708

4709

4710 CFGBlock *NewTryTerminatedBlock = createBlock(false);

4711

4712 NewTryTerminatedBlock->setTerminator(Terminator);

4713

4714 bool HasCatchAll = false;

4715 for (unsigned I = 0, E = Terminator->getNumHandlers(); I != E; ++I) {

4716

4717 Succ = TrySuccessor;

4718 CXXCatchStmt *CS = Terminator->getHandler(I);

4720 HasCatchAll = true;

4721 }

4722 Block = nullptr;

4723 CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);

4724 if (!CatchBlock)

4725 return nullptr;

4726

4727

4728 addSuccessor(NewTryTerminatedBlock, CatchBlock);

4729 }

4730 if (!HasCatchAll) {

4731 if (PrevTryTerminatedBlock)

4732 addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);

4733 else

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

4735 }

4736

4737

4738 Succ = TrySuccessor;

4739

4740

4741 SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);

4742 cfg->addTryDispatchBlock(TryTerminatedBlock);

4743

4744 assert(Terminator->getTryBlock() && "try must contain a non-NULL body");

4745 Block = nullptr;

4746 return addStmt(Terminator->getTryBlock());

4747}

4748

4749CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {

4750

4751

4752

4753

4754

4755 SaveAndRestore save_scope_pos(ScopePos);

4756

4757

4758

4760 LocalScope::const_iterator BeginScopePos = ScopePos;

4761 addLocalScopeForVarDecl(VD);

4762 addAutomaticObjHandling(ScopePos, BeginScopePos, CS);

4763 }

4764

4767

4768 CFGBlock *CatchBlock = Block;

4769 if (!CatchBlock)

4770 CatchBlock = createBlock();

4771

4772

4773

4774

4775

4776 appendStmt(CatchBlock, CS);

4777

4778

4779

4781

4782

4783 if (badCFG)

4784 return nullptr;

4785

4786

4787 Block = nullptr;

4788

4789 return CatchBlock;

4790}

4791

4792CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {

4793

4794

4795

4796

4797

4798

4799

4800

4801

4802

4803

4804

4805

4806

4807 SaveAndRestore save_scope_pos(ScopePos);

4808

4809

4811 addLocalScopeForStmt(Range);

4813 addLocalScopeForStmt(Begin);

4815 addLocalScopeForStmt(End);

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

4817

4818 LocalScope::const_iterator ContinueScopePos = ScopePos;

4819

4820

4821

4822 CFGBlock *LoopSuccessor = nullptr;

4824 if (badCFG)

4825 return nullptr;

4826 LoopSuccessor = Block;

4827 } else

4828 LoopSuccessor = Succ;

4829

4830

4831

4832 SaveAndRestore save_break(BreakJumpTarget);

4833 BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);

4834

4835

4836 CFGBlock *ConditionBlock = createBlock(false);

4838

4839

4840 if (Expr *C = S->getCond()) {

4841 Block = ConditionBlock;

4842 CFGBlock *BeginConditionBlock = addStmt(C);

4843 if (badCFG)

4844 return nullptr;

4845 assert(BeginConditionBlock == ConditionBlock &&

4846 "condition block in for-range was unexpectedly complex");

4847 (void)BeginConditionBlock;

4848 }

4849

4850

4851

4852 Succ = ConditionBlock;

4853

4854

4855 TryResult KnownVal(true);

4856

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

4859

4860

4861 {

4863

4864

4865 SaveAndRestore save_Block(Block), save_Succ(Succ);

4866 SaveAndRestore save_continue(ContinueJumpTarget);

4867

4868

4869

4870 Block = nullptr;

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

4872 if (badCFG)

4873 return nullptr;

4874 ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);

4875

4876

4877

4878 ContinueJumpTarget.block->setLoopTarget(S);

4879

4880

4882 if (badCFG)

4883 return nullptr;

4884 Block = nullptr;

4885

4886

4888

4889

4890

4892 addLocalScopeAndDtors(S->getBody());

4893

4894

4896

4897 if (badCFG)

4898 return nullptr;

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

4900 if (badCFG)

4901 return nullptr;

4902

4903

4904 addSuccessor(ConditionBlock,

4905 KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);

4906 }

4907

4908

4909

4910 addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);

4911

4912

4913 Block = createBlock();

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

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

4919 return Head;

4920}

4921

4922CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,

4923 AddStmtChoice asc, bool ExternallyDestructed) {

4925

4926

4927 TempDtorContext Context;

4928 VisitForTemporaryDtors(E->getSubExpr(), ExternallyDestructed, Context);

4929

4930

4931

4932 asc = asc.withAlwaysAdd(true);

4933 }

4935}

4936

4937CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,

4938 AddStmtChoice asc) {

4939 if (asc.alwaysAdd(*this, E)) {

4940 autoCreateBlock();

4941 appendStmt(Block, E);

4942

4943 findConstructionContexts(

4946

4947

4948 asc = asc.withAlwaysAdd(false);

4949 }

4951}

4952

4953CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,

4954 AddStmtChoice asc) {

4955

4956

4957

4958 findConstructionContextsForArguments(C);

4959 appendConstructor(C);

4960

4961 return VisitChildren(C);

4962}

4963

4964CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,

4965 AddStmtChoice asc) {

4966 autoCreateBlock();

4967 appendStmt(Block, NE);

4968

4969 findConstructionContexts(

4971 const_cast<CXXConstructExpr *>(NE->getConstructExpr()));

4972

4973 if (NE->getInitializer())

4974 Block = Visit(NE->getInitializer());

4975

4977 appendNewAllocator(Block, NE);

4978

4979 if (NE->isArray() && *NE->getArraySize())

4980 Block = Visit(*NE->getArraySize());

4981

4983 E = NE->placement_arg_end(); I != E; ++I)

4984 Block = Visit(*I);

4985

4987}

4988

4989CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,

4990 AddStmtChoice asc) {

4991 autoCreateBlock();

4992 appendStmt(Block, DE);

4994 if (!DTy.isNull()) {

4997 if (RD) {

4999 appendDeleteDtor(Block, RD, DE);

5000 }

5001 }

5002

5003 return VisitChildren(DE);

5004}

5005

5006CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,

5007 AddStmtChoice asc) {

5008 if (asc.alwaysAdd(*this, E)) {

5009 autoCreateBlock();

5010 appendStmt(Block, E);

5011

5012 asc = asc.withAlwaysAdd(false);

5013 }

5015}

5016

5017CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,

5018 AddStmtChoice asc) {

5019

5020

5021

5022 findConstructionContextsForArguments(E);

5023 appendConstructor(E);

5024

5025 return VisitChildren(E);

5026}

5027

5028CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,

5029 AddStmtChoice asc) {

5030 if (asc.alwaysAdd(*this, E)) {

5031 autoCreateBlock();

5032 appendStmt(Block, E);

5033 }

5034

5035 if (E->getCastKind() == CK_IntegralToBoolean)

5037

5038 return Visit(E->getSubExpr(), AddStmtChoice());

5039}

5040

5041CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {

5042 return Visit(E->getSubExpr(), AddStmtChoice());

5043}

5044

5045CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {

5046

5047 CFGBlock *IBlock = cfg->getIndirectGotoBlock();

5048

5049 if (!IBlock) {

5050 IBlock = createBlock(false);

5051 cfg->setIndirectGotoBlock(IBlock);

5052 }

5053

5054

5055

5056 if (badCFG)

5057 return nullptr;

5058

5059 Block = createBlock(false);

5060 Block->setTerminator(I);

5061 addSuccessor(Block, IBlock);

5063}

5064

5065CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,

5066 TempDtorContext &Context) {

5068

5069tryAgain:

5070 if (!E) {

5071 badCFG = true;

5072 return nullptr;

5073 }

5075 default:

5076 return VisitChildrenForTemporaryDtors(E, false, Context);

5077

5078 case Stmt::InitListExprClass:

5079 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);

5080

5081 case Stmt::BinaryOperatorClass:

5083 ExternallyDestructed,

5084 Context);

5085

5086 case Stmt::CXXBindTemporaryExprClass:

5087 return VisitCXXBindTemporaryExprForTemporaryDtors(

5089

5090 case Stmt::BinaryConditionalOperatorClass:

5091 case Stmt::ConditionalOperatorClass:

5092 return VisitConditionalOperatorForTemporaryDtors(

5094

5095 case Stmt::ImplicitCastExprClass:

5096

5098 goto tryAgain;

5099

5100 case Stmt::CXXFunctionalCastExprClass:

5101

5103 goto tryAgain;

5104

5105 case Stmt::ConstantExprClass:

5107 goto tryAgain;

5108

5109 case Stmt::ParenExprClass:

5111 goto tryAgain;

5112

5113 case Stmt::MaterializeTemporaryExprClass: {

5116 SmallVector<const Expr *, 2> CommaLHSs;

5117 SmallVector<SubobjectAdjustment, 2> Adjustments;

5118

5119 E = const_cast<Expr *>(

5121 ->getSubExpr()

5122 ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));

5123

5124 for (const Expr *CommaLHS : CommaLHSs) {

5125 VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),

5126 false, Context);

5127 }

5128 goto tryAgain;

5129 }

5130

5131 case Stmt::BlockExprClass:

5132

5133

5135

5136 case Stmt::LambdaExprClass: {

5137

5138

5140 CFGBlock *B = Block;

5141 for (Expr *Init : LE->capture_inits()) {

5143 if (CFGBlock *R = VisitForTemporaryDtors(

5144 Init, true, Context))

5145 B = R;

5146 }

5147 }

5148 return B;

5149 }

5150

5151 case Stmt::StmtExprClass:

5152

5153

5155

5156 case Stmt::CXXDefaultArgExprClass:

5158 goto tryAgain;

5159

5160 case Stmt::CXXDefaultInitExprClass:

5162 goto tryAgain;

5163 }

5164}

5165

5166CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,

5167 bool ExternallyDestructed,

5168 TempDtorContext &Context) {

5170

5172 }

5173

5174

5175

5176

5177

5178 CFGBlock *B = Block;

5179 for (Stmt *Child : E->children())

5180 if (Child)

5181 if (CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))

5182 B = R;

5183

5184 return B;

5185}

5186

5187CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(

5188 BinaryOperator *E, bool ExternallyDestructed, TempDtorContext &Context) {

5190

5191

5192 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);

5193 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), ExternallyDestructed, Context);

5194 return RHSBlock ? RHSBlock : LHSBlock;

5195 }

5196

5198 VisitForTemporaryDtors(E->getLHS(), false, Context);

5199 TryResult RHSExecuted = tryEvaluateBool(E->getLHS());

5200 if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)

5201 RHSExecuted.negate();

5202

5203

5204

5205

5206 TempDtorContext RHSContext(

5207 bothKnownTrue(Context.KnownExecuted, RHSExecuted));

5208 VisitForTemporaryDtors(E->getRHS(), false, RHSContext);

5209 InsertTempDtorDecisionBlock(RHSContext);

5210

5212 }

5213

5215

5216

5217 CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);

5218 CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);

5219 return LHSBlock ? LHSBlock : RHSBlock;

5220 }

5221

5222

5223 return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);

5224}

5225

5226CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(

5227 CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context) {

5228

5229

5230 CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), true, Context);

5231 if (!ExternallyDestructed) {

5232

5233

5234

5236

5238

5239

5240

5241

5242 if (B) Succ = B;

5243 Block = createNoReturnBlock();

5244 } else if (Context.needsTempDtorBranch()) {

5245

5246

5247 if (B) Succ = B;

5248 Block = createBlock();

5249 } else {

5250 autoCreateBlock();

5251 }

5252 if (Context.needsTempDtorBranch()) {

5253 Context.setDecisionPoint(Succ, E);

5254 }

5255 appendTemporaryDtor(Block, E);

5256

5258 }

5259 return B;

5260}

5261

5262void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,

5263 CFGBlock *FalseSucc) {

5264 if (!Context.TerminatorExpr) {

5265

5266 return;

5267 }

5268 assert(Context.TerminatorExpr);

5269 CFGBlock *Decision = createBlock(false);

5270 Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,

5272 addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());

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

5274 !Context.KnownExecuted.isTrue());

5275 Block = Decision;

5276}

5277

5278CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(

5279 AbstractConditionalOperator *E, bool ExternallyDestructed,

5280 TempDtorContext &Context) {

5281 VisitForTemporaryDtors(E->getCond(), false, Context);

5282 CFGBlock *ConditionBlock = Block;

5283 CFGBlock *ConditionSucc = Succ;

5284 TryResult ConditionVal = tryEvaluateBool(E->getCond());

5285 TryResult NegatedVal = ConditionVal;

5286 if (NegatedVal.isKnown()) NegatedVal.negate();

5287

5288 TempDtorContext TrueContext(

5289 bothKnownTrue(Context.KnownExecuted, ConditionVal));

5290 VisitForTemporaryDtors(E->getTrueExpr(), ExternallyDestructed, TrueContext);

5291 CFGBlock *TrueBlock = Block;

5292

5293 Block = ConditionBlock;

5294 Succ = ConditionSucc;

5295 TempDtorContext FalseContext(

5296 bothKnownTrue(Context.KnownExecuted, NegatedVal));

5297 VisitForTemporaryDtors(E->getFalseExpr(), ExternallyDestructed, FalseContext);

5298

5299 if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {

5300 InsertTempDtorDecisionBlock(FalseContext, TrueBlock);

5301 } else if (TrueContext.TerminatorExpr) {

5302 Block = TrueBlock;

5303 InsertTempDtorDecisionBlock(TrueContext);

5304 } else {

5305 InsertTempDtorDecisionBlock(FalseContext);

5306 }

5308}

5309

5310CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,

5311 AddStmtChoice asc) {

5312 if (asc.alwaysAdd(*this, D)) {

5313 autoCreateBlock();

5314 appendStmt(Block, D);

5315 }

5316

5317

5318 CFGBlock *B = Block;

5319

5320

5321

5322 SmallVector<Stmt *, 8> Used(

5323 OMPExecutableDirective::used_clauses_children(D->clauses()));

5324 for (Stmt *S : llvm::reverse(Used)) {

5325 assert(S && "Expected non-null used-in-clause child.");

5326 if (CFGBlock *R = Visit(S))

5327 B = R;

5328 }

5329

5330 if (!D->isStandaloneDirective()) {

5331 Stmt *S = D->getRawStmt();

5333 addLocalScopeAndDtors(S);

5334 if (CFGBlock *R = addStmt(S))

5335 B = R;

5336 }

5337

5338 return B;

5339}

5340

5341

5342

5343

5345 bool first_block = begin() == end();

5346

5347

5349 Blocks.push_back(Mem, BlkBVC);

5350

5351

5352 if (first_block)

5353 Entry = Exit = &back();

5354

5355

5356 return &back();

5357}

5358

5359

5362 CFGBuilder Builder(C, BO);

5363 return Builder.buildCFG(D, Statement);

5364}

5365

5367

5368

5369 if (size() <= 3)

5370 return true;

5371

5372

5373

5374

5377 while (B != Exit) {

5378 auto IteratorAndFlag = Visited.insert(B);

5379 if (!IteratorAndFlag.second) {

5380

5381 return false;

5382 }

5383

5384

5385 const CFGBlock *FirstReachableB = nullptr;

5387 if (!AB.isReachable())

5388 continue;

5389

5390 if (FirstReachableB == nullptr) {

5391 FirstReachableB = &*AB;

5392 } else {

5393

5394 return false;

5395 }

5396 }

5397

5398 if (!FirstReachableB) {

5399

5400 return true;

5401 }

5402

5403

5404 B = FirstReachableB;

5405 }

5406

5407

5408 return true;

5409}

5410

5424 llvm_unreachable("getDestructorDecl should only be used with "

5425 "ImplicitDtors");

5428 QualType ty = var->getType();

5429

5430

5431

5432

5433

5435 if (const Expr *Init = var->getInit()) {

5437 }

5438 }

5439

5441 ty = arrayType->getElementType();

5442 }

5443

5444

5445

5446

5447

5449 assert(classDecl);

5451 }

5459 }

5465 }

5469

5471 ty = arrayType->getElementType();

5472 }

5473

5475 assert(classDecl);

5477 }

5479

5480 return nullptr;

5481 }

5482 llvm_unreachable("getKind() returned bogus value");

5483}

5484

5485

5486

5487

5488

5490 : ReachableBlock(IsReachable ? B : nullptr),

5491 UnreachableBlock(!IsReachable ? B : nullptr,

5492 B && IsReachable ? AB_Normal : AB_Unreachable) {}

5493

5495 : ReachableBlock(B),

5496 UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,

5497 B == AlternateBlock ? AB_Alternate : AB_Normal) {}

5498

5503

5505 UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);

5506

5507 Succs.push_back(Succ, C);

5508}

5509

5513 return true;

5514

5516

5517

5520 if (S->isAllEnumCasesCovered()) {

5523 return true;

5524 }

5525 }

5526 }

5527

5528 return false;

5529}

5530

5531

5532

5533

5534

5535namespace {

5536

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

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

5540

5541 StmtMapTy StmtMap;

5542 DeclMapTy DeclMap;

5543 signed currentBlock = 0;

5544 unsigned currStmt = 0;

5546

5547public:

5548 StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)

5549 : LangOpts(LO) {

5550 if (!cfg)

5551 return;

5553 unsigned j = 1;

5554 for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;

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

5556 if (std::optional SE = BI->getAs()) {

5557 const Stmt *stmt= SE->getStmt();

5558 std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);

5559 StmtMap[stmt] = P;

5560

5561 switch (stmt->getStmtClass()) {

5562 case Stmt::DeclStmtClass:

5563 DeclMap[cast(stmt)->getSingleDecl()] = P;

5564 break;

5565 case Stmt::IfStmtClass: {

5566 const VarDecl *var = cast(stmt)->getConditionVariable();

5567 if (var)

5568 DeclMap[var] = P;

5569 break;

5570 }

5571 case Stmt::ForStmtClass: {

5572 const VarDecl *var = cast(stmt)->getConditionVariable();

5573 if (var)

5574 DeclMap[var] = P;

5575 break;

5576 }

5577 case Stmt::WhileStmtClass: {

5578 const VarDecl *var =

5579 cast(stmt)->getConditionVariable();

5580 if (var)

5581 DeclMap[var] = P;

5582 break;

5583 }

5584 case Stmt::SwitchStmtClass: {

5585 const VarDecl *var =

5586 cast(stmt)->getConditionVariable();

5587 if (var)

5588 DeclMap[var] = P;

5589 break;

5590 }

5591 case Stmt::CXXCatchStmtClass: {

5592 const VarDecl *var =

5593 cast(stmt)->getExceptionDecl();

5594 if (var)

5595 DeclMap[var] = P;

5596 break;

5597 }

5598 default:

5599 break;

5600 }

5601 }

5602 }

5603 }

5604 }

5605

5606 ~StmtPrinterHelper() override = default;

5607

5608 const LangOptions &getLangOpts() const { return LangOpts; }

5609 void setBlockID(signed i) { currentBlock = i; }

5610 void setStmtID(unsigned i) { currStmt = i; }

5611

5612 bool handledStmt(Stmt *S, raw_ostream &OS) override {

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

5614

5615 if (I == StmtMap.end())

5616 return false;

5617

5618 if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock

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

5620 return false;

5621 }

5622

5623 OS << "[B" << I->second.first << "." << I->second.second << "]";

5624 return true;

5625 }

5626

5627 bool handleDecl(const Decl *D, raw_ostream &OS) {

5628 DeclMapTy::iterator I = DeclMap.find(D);

5629

5630 if (I == DeclMap.end()) {

5631

5632

5633 if (auto *PVD = dyn_cast_or_null(D)) {

5634 OS << "[Parm: " << PVD->getNameAsString() << "]";

5635 return true;

5636 }

5637 return false;

5638 }

5639

5640 if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock

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

5642 return false;

5643 }

5644

5645 OS << "[B" << I->second.first << "." << I->second.second << "]";

5646 return true;

5647 }

5648};

5649

5650class CFGBlockTerminatorPrint

5651 : public StmtVisitor<CFGBlockTerminatorPrint,void> {

5652 raw_ostream &OS;

5653 StmtPrinterHelper* Helper;

5654 PrintingPolicy Policy;

5655

5656public:

5657 CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,

5658 const PrintingPolicy &Policy)

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

5661 }

5662

5663 void VisitIfStmt(IfStmt *I) {

5664 OS << "if ";

5666 C->printPretty(OS, Helper, Policy);

5667 }

5668

5669

5670 void VisitStmt(Stmt *Terminator) {

5671 Terminator->printPretty(OS, Helper, Policy);

5672 }

5673

5674 void VisitDeclStmt(DeclStmt *DS) {

5676 OS << "static init " << VD->getName();

5677 }

5678

5679 void VisitForStmt(ForStmt *F) {

5680 OS << "for (" ;

5682 OS << "...";

5683 OS << "; ";

5685 C->printPretty(OS, Helper, Policy);

5686 OS << "; ";

5688 OS << "...";

5689 OS << ")";

5690 }

5691

5692 void VisitWhileStmt(WhileStmt *W) {

5693 OS << "while " ;

5695 C->printPretty(OS, Helper, Policy);

5696 }

5697

5698 void VisitDoStmt(DoStmt *D) {

5699 OS << "do ... while ";

5701 C->printPretty(OS, Helper, Policy);

5702 }

5703

5704 void VisitSwitchStmt(SwitchStmt *Terminator) {

5705 OS << "switch ";

5707 }

5708

5709 void VisitCXXTryStmt(CXXTryStmt *) { OS << "try ..."; }

5710

5711 void VisitObjCAtTryStmt(ObjCAtTryStmt *) { OS << "@try ..."; }

5712

5713 void VisitSEHTryStmt(SEHTryStmt *CS) { OS << "__try ..."; }

5714

5715 void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {

5716 if (Stmt *Cond = C->getCond())

5718 OS << " ? ... : ...";

5719 }

5720

5721 void VisitChooseExpr(ChooseExpr *C) {

5722 OS << "__builtin_choose_expr( ";

5723 if (Stmt *Cond = C->getCond())

5725 OS << " )";

5726 }

5727

5728 void VisitIndirectGotoStmt(IndirectGotoStmt *I) {

5729 OS << "goto *";

5731 T->printPretty(OS, Helper, Policy);

5732 }

5733

5734 void VisitBinaryOperator(BinaryOperator* B) {

5736 VisitExpr(B);

5737 return;

5738 }

5739

5742

5744 case BO_LOr:

5745 OS << " || ...";

5746 return;

5747 case BO_LAnd:

5748 OS << " && ...";

5749 return;

5750 default:

5751 llvm_unreachable("Invalid logical operator.");

5752 }

5753 }

5754

5755 void VisitExpr(Expr *E) {

5757 }

5758

5759public:

5760 void print(CFGTerminator T) {

5761 switch (T.getKind()) {

5763 Visit(T.getStmt());

5764 break;

5766 OS << "(Temp Dtor) ";

5767 Visit(T.getStmt());

5768 break;

5770 OS << "(See if most derived ctor has already initialized vbases)";

5771 break;

5772 }

5773 }

5774};

5775

5776}

5777

5784 else

5786 OS << "(";

5789 OS << ")";

5790

5792 OS << " (Base initializer)";

5794 OS << " (Delegating initializer)";

5795 else

5796 OS << " (Member initializer)";

5797}

5798

5800 StmtPrinterHelper &Helper,

5803 switch (CC->getKind()) {

5805 OS << ", ";

5808 return;

5809 }

5811 OS << ", ";

5812 const auto *CICC =

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

5816 break;

5817 }

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

5821 break;

5822 }

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

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

5827 break;

5828 }

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

5832 break;

5833 }

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

5837 break;

5838 }

5840 const auto *RSCC =

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

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

5844 break;

5845 }

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

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

5850 break;

5851 }

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

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

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

5857 break;

5858 }

5861 Helper.handledStmt(const_cast<LambdaExpr *>(LCC->getLambdaExpr()), OS);

5862 OS << "+" << LCC->getIndex();

5863 return;

5864 }

5867 if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {

5868 OS << ", ";

5869 Helper.handledStmt(const_cast<Stmt *>(BTE), OS);

5870 }

5871 OS << ", ";

5872 Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);

5873 OS << "+" << ACC->getIndex();

5874 return;

5875 }

5876 }

5877 for (auto I: Stmts)

5878 if (I) {

5879 OS << ", ";

5880 Helper.handledStmt(const_cast<Stmt *>(I), OS);

5881 }

5882}

5883

5884static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,

5885 const CFGElement &E, bool TerminateWithNewLine = true);

5886

5888 bool TerminateWithNewLine) const {

5890 StmtPrinterHelper Helper(nullptr, LangOpts);

5891 print_elem(OS, Helper, *this, TerminateWithNewLine);

5892}

5893

5894static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,

5895 const CFGElement &E, bool TerminateWithNewLine) {

5902 assert(S != nullptr && "Expecting non-null Stmt");

5903

5904

5905 if (const StmtExpr *SE = dyn_cast(S)) {

5907

5908 auto Children = Sub->children();

5910 OS << "({ ... ; ";

5912 OS << " })";

5913 if (TerminateWithNewLine)

5914 OS << '\n';

5915 return;

5916 }

5917 }

5918

5919 if (const BinaryOperator* B = dyn_cast(S)) {

5920 if (B->getOpcode() == BO_Comma) {

5921 OS << "... , ";

5922 Helper.handledStmt(B->getRHS(),OS);

5923 if (TerminateWithNewLine)

5924 OS << '\n';

5925 return;

5926 }

5927 }

5928 S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));

5929

5932 OS << " (OperatorCall)";

5933 OS << " (CXXRecordTypedCall";

5935 OS << ")";

5937 OS << " (OperatorCall)";

5939 OS << " (BindTemporary)";

5940 } else if (const CXXConstructExpr *CCE = dyn_cast(S)) {

5941 OS << " (CXXConstructExpr";

5944 }

5945 OS << ", " << CCE->getType() << ")";

5946 } else if (const CastExpr *CE = dyn_cast(S)) {

5947 OS << " (" << CE->getStmtClassName() << ", " << CE->getCastKindName()

5948 << ", " << CE->getType() << ")";

5949 }

5950

5951

5952 if (isa(S) && TerminateWithNewLine)

5953 OS << '\n';

5954

5955 return;

5956 }

5957

5960 break;

5961

5965 Helper.handleDecl(VD, OS);

5966

5968 if (T->isReferenceType())

5970

5971 OS << ".~";

5972 T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));

5973 OS << "() (Implicit destructor)";

5974 break;

5975 }

5976

5978 OS << "CleanupFunction ("

5980 break;

5981

5984 OS << " (Lifetime ends)";

5985 break;

5986

5989 << " (LoopExit)";

5990 break;

5991

5993 OS << "CFGScopeBegin(";

5996 OS << ")";

5997 break;

5998

6000 OS << "CFGScopeEnd(";

6003 OS << ")";

6004 break;

6005

6007 OS << "CFGNewAllocator(";

6009 AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));

6010 OS << ")";

6011 break;

6012

6016 if (!RD)

6017 return;

6021 OS << "->~" << RD->getName().str() << "()";

6022 OS << " (Implicit destructor)";

6023 break;

6024 }

6025

6029 OS << " (Base object destructor)";

6030 break;

6031 }

6032

6036 OS << "this->" << FD->getName();

6037 OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";

6038 OS << " (Member object destructor)";

6039 break;

6040 }

6041

6045 OS << "~";

6047 OS << "() (Temporary object destructor)";

6048 break;

6049 }

6050 }

6051 if (TerminateWithNewLine)

6052 OS << '\n';

6053}

6054

6057 StmtPrinterHelper &Helper, bool print_edges,

6058 bool ShowColors) {

6060

6061

6062 if (ShowColors)

6063 OS.changeColor(raw_ostream::YELLOW, true);

6064

6066

6068 OS << " (ENTRY)]\n";

6069 else if (&B == &cfg->getExit())

6070 OS << " (EXIT)]\n";

6072 OS << " (INDIRECT GOTO DISPATCH)]\n";

6074 OS << " (NORETURN)]\n";

6075 else

6076 OS << "]\n";

6077

6078 if (ShowColors)

6079 OS.resetColor();

6080

6081

6083 if (print_edges)

6084 OS << " ";

6085

6089 OS << "case ";

6090 if (const Expr *LHS = C->getLHS())

6092 if (const Expr *RHS = C->getRHS()) {

6093 OS << " ... ";

6095 }

6097 OS << "default";

6099 OS << "catch (";

6101 ED->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);

6102 else

6103 OS << "...";

6104 OS << ")";

6106 OS << "@catch (";

6107 if (const VarDecl *PD = CS->getCatchParamDecl())

6108 PD->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);

6109 else

6110 OS << "...";

6111 OS << ")";

6113 OS << "__except (";

6116 OS << ")";

6117 } else

6118 llvm_unreachable("Invalid label statement in CFGBlock.");

6119

6120 OS << ":\n";

6121 }

6122

6123

6124 unsigned j = 1;

6125

6127 I != E ; ++I, ++j ) {

6128

6129 if (print_edges)

6130 OS << " ";

6131

6132 OS << llvm::format("%3d", j) << ": ";

6133

6134 Helper.setStmtID(j);

6135

6137 }

6138

6139

6141 if (ShowColors)

6142 OS.changeColor(raw_ostream::GREEN);

6143

6144 OS << " T: ";

6145

6146 Helper.setBlockID(-1);

6147

6149 CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);

6151 OS << '\n';

6152

6153 if (ShowColors)

6154 OS.resetColor();

6155 }

6156

6157 if (print_edges) {

6158

6160 const raw_ostream::Colors Color = raw_ostream::BLUE;

6161 if (ShowColors)

6162 OS.changeColor(Color);

6163 OS << " Preds " ;

6164 if (ShowColors)

6165 OS.resetColor();

6166 OS << '(' << B.pred_size() << "):";

6167 unsigned i = 0;

6168

6169 if (ShowColors)

6170 OS.changeColor(Color);

6171

6173 I != E; ++I, ++i) {

6174 if (i % 10 == 8)

6175 OS << "\n ";

6176

6178 bool Reachable = true;

6179 if (!B) {

6180 Reachable = false;

6181 B = I->getPossiblyUnreachableBlock();

6182 }

6183

6185 if (!Reachable)

6186 OS << "(Unreachable)";

6187 }

6188

6189 if (ShowColors)

6190 OS.resetColor();

6191

6192 OS << '\n';

6193 }

6194

6195

6197 const raw_ostream::Colors Color = raw_ostream::MAGENTA;

6198 if (ShowColors)

6199 OS.changeColor(Color);

6200 OS << " Succs ";

6201 if (ShowColors)

6202 OS.resetColor();

6203 OS << '(' << B.succ_size() << "):";

6204 unsigned i = 0;

6205

6206 if (ShowColors)

6207 OS.changeColor(Color);

6208

6210 I != E; ++I, ++i) {

6211 if (i % 10 == 8)

6212 OS << "\n ";

6213

6215

6216 bool Reachable = true;

6217 if (!B) {

6218 Reachable = false;

6219 B = I->getPossiblyUnreachableBlock();

6220 }

6221

6222 if (B) {

6224 if (!Reachable)

6225 OS << "(Unreachable)";

6226 }

6227 else {

6228 OS << " NULL";

6229 }

6230 }

6231

6232 if (ShowColors)

6233 OS.resetColor();

6234 OS << '\n';

6235 }

6236 }

6237}

6238

6239

6241 print(llvm::errs(), LO, ShowColors);

6242}

6243

6244

6246 StmtPrinterHelper Helper(this, LO);

6247

6248

6250

6251

6252 for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {

6253

6255 continue;

6256

6257 print_block(OS, this, **I, Helper, true, ShowColors);

6258 }

6259

6260

6262 OS << '\n';

6263 OS.flush();

6264}

6265

6269

6270

6272 bool ShowColors) const {

6273 print(llvm::errs(), cfg, LO, ShowColors);

6274}

6275

6279

6280

6281

6283 const LangOptions &LO, bool ShowColors) const {

6284 StmtPrinterHelper Helper(cfg, LO);

6285 print_block(OS, cfg, *this, Helper, true, ShowColors);

6286 OS << '\n';

6287}

6288

6289

6292 CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));

6294}

6295

6296

6298 bool AddQuotes) const {

6299 std::string Buf;

6300 llvm::raw_string_ostream TempOut(Buf);

6301

6303

6305}

6306

6307

6308

6309

6310

6311

6312

6315 return true;

6316

6317

6318

6319

6320

6321

6322

6323 if (llvm::any_of(*Blk, [](const CFGElement &Elm) {

6324 if (std::optional StmtElm = Elm.getAs<CFGStmt>())

6326 return true;

6327 return false;

6328 }))

6329 return true;

6330

6331 return false;

6332}

6333

6336

6337 const CFGBlock *StartBlk = this;

6339 return true;

6340

6343

6344 DFSWorkList.push_back(StartBlk);

6345 while (!DFSWorkList.empty()) {

6346 const CFGBlock *Blk = DFSWorkList.pop_back_val();

6347 Visited.insert(Blk);

6348

6349

6350

6351

6352

6353 if (Blk == &Cfg.getExit())

6354 return false;

6355

6356 for (const auto &Succ : Blk->succs()) {

6357 if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {

6359

6360

6361 DFSWorkList.push_back(SuccBlk);

6362 }

6363 }

6364 }

6365 }

6366

6367

6368 return true;

6369}

6370

6372

6373

6375 return nullptr;

6376

6377

6378

6380 return nullptr;

6381

6382

6383 if (size() == 0)

6384 return nullptr;

6385

6387 if (!StmtElem)

6388 return nullptr;

6389

6390 const Stmt *Cond = StmtElem->getStmt();

6392 return nullptr;

6393

6394

6395

6397}

6398

6402 return nullptr;

6403

6404 Expr *E = nullptr;

6405

6406 switch (Terminator->getStmtClass()) {

6407 default:

6408 break;

6409

6410 case Stmt::CXXForRangeStmtClass:

6412 break;

6413

6414 case Stmt::ForStmtClass:

6416 break;

6417

6418 case Stmt::WhileStmtClass:

6420 break;

6421

6422 case Stmt::DoStmtClass:

6424 break;

6425

6426 case Stmt::IfStmtClass:

6428 break;

6429

6430 case Stmt::ChooseExprClass:

6432 break;

6433

6434 case Stmt::IndirectGotoStmtClass:

6436 break;

6437

6438 case Stmt::SwitchStmtClass:

6440 break;

6441

6442 case Stmt::BinaryConditionalOperatorClass:

6444 break;

6445

6446 case Stmt::ConditionalOperatorClass:

6448 break;

6449

6450 case Stmt::BinaryOperatorClass:

6452 break;

6453

6454 case Stmt::ObjCForCollectionStmtClass:

6456 }

6457

6458 if (!StripParens)

6459 return E;

6460

6462}

6463

6464

6465

6466

6467

6469

6471 StmtPrinterHelper H(this, LO);

6473 llvm::ViewGraph(this,"CFG");

6475}

6476

6477namespace llvm {

6478

6479template<>

6482

6484 std::string OutStr;

6485 llvm::raw_string_ostream Out(OutStr);

6487

6488 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());

6489

6490

6491 for (unsigned i = 0; i != OutStr.length(); ++i)

6492 if (OutStr[i] == '\n') {

6493 OutStr[i] = '\\';

6494 OutStr.insert(OutStr.begin()+i+1, 'l');

6495 }

6496

6497 return OutStr;

6498 }

6499};

6500

6501}

Defines the clang::ASTContext interface.

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

static StmtPrinterHelper * GraphHelper

Definition CFG.cpp:6468

static bool isCXXAssumeAttr(const AttributedStmt *A)

Definition CFG.cpp:2578

static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E, bool TerminateWithNewLine=true)

Definition CFG.cpp:5894

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

Definition CFG.cpp:5778

static SourceLocation GetEndLoc(Decl *D)

Definition CFG.cpp:66

static bool isBuiltinAssumeWithSideEffects(const ASTContext &Ctx, const CallExpr *CE)

Definition CFG.cpp:2803

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

Definition CFG.cpp:2788

static bool isFallthroughStatement(const AttributedStmt *A)

Definition CFG.cpp:2571

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

Definition CFG.cpp:6055

static bool isImmediateSinkBlock(const CFGBlock *Blk)

Definition CFG.cpp:6313

static const Expr * tryTransformToLiteralConstant(const Expr *E)

Helper for tryNormalizeBinaryOperator.

Definition CFG.cpp:102

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

Definition CFG.cpp:1862

static const VariableArrayType * FindVA(const Type *t)

Definition CFG.cpp:1501

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

Definition CFG.cpp:117

static bool IsLiteralConstantExpr(const Expr *E)

Returns true on constant values based around a single IntegerLiteral, CharacterLiteral,...

Definition CFG.cpp:77

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

Definition CFG.cpp:5799

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

Definition CFG.cpp:4565

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

Definition CFG.cpp:147

static TryResult bothKnownTrue(TryResult R1, TryResult R2)

Definition CFG.cpp:422

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

static Decl::Kind getKind(const Decl *D)

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.

SmallVector< AnnotatedLine *, 1 > Children

If this token starts a block, this contains all the unwrapped lines in it.

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

ValueKind getKind() 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

int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const

Compare the rank of two floating point types as above, but compare equal if both types have the same ...

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.

Expr * getCond() const

getCond - Return the expression representing the condition for the ?

Expr * getTrueExpr() const

getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...

Expr * getFalseExpr() const

getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...

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

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 isCommaOp(Opcode Opc)

static bool isAssignmentOp(Opcode Opc)

static bool isEqualityOp(Opcode Opc)

ArrayRef< Capture > captures() const

const BlockDecl * getBlockDecl() const

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.

Definition CFG.cpp:5489

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.

Definition CFG.cpp:6290

void setLoopTarget(const Stmt *loopTarget)

bool isInevitablySinking() const

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

Definition CFG.cpp:6334

size_t getIndexInCFG() const

Definition CFG.cpp:6266

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

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

Definition CFG.cpp:5510

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.

Definition CFG.cpp:6282

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.

Definition CFG.cpp:6297

void dump() const

Definition CFG.cpp:6276

void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)

CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)

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

Definition CFG.cpp:6371

Stmt * getTerminatorCondition(bool StripParens=true)

Definition CFG.cpp:6399

void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)

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

Definition CFG.cpp:5499

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.

T castAs() const

Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.

void dumpToStream(llvm::raw_ostream &OS, bool TerminateWithNewLine=true) const

Definition CFG.cpp:5887

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

Definition CFG.cpp:5412

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

@ 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 AssumeReachableDefaultInSwitchStatements

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

CFGBlockListTy::const_iterator const_iterator

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

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

Definition CFG.cpp:6245

bool isLinear() const

Returns true if the CFG has no branches.

Definition CFG.cpp:5366

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

Builds a CFG from an AST.

Definition CFG.cpp:5360

llvm::BumpPtrAllocator & getAllocator()

CFGBlock * createBlock()

Create a new block in the CFG.

Definition CFG.cpp:5344

CFGBlock * getIndirectGotoBlock()

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

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

Definition CFG.cpp:6240

void viewCFG(const LangOptions &LO) const

Definition CFG.cpp:6470

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()

const Expr * getSubExpr() const

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

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.

DeclStmt * getBeginStmt()

DeclStmt * getLoopVarStmt()

DeclStmt * getRangeStmt()

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

ExprIterator arg_iterator

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

const CXXDestructorDecl * getDestructor() const

CXXCatchStmt * getHandler(unsigned i)

unsigned getNumHandlers() const

CompoundStmt * getTryBlock()

bool isPotentiallyEvaluated() const

Determine whether this typeid has a type operand which is potentially evaluated, per C++11 [expr....

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

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

unsigned getBuiltinCallee() const

getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.

CaseStmt - Represent a case statement.

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

CastKind getCastKind() const

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

reverse_body_iterator body_rbegin()

@ ElidableConstructorKind

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

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.

Expr * getReadyExpr() const

Expr * getResumeExpr() const

Expr * getSuspendExpr() const

Expr * getCommonExpr() const

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

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.

ASTContext & getASTContext() const LLVM_READONLY

SourceLocation getLocation() const

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.

bool isValueDependent() const

Determines whether the value of this expression depends on.

bool isTypeDependent() const

Determines whether the type of this expression depends on.

llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) 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 EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const

EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...

bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const

HasSideEffects - This routine returns true for all those expressions which have any effect other than...

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.

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 prototype with parameter type info, e.g.

FunctionType - C99 6.7.5.3 - Function Declarators.

LabelDecl * getLabel() const

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.

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

Expr ** capture_init_iterator

Iterator that walks over the capture initialization arguments.

capture_init_iterator capture_init_end()

Retrieve the iterator pointing one past the last initialization argument for this lambda expression.

capture_init_iterator capture_init_begin()

Retrieve the first initialization argument for this lambda expression (which initializes the first ca...

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.

StringRef getName() const

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

std::string getQualifiedNameAsString() const

Represents Objective-C's @catch statement.

const Stmt * getCatchBody() const

const Expr * getSynchExpr() const

const CompoundStmt * getSynchBody() const

const ObjCAtFinallyStmt * getFinallyStmt() const

Retrieve the @finally statement, if any.

const Stmt * getTryBody() const

Retrieve the @try body.

catch_range catch_stmts()

const Stmt * getSubStmt() const

unsigned getNumSemanticExprs() const

Expr * getSemanticExpr(unsigned index)

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

CompoundStmt * getBlock() const

Expr * getFilterExpr() const

CompoundStmt * getBlock() const

CompoundStmt * getTryBlock() const

SEHFinallyStmt * getFinallyHandler() const

SEHExceptStmt * getExceptHandler() const

Returns 0 if not defined.

Encodes a location in the source.

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

CompoundStmt * getSubStmt()

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.

bool isBlockPointerType() const

CXXRecordDecl * getAsCXXRecordDecl() const

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

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

QualType getArgumentType() const

bool isArgumentType() const

UnaryExprOrTypeTrait getKind() const

Expr * getSubExpr() const

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.

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

const internal::VariadicAllOfMatcher< Stmt > stmt

Matches statements.

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

bool Sub(InterpState &S, CodePtr OpPC)

bool NE(InterpState &S, CodePtr OpPC)

bool LE(InterpState &S, CodePtr OpPC)

bool Cast(InterpState &S, CodePtr OpPC)

std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl

All declarations that can appear in a module declaration.

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

bool isa(CodeGen::Address addr)

bool hasSpecificAttr(const Container &container)

FunctionType::ExtInfo getFunctionExtInfo(const Type &t)

bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)

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

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

@ SD_FullExpression

Full-expression storage duration (for temporaries).

@ Result

The result type of a method or function.

const FunctionProtoType * T

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

@ Type

The name was classified as a type.

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

U cast(CodeGen::Address addr)

Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)

Definition CFG.cpp:1448

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.

DOTGraphTraits(bool isSimple=false)

Definition CFG.cpp:6481

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

Definition CFG.cpp:6483