clang: include/clang/Analysis/CFG.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14#ifndef LLVM_CLANG_ANALYSIS_CFG_H

15#define LLVM_CLANG_ANALYSIS_CFG_H

16

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

24#include "llvm/ADT/GraphTraits.h"

25#include "llvm/ADT/PointerIntPair.h"

26#include "llvm/ADT/iterator_range.h"

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

28#include "llvm/Support/raw_ostream.h"

29#include

30#include

31#include

32#include

33#include

34#include

35#include

36

38

39class ASTContext;

40class BinaryOperator;

41class CFG;

42class CXXBaseSpecifier;

43class CXXBindTemporaryExpr;

44class CXXCtorInitializer;

45class CXXDeleteExpr;

46class CXXDestructorDecl;

47class CXXNewExpr;

48class CXXRecordDecl;

50class FieldDecl;

51class LangOptions;

52class VarDecl;

53

54

56public:

58

65

71

80 };

81

82protected:

83

84 llvm::PointerIntPair<void *, 2> Data1;

85 llvm::PointerIntPair<void *, 2> Data2;

86

87 CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr)

88 : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),

89 Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {

90 assert(getKind() == kind);

91 }

92

94

95public:

96

97

98 template

100 assert(T::isKind(*this));

101 T t;

103 e = *this;

104 return t;

105 }

106

107

108

109 template std::optional getAs() const {

110 if (!T::isKind(*this))

111 return std::nullopt;

112 T t;

114 e = *this;

115 return t;

116 }

117

119 unsigned x = Data2.getInt();

120 x <<= 2;

121 x |= Data1.getInt();

122 return (Kind) x;

123 }

124

125 void dumpToStream(llvm::raw_ostream &OS) const;

126

129 }

130};

131

133public:

135 assert(isKind(*this));

136 }

137

139 return static_cast<const Stmt *>(Data1.getPointer());

140 }

141

142private:

144

145 static bool isKind(const CFGElement &E) {

147 }

148

149protected:

151};

152

153

154

155

157public:

161 assert(C);

163 }

164

167 }

168

169private:

171

173

174 static bool isKind(const CFGElement &E) {

176 }

177};

178

179

180

181

182

183

184

186public:

187

188

190 assert(isa(E) || isa(E));

191

192

193

194 return E->isGLValue() &&

195 E->getType().getCanonicalType()->getAsCXXRecordDecl();

196 }

197

201 assert(C && (isa(C) ||

202

203 isa(C) ||

204 isa(C) ||

205 isa(C) ||

206 isa(C) ||

207 isa(C)));

209 }

210

213 }

214

215private:

217

219

220 static bool isKind(const CFGElement &E) {

222 }

223};

224

225

226

228public:

231

234 }

235

236private:

238

240

241 static bool isKind(const CFGElement &E) {

243 }

244};

245

246

248public:

251

252

255 }

256

257private:

259

261

262 static bool isKind(const CFGElement &elem) {

264 }

265};

266

267

268

269

270

271

272

274public:

276

278 return static_cast<Stmt *>(Data1.getPointer());

279 }

280

281private:

283

285

286 static bool isKind(const CFGElement &elem) {

288 }

289};

290

291

293public:

296

298 return static_cast<VarDecl *>(Data1.getPointer());

299 }

300

302 return static_cast<Stmt *>(Data2.getPointer());

303 }

304

305private:

307

309

310 static bool isKind(const CFGElement &elem) {

312 }

313};

314

315

316

318public:

322

323

325 return static_cast<Stmt*>(Data2.getPointer());

326 }

327

328

330 return static_cast<VarDecl *>(Data1.getPointer());

331 }

332

333private:

335 static bool isKind(const CFGElement &E) {

336 Kind kind = E.getKind();

338 }

339};

340

341

342

344public:

347

349 return static_cast<VarDecl *>(Data1.getPointer());

350 }

351

353 return static_cast<Stmt *>(Data2.getPointer());

354 }

355

356private:

358 static bool isKind(const CFGElement &E) {

359 Kind kind = E.getKind();

361 }

362};

363

364

365

367protected:

369

373 }

374

375public:

378

379private:

381

382 static bool isKind(const CFGElement &E) {

383 Kind kind = E.getKind();

385 }

386};

387

389public:

393 assert(VD->hasAttr());

394 }

395

397 return static_cast<VarDecl *>(Data1.getPointer());

398 }

399

400

