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
191
192
193
194 return ->isGLValue() &&
195 E->getType().getCanonicalType()->getAsCXXRecordDecl();
196 }
197
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) {
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) {
361 }
362};
363
364
365
367protected:
369
373 }
374
375public:
378
379private:
381
382 static bool isKind(const CFGElement &E) {
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)