403 return A->getFunctionDecl();

404 }

405

406private:

408

411 }

412};

413

414

415

416

418public:

421

423 return static_cast<VarDecl*>(Data1.getPointer());

424 }

425

426

428 return static_cast<Stmt*>(Data2.getPointer());

429 }

430

431private:

433

435

436 static bool isKind(const CFGElement &elem) {

438 }

439};

440

441

443public:

446

449 }

450

451

454 }

455

456private:

458

460

461 static bool isKind(const CFGElement &elem) {

463 }

464};

465

466

467

469public:

472

475 }

476

477private:

479

481

482 static bool isKind(const CFGElement &E) {

484 }

485};

486

487

488

490public:

493

495 return static_cast<const FieldDecl*>(Data1.getPointer());

496 }

497

498private:

500

502

503 static bool isKind(const CFGElement &E) {

505 }

506};

507

508

509

511public:

514

517 }

518

519private:

521

523

524 static bool isKind(const CFGElement &E) {

526 }

527};

528

529

530

532public:

534

535

537

538

539

541

542

543

545

546

547

548

551

552private:

553 static constexpr int KindBits = 2;

555 "Not enough room for kind!");

556 llvm::PointerIntPair<Stmt *, KindBits> Data;

557

558public:

561

562 bool isValid() const { return Data.getOpaqueValue() != nullptr; }

566

569 }

572 }

575 }

576};

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

605 class ElementList {

607

608 ImplTy Impl;

609

610 public:

612

613 using iterator = std::reverse_iteratorImplTy::iterator;

614 using const_iterator = std::reverse_iteratorImplTy::const\_iterator;

618

620

623 return Impl.insert(I, Cnt, E, C);

624 }

625

626 const_reference front() const { return Impl.back(); }

627 const_reference back() const { return Impl.front(); }

628

629 iterator begin() { return Impl.rbegin(); }

630 iterator end() { return Impl.rend(); }

631 const_iterator begin() const { return Impl.rbegin(); }

637

638 CFGElement operator[](size_t i) const {

639 assert(i < Impl.size());

640 return Impl[Impl.size() - 1 - i];

641 }

642

643 size_t size() const { return Impl.size(); }

644 bool empty() const { return Impl.empty(); }

645 };

646

647

648

649

650 template class ElementRefImpl {

651

652 template friend class ElementRefImpl;

653

654 using CFGBlockPtr =

655 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;

656

657 using CFGElementPtr =

658 std::conditional_t<IsConst, const CFGElement *, CFGElement *>;

659

660 protected:

662 size_t Index;

663

664 public:

665 ElementRefImpl(CFGBlockPtr Parent, size_t Index)

667

668 template

669 ElementRefImpl(ElementRefImpl Other)

670 : ElementRefImpl(Other.Parent, Other.Index) {}

671

672 size_t getIndexInBlock() const { return Index; }

673

674 CFGBlockPtr getParent() { return Parent; }

675 CFGBlockPtr getParent() const { return Parent; }

676

678 return std::make_pair(Parent, Index) <

679 std::make_pair(Other.Parent, Other.Index);

680 }

681

684 }

685

686 bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }

688 CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }

689

690 void dumpToStream(llvm::raw_ostream &OS) const {

691 OS << getIndexInBlock() + 1 << ": ";

692 (*this)->dumpToStream(OS);

693 }

694

695 void dump() const {

696 dumpToStream(llvm::errs());

697 }

698 };

699

700 template <bool IsReverse, bool IsConst> class ElementRefIterator {

701

702 template <bool IsOtherReverse, bool IsOtherConst>

703 friend class ElementRefIterator;

704

705 using CFGBlockRef =

706 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;

707

708 using UnderlayingIteratorTy = std::conditional_t<

709 IsConst,

711 ElementList::const_iterator>,

713 ElementList::iterator>>;

714

715 using IteratorTraits = typename std::iterator_traits;

716 using ElementRef = typename CFGBlock::ElementRefImpl;

717

718 public:

719 using difference_type = typename IteratorTraits::difference_type;

720 using value_type = ElementRef;

721 using pointer = ElementRef *;

722 using iterator_category = typename IteratorTraits::iterator_category;

723

724 private:

726 UnderlayingIteratorTy Pos;

727

728 public:

729 ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos)

731

732 template

733 ElementRefIterator(ElementRefIterator<false, IsOtherConst> E)

734 : ElementRefIterator(E.Parent, E.Pos.base()) {}

735

736 template

737 ElementRefIterator(ElementRefIterator<true, IsOtherConst> E)

738 : ElementRefIterator(E.Parent, std::make_reverse_iterator(E.Pos)) {}

739

742 return Pos < Other.Pos;

743 }

744

747 }

748

749 bool operator!=(ElementRefIterator Other) const {

750 return !(*this == Other);

751 }

752

753 private:

754 template

755 static size_t

756 getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) {

757 return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1;

758 }

759

760 template

761 static size_t

762 getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) {

763 return E.Pos - E.Parent->begin();

764 }

765

766 public:

767 value_type operator*() { return {Parent, getIndexInBlock(*this)}; }

768

769 difference_type operator-(ElementRefIterator Other) const {

770 return Pos - Other.Pos;

771 }

772

773 ElementRefIterator operator++() {

774 ++this->Pos;

775 return *this;

776 }

777 ElementRefIterator operator++(int) {

778 ElementRefIterator Ret = *this;

779 ++*this;

780 return Ret;

781 }

782 ElementRefIterator operator+(size_t count) {

783 this->Pos += count;

784 return *this;

785 }

786 ElementRefIterator operator-(size_t count) {

787 this->Pos -= count;

788 return *this;

789 }

790 };

791

792public:

793

795

796

797

798

800

801

802

804

805

806

807

809

810

812

813public:

814

815

816

817

818

820 enum Kind {

821 AB_Normal,

822 AB_Unreachable,

823 AB_Alternate

824 };

825

827 llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock;

828

829 public:

830

832

833

834

836

837

839 return ReachableBlock;

840 }

841

842

844 return UnreachableBlock.getPointer();

845 }

846

847

848

851 }

852

855 }

856

859 }

860

862 Kind K = (Kind) UnreachableBlock.getInt();

863 return K == AB_Normal || K == AB_Alternate;

864 }

865 };

866

867private:

868

870 AdjacentBlocks Preds;

871 AdjacentBlocks Succs;

872

873

874

875

876

877

878

879

880

881

882 LLVM_PREFERRED_TYPE(bool)

883 unsigned HasNoReturnElement : 1;

884

885

886 CFG *Parent;

887

888public:

891 Succs(C, 1), HasNoReturnElement(false), Parent(parent) {}

892

893

898

900

903

908

913

916

921

924

927 llvm::iterator_range<const_reverse_ref_iterator>;

928

933

938

944 }

945

948

950

951

956 using pred_range = llvm::iterator_range<pred_iterator>;

958

963 using succ_range = llvm::iterator_range<succ_iterator>;

965

970

975

978 }

979

982 }

983

988

993

996 }

997

1000 }

1001

1002 unsigned succ_size() const { return Succs.size(); }

1004

1005 unsigned pred_size() const { return Preds.size(); }

1007

1008

1010 public:

1011 LLVM_PREFERRED_TYPE(bool)

1013 LLVM_PREFERRED_TYPE(bool)

1015

1018 };

1019

1022

1023 template <typename IMPL, bool IsPred>

1025 private:

1029

1030 public:

1034 : I(i), E(e), F(f), From(from) {

1035 while (hasMore() && Filter(*I))

1036 ++I;

1037 }

1038

1040

1042 do { ++I; } while (hasMore() && Filter(*I));

1043 return *this;

1044 }

1045

1047

1048 private:

1049 bool Filter(const CFGBlock *To) {

1051 }

1052 };

1053

1056

1059

1062 }

1063

1066 }

1067

1068

1069

1074

1075

1076

1078

1080

1083

1084

1085

1086

1087

1088

1089

1091

1093

1096 }

1097

1099

1102

1104

1106

1108

1109 void dump() const;

1110

1114

1117 bool AddQuotes) const;

1118

1121 }

1122

1123

1125

1128 }

1129

1133 }

1134

1139 }

1140

1144 }

1145

1149 }

1150

1154 }

1155

1158 }

1159

1162 }

1163

1166 }

1167

1170 }

1171

1174 }

1175

1178 }

1179

1182 }

1183

1186 }

1187

1190 }

1191};

1192

1193

1194

1196public:

1199

1203 bool isAlwaysTrue) {}

1205};

1206

1207

1208

1209

1210

1211

1212

1213

1215public:

1216

1217

1218

1219

1221

1222

1223 std::bitset<Stmt::lastStmtConstant + 1> alwaysAddMask;

1224

1225 public:

1226 using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>;

1227

1246

1248

1250 return alwaysAddMask[stmt->getStmtClass()];

1251 }

1252

1254 alwaysAddMask[stmtClass] = val;

1255 return *this;

1256 }

1257

1259 alwaysAddMask.set();

1260 return *this;

1261 }

1262 };

1263

1264

1266 const BuildOptions &BO);

1267

1268

1269

1271

1272

1273

1274

1276

1277

1278

1280

1281

1282

1283

1284

1290

1293

1298

1301

1302 llvm::iterator_range nodes() { return {begin(), end()}; }

1303 llvm::iterator_range<const_iterator> const_nodes() const {

1305 }

1306

1309

1314

1317 }

1320 }

1321

1326

1329

1332

1334 return TryDispatchBlocks.begin();

1335 }

1336

1338 return TryDispatchBlocks.end();

1339 }

1340

1343 }

1344

1346 TryDispatchBlocks.push_back(block);

1347 }

1348

1349

1350

1351

1352

1355 assert(Synthetic->isSingleDecl() && "Can handle single declarations only");

1356 assert(Synthetic != Source && "Don't include original DeclStmts in map");

1357 assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map");

1358 SyntheticDeclStmts[Synthetic] = Source;

1359 }

1360

1362 llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator;

1364

1365

1366

1367

1368

1369

1371 return SyntheticDeclStmts.begin();

1372 }

1373

1374

1376 return SyntheticDeclStmts.end();

1377 }

1378

1379

1382 }

1383

1384

1385

1386

1387

1391 BI != BE; ++BI) {

1392 if (std::optional stmt = BI->getAs<CFGStmt>())

1393 O(const_cast<Stmt *>(stmt->getStmt()));

1394 }

1395 }

1396

1397

1398

1399

1400

1401

1403

1404

1405

1406

1407 unsigned size() const { return NumBlockIDs; }

1408

1409

1410

1411

1412

1414

1415

1416

1417

1418

1422

1423

1424

1425

1426

1427 CFG() : Blocks(BlkBVC, 10) {}

1428

1431 }

1432

1434 return BlkBVC;

1435 }

1436

1437private:

1440

1441

1442 CFGBlock* IndirectGotoBlock = nullptr;

1443

1444 unsigned NumBlockIDs = 0;

1445

1447

1449

1450

1451

1452 std::vector<const CFGBlock *> TryDispatchBlocks;

1453

1454

1455

1456 llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;

1457};

1458

1460

1461}

1462

1463

1464

1465

1466

1467namespace llvm {

1468

1469

1470

1473

1476 }

1477};

1478

1479

1480

1484

1488};

1489

1491 using NodeRef = const ::clang::CFGBlock *;

1493

1497};

1498

1502

1504 return G.Graph;

1505 }

1506

1509};

1510

1512 using NodeRef = const ::clang::CFGBlock *;

1514

1516 return G.Graph;

1517 }

1518

1521};

1522

1523

1524

1526 : public GraphTraits< ::clang::CFGBlock *> {

1528

1533};

1534

1536 : public GraphTraits<const ::clang::CFGBlock *> {

1538

1540

1542 return F->nodes_begin();

1543 }

1544

1546 return F->nodes_end();

1547 }

1548

1549 static unsigned size(const ::clang::CFG* F) {

1550 return F->size();

1551 }

1552};

1553

1554template <> struct GraphTraits<Inverse< ::clang::CFG *>>

1555 : public GraphTraits<Inverse< ::clang::CFGBlock *>> {

1557

1561};

1562

1563template <> struct GraphTraits<Inverse<const ::clang::CFG *>>

1564 : public GraphTraits<Inverse<const ::clang::CFGBlock *>> {

1566

1568

1570 return F->nodes_begin();

1571 }

1572

1574 return F->nodes_end();

1575 }

1576};

1577

1578}

1579

1580#endif

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

static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)

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

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

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

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

llvm::BumpPtrAllocator & getAllocator()

std::reverse_iterator< const_iterator > const_reverse_iterator

const CFGElement & const_reference

reverse_iterator rbegin()

std::reverse_iterator< iterator > reverse_iterator

const CFGElement * const_iterator

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

const VarDecl * getVarDecl() const

const Stmt * getTriggerStmt() const

CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)

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

CFGBaseDtor(const CXXBaseSpecifier *base)

const CXXBaseSpecifier * getBaseSpecifier() const

This class represents a potential adjacent block in the CFG.

CFGBlock & operator*() const

CFGBlock * operator->() const

CFGBlock * getReachableBlock() const

Get the reachable block, if one exists.

CFGBlock * getPossiblyUnreachableBlock() const

Get the potentially unreachable block.

unsigned IgnoreNullPredecessors

unsigned IgnoreDefaultsWithCoveredEnums

FilteredCFGBlockIterator & operator++()

const CFGBlock * operator*() const

FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, const FilterOptions &f)

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

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

FilteredCFGBlockIterator< const_succ_iterator, false > filtered_succ_iterator

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

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

ElementList::iterator iterator

void setLoopTarget(const Stmt *loopTarget)

bool isInevitablySinking() const

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

filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const

size_t getIndexInCFG() const

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

AdjacentBlocks::reverse_iterator pred_reverse_iterator

const_reverse_iterator rend() const

CFGElement operator[](size_t i) const

llvm::iterator_range< pred_iterator > pred_range

FilteredCFGBlockIterator< const_pred_iterator, true > filtered_pred_iterator

const_reverse_ref_iterator_range rrefs() const

llvm::iterator_range< const_succ_iterator > succ_const_range

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

ElementRefIterator< false, false > ref_iterator

reverse_iterator rbegin()

void setTerminator(CFGTerminator Term)

void printAsOperand(raw_ostream &OS, bool)

void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)

llvm::iterator_range< const_reverse_ref_iterator > const_reverse_ref_iterator_range

filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const

llvm::iterator_range< reverse_ref_iterator > reverse_ref_iterator_range

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

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

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

ElementList::const_iterator const_iterator

const Stmt * getLabel() const

AdjacentBlocks::iterator pred_iterator

pred_reverse_iterator pred_rend()

bool hasNoReturnElement() const

succ_reverse_iterator succ_rend()

ElementRefIterator< true, false > reverse_ref_iterator

const_reverse_ref_iterator rref_end() const

const_succ_iterator succ_begin() const

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

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

const_pred_iterator pred_end() const

const_iterator begin() const

void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)

unsigned BlockID

A numerical ID assigned to a CFGBlock during construction of the CFG.

const_pred_reverse_iterator pred_rbegin() const

succ_reverse_iterator succ_rbegin()

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

printTerminatorJson - Pretty-prints the terminator in JSON format.

llvm::iterator_range< ref_iterator > ref_iterator_range

AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator

ref_iterator_range refs()

ElementRefIterator< false, true > const_ref_iterator

ElementRefImpl< true > ConstCFGElementRef

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.

const_ref_iterator ref_begin() const

CFGTerminator getTerminator() const

succ_iterator succ_begin()

Stmt * getTerminatorStmt()

const_succ_reverse_iterator succ_rend() const

void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)

const Stmt * getLoopTarget() const

AdjacentBlocks::const_iterator const_pred_iterator

succ_const_range succs() const

unsigned pred_size() const

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

AdjacentBlocks::iterator succ_iterator

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

pred_const_range preds() const

ElementList Elements

The set of statements in the basic block.

const_reverse_iterator rbegin() const

ElementRefImpl< false > CFGElementRef

pred_reverse_iterator pred_rbegin()

ElementRefIterator< true, true > const_reverse_ref_iterator

pred_iterator pred_begin()

const Stmt * LoopTarget

Some blocks are used to represent the "loop edge" to the start of a loop from within the loop body.

reverse_ref_iterator rref_begin()

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

reverse_ref_iterator rref_end()

const Stmt * getTerminatorStmt() const

const_ref_iterator_range refs() const

const_iterator end() const

const_ref_iterator ref_end() const

void setLabel(Stmt *Statement)

unsigned getBlockID() const

const_succ_reverse_iterator succ_rbegin() const

void appendStmt(Stmt *statement, BumpVectorContext &C)

llvm::iterator_range< const_ref_iterator > const_ref_iterator_range

void setHasNoReturnElement()

const_pred_iterator pred_begin() const

const Stmt * getTerminatorCondition(bool StripParens=true) const

const_succ_iterator succ_end() const

const Expr * getLastCondition() const

const_pred_reverse_iterator pred_rend() const

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

AdjacentBlocks::reverse_iterator succ_reverse_iterator

Stmt * getTerminatorCondition(bool StripParens=true)

AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator

void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)

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

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

AdjacentBlocks::const_iterator const_succ_iterator

reverse_ref_iterator_range rrefs()

CFGTerminator Terminator

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

llvm::iterator_range< succ_iterator > succ_range

unsigned succ_size() const

const_reverse_ref_iterator rref_begin() const

llvm::iterator_range< const_pred_iterator > pred_const_range

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

const ConstructionContext * getConstructionContext() const

CFGCXXRecordTypedCall(const Expr *E, const ConstructionContext *C)

static bool isCXXRecordTypedCall(const Expr *E)

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

CFGCallback defines methods that should be called when a logical operator error is found when buildin...

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)

virtual ~CFGCallback()=default

CFGCleanupFunction(const VarDecl *VD)

const VarDecl * getVarDecl() const

const FunctionDecl * getFunctionDecl() const

Returns the function to be called when cleaning up the var decl.

CFGCleanupFunction()=default

Represents C++ constructor call.

const ConstructionContext * getConstructionContext() const

CFGConstructor(const CXXConstructExpr *CE, const ConstructionContext *C)

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

CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)

const CXXDeleteExpr * getDeleteExpr() const

const CXXRecordDecl * getCXXRecordDecl() const

Represents a top-level expression in a basic block.

void dumpToStream(llvm::raw_ostream &OS) const

T castAs() const

Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.

llvm::PointerIntPair< void *, 2 > Data1

llvm::PointerIntPair< void *, 2 > Data2

std::optional< T > getAs() const

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

CFGElement(Kind kind, const void *Ptr1, const void *Ptr2=nullptr)

Represents C++ object destructor implicitly generated by compiler on various occasions.

const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const

CFGImplicitDtor(Kind kind, const void *data1, const void *data2=nullptr)

CFGImplicitDtor()=default

bool isNoReturn(ASTContext &astContext) const

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

CXXCtorInitializer * getInitializer() const

CFGInitializer(const CXXCtorInitializer *initializer)

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

CFGLifetimeEnds(const VarDecl *var, const Stmt *stmt)

const Stmt * getTriggerStmt() const

const VarDecl * getVarDecl() const

Represents the point where a loop ends.

const Stmt * getLoopStmt() const

CFGLoopExit(const Stmt *stmt)

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

const FieldDecl * getFieldDecl() const

CFGMemberDtor(const FieldDecl *field)

Represents C++ allocator call.

const CXXNewExpr * getAllocatorExpr() const

CFGNewAllocator(const CXXNewExpr *S)

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

const VarDecl * getVarDecl() const

const Stmt * getTriggerStmt() const

CFGScopeBegin(const VarDecl *VD, const Stmt *S)

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

CFGScopeEnd(const VarDecl *VD, const Stmt *S)

const Stmt * getTriggerStmt() const

const VarDecl * getVarDecl() const

CFGStmt(const Stmt *S, Kind K=Statement)

const Stmt * getStmt() const

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

const CXXBindTemporaryExpr * getBindTemporaryExpr() const

CFGTemporaryDtor(const CXXBindTemporaryExpr *expr)

Represents CFGBlock terminator statement.

bool isVirtualBaseBranch() const

bool isTemporaryDtorsBranch() const

bool isStmtBranch() const

CFGTerminator(Stmt *S, Kind K=StmtBranch)

const Stmt * getStmt() const

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

@ NumKindsMinusOne

Number of different kinds, for assertions.

bool PruneTriviallyFalseEdges

bool AddStaticInitBranches

bool OmitImplicitValueInitializers

ForcedBlkExprs ** forcedBlkExprs

bool AddCXXDefaultInitExprInAggregates

bool AddCXXDefaultInitExprInCtors

BuildOptions & setAllAlwaysAdd()

BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)

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

llvm::iterator_range< synthetic_stmt_iterator > synthetic_stmt_range

CFGBlockListTy::const_iterator const_iterator

const_iterator nodes_end() const

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

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

llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator

std::reverse_iterator< const_iterator > const_reverse_iterator

try_block_range try_blocks() const

bool isLinear() const

Returns true if the CFG has no branches.

synthetic_stmt_range synthetic_stmts() const

void VisitBlockStmts(Callback &O) const

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

Builds a CFG from an AST.

llvm::BumpPtrAllocator & getAllocator()

std::reverse_iterator< iterator > reverse_iterator

CFGBlockListTy::iterator iterator

const_reverse_iterator rbegin() const

const_iterator end() const

CFGBlock * createBlock()

Create a new block in the CFG.

void addSyntheticDeclStmt(const DeclStmt *Synthetic, const DeclStmt *Source)

Records a synthetic DeclStmt and the DeclStmt it was constructed from.

const CFGBlock * getIndirectGotoBlock() const

llvm::iterator_range< try_block_iterator > try_block_range

const_iterator begin() const

void setIndirectGotoBlock(CFGBlock *B)

Set the block used for indirect goto jumps.

void addTryDispatchBlock(const CFGBlock *block)

try_block_iterator try_blocks_end() const

synthetic_stmt_iterator synthetic_stmt_end() const

void setEntry(CFGBlock *B)

Set the entry block of the CFG.

llvm::iterator_range< const_iterator > const_nodes() const

const CFGBlock & getEntry() const

CFGBlock * getIndirectGotoBlock()

llvm::iterator_range< reverse_iterator > reverse_nodes()

std::vector< const CFGBlock * >::const_iterator try_block_iterator

const CFGBlock & getExit() const

llvm::iterator_range< const_reverse_iterator > const_reverse_nodes() const

const_reverse_iterator rend() const

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

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

unsigned getNumBlockIDs() const

Returns the total number of BlockIDs allocated (which start at 0).

const_iterator nodes_begin() const

void viewCFG(const LangOptions &LO) const

try_block_iterator try_blocks_begin() const

BumpVector< CFGBlock * > CFGBlockListTy

synthetic_stmt_iterator synthetic_stmt_begin() const

Iterates over synthetic DeclStmts in the CFG.

reverse_iterator rbegin()

llvm::iterator_range< iterator > nodes()

BumpVectorContext & getBumpVectorContext()

Represents a base class of a C++ class.

Represents binding an expression to a temporary.

Represents a call to a C++ constructor.

Represents a C++ base or member initializer.

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

Represents a C++ destructor within a class.

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

Represents a C++ struct/union/class.

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

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

bool isSingleDecl() const

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

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

This represents one expression.

Represents a member of a struct/union/class.

Represents a function declaration or definition.

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

Represents a point when we exit a loop.

Stmt - This represents one statement.

Represents a variable declaration or definition.

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

const internal::VariadicAllOfMatcher< Stmt > stmt

Matches statements.

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

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

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

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

const FunctionProtoType * T

Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)

@ Other

Other implicit parameter.

Diagnostic wrappers for TextAPI types for error reporting.

static ChildIteratorType child_end(NodeRef N)

static NodeRef getEntryNode(Inverse<::clang::CFGBlock * > G)

::clang::CFGBlock::const_pred_iterator ChildIteratorType

static ChildIteratorType child_begin(NodeRef N)

static nodes_iterator nodes_end(::clang::CFG *F)

static NodeRef getEntryNode(::clang::CFG *F)

static nodes_iterator nodes_begin(::clang::CFG *F)

static NodeRef getEntryNode(Inverse< const ::clang::CFGBlock * > G)

static ChildIteratorType child_begin(NodeRef N)

::clang::CFGBlock::const_pred_iterator ChildIteratorType

static ChildIteratorType child_end(NodeRef N)

static NodeRef getEntryNode(const ::clang::CFG *F)

static nodes_iterator nodes_begin(const ::clang::CFG *F)

static nodes_iterator nodes_end(const ::clang::CFG *F)

static ChildIteratorType child_begin(NodeRef N)

static ChildIteratorType child_end(NodeRef N)

static NodeRef getEntryNode(::clang::CFGBlock *BB)

::clang::CFGBlock::succ_iterator ChildIteratorType

static nodes_iterator nodes_end(::clang::CFG *F)

static NodeRef getEntryNode(::clang::CFG *F)

static unsigned size(::clang::CFG *F)

static nodes_iterator nodes_begin(::clang::CFG *F)

::clang::CFGBlock::const_succ_iterator ChildIteratorType

static NodeRef getEntryNode(const clang::CFGBlock *BB)

static ChildIteratorType child_begin(NodeRef N)

static ChildIteratorType child_end(NodeRef N)

static nodes_iterator nodes_begin(const ::clang::CFG *F)

static unsigned size(const ::clang::CFG *F)

static nodes_iterator nodes_end(const ::clang::CFG *F)

static NodeRef getEntryNode(const ::clang::CFG *F)

static SimpleType getSimplifiedValue(::clang::CFGTerminator Val)