clang 24.0.0git
CFG.h
Go to the documentation of this file.
1//===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the CFG and CFGBuilder classes for representing and
10// building Control-Flow Graphs (CFGs) from ASTs.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_ANALYSIS_CFG_H
15#define LLVM_CLANG_ANALYSIS_CFG_H
16
17#include "clang/AST/Attr.h"
18#include "clang/AST/ExprCXX.h"
19#include "clang/AST/ExprObjC.h"
22#include "clang/Basic/LLVM.h"
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 <bitset>
30#include <cassert>
31#include <cstddef>
32#include <iterator>
33#include <memory>
34#include <optional>
35#include <vector>
36
37namespace clang {
38
39class ASTContext;
40class BinaryOperator;
41class CFG;
45class CXXDeleteExpr;
47class CXXNewExpr;
48class CXXRecordDecl;
49class Decl;
50class FieldDecl;
51class LangOptions;
52class VarDecl;
53
54/// Represents a top-level expression in a basic block.
56public:
85
86protected:
87 // The int bits are used to mark the kind.
88 llvm::PointerIntPair<const void *, 2> Data1;
89 llvm::PointerIntPair<const void *, 2> Data2;
90
91 CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr)
92 : Data1(Ptr1, ((unsigned)kind) & 0x3),
93 Data2(Ptr2, (((unsigned)kind) >> 2) & 0x3) {
94 assert(getKind() == kind);
95 }
96
97 CFGElement() = default;
98
99public:
100 /// Convert to the specified CFGElement type, asserting that this
101 /// CFGElement is of the desired type.
102 template<typename T>
103 T castAs() const {
104 assert(T::isKind(*this));
105 T t;
106 CFGElement& e = t;
107 e = *this;
108 return t;
109 }
110
111 /// Convert to the specified CFGElement type, returning std::nullopt if this
112 /// CFGElement is not of the desired type.
113 template <typename T> std::optional<T> getAs() const {
114 if (!T::isKind(*this))
115 return std::nullopt;
116 T t;
117 CFGElement& e = t;
118 e = *this;
119 return t;
120 }
121
122 Kind getKind() const {
123 unsigned x = Data2.getInt();
124 x <<= 2;
125 x |= Data1.getInt();
126 return (Kind) x;
127 }
128
129 void dumpToStream(llvm::raw_ostream &OS,
130 bool TerminateWithNewLine = true) const;
131
132 void dump() const {
133 dumpToStream(llvm::errs());
134 }
135};
136
137class CFGStmt : public CFGElement {
138public:
139 explicit CFGStmt(const Stmt *S, Kind K = Statement) : CFGElement(K, S) {
140 assert(isKind(*this));
141 }
142
143 const Stmt *getStmt() const {
144 return static_cast<const Stmt *>(Data1.getPointer());
145 }
146
147private:
148 friend class CFGElement;
149
150 static bool isKind(const CFGElement &E) {
151 return E.getKind() >= STMT_BEGIN && E.getKind() <= STMT_END;
152 }
153
154protected:
155 CFGStmt() = default;
156};
157
158/// Represents C++ constructor call. Maintains information necessary to figure
159/// out what memory is being initialized by the constructor expression. For now
160/// this is only used by the analyzer's CFG.
161class CFGConstructor : public CFGStmt {
162public:
164 const ConstructionContext *C)
165 : CFGStmt(CE, Constructor) {
166 assert(C);
167 Data2.setPointer(C);
168 }
169
171 return static_cast<const ConstructionContext *>(Data2.getPointer());
172 }
173
174private:
175 friend class CFGElement;
176
177 CFGConstructor() = default;
178
179 static bool isKind(const CFGElement &E) {
180 return E.getKind() == Constructor;
181 }
182};
183
184/// Represents a function call that returns a C++ object by value. This, like
185/// constructor, requires a construction context in order to understand the
186/// storage of the returned object . In C such tracking is not necessary because
187/// no additional effort is required for destroying the object or modeling copy
188/// elision. Like CFGConstructor, this element is for now only used by the
189/// analyzer's CFG.
191public:
192 /// Returns true when call expression \p CE needs to be represented
193 /// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
194 static bool isCXXRecordTypedCall(const Expr *E) {
195 assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E));
196 // There is no such thing as reference-type expression. If the function
197 // returns a reference, it'll return the respective lvalue or xvalue
198 // instead, and we're only interested in objects.
199 return !E->isGLValue() &&
201 }
202
205 assert(isCXXRecordTypedCall(E));
207 // These are possible in C++17 due to mandatory copy elision.
213 Data2.setPointer(C);
214 }
215
217 return static_cast<const ConstructionContext *>(Data2.getPointer());
218 }
219
220private:
221 friend class CFGElement;
222
223 CFGCXXRecordTypedCall() = default;
224
225 static bool isKind(const CFGElement &E) {
226 return E.getKind() == CXXRecordTypedCall;
227 }
228};
229
230/// Represents C++ base or member initializer from constructor's initialization
231/// list.
233public:
234 explicit CFGInitializer(const CXXCtorInitializer *initializer)
235 : CFGElement(Initializer, initializer) {}
236
238 return static_cast<const CXXCtorInitializer *>(Data1.getPointer());
239 }
240
241private:
242 friend class CFGElement;
243
244 CFGInitializer() = default;
245
246 static bool isKind(const CFGElement &E) {
247 return E.getKind() == Initializer;
248 }
249};
250
251/// Represents C++ allocator call.
253public:
254 explicit CFGNewAllocator(const CXXNewExpr *S)
255 : CFGElement(NewAllocator, S) {}
256
257 // Get the new expression.
259 return static_cast<const CXXNewExpr *>(Data1.getPointer());
260 }
261
262private:
263 friend class CFGElement;
264
265 CFGNewAllocator() = default;
266
267 static bool isKind(const CFGElement &elem) {
268 return elem.getKind() == NewAllocator;
269 }
270};
271
272/// Represents the point where a loop ends.
273/// This element is only produced when building the CFG for the static
274/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag.
275///
276/// Note: a loop exit element can be reached even when the loop body was never
277/// entered.
278class CFGLoopExit : public CFGElement {
279public:
280 explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {}
281
282 const Stmt *getLoopStmt() const {
283 return static_cast<const Stmt *>(Data1.getPointer());
284 }
285
286private:
287 friend class CFGElement;
288
289 CFGLoopExit() = default;
290
291 static bool isKind(const CFGElement &elem) {
292 return elem.getKind() == LoopExit;
293 }
294};
295
296/// Base class for representing elements related to the lifetime of automatic
297/// objects.
299public:
300 LLVM_ATTRIBUTE_RETURNS_NONNULL const Stmt *getTriggerStmt() const {
301 return static_cast<const Stmt *>(Data1.getPointer());
302 }
303
304private:
305 friend class CFGElement;
306
307 static bool isKind(const CFGElement &E) {
308 return E.getKind() >= SCOPE_BEGIN && E.getKind() <= SCOPE_END;
309 }
310
311protected:
312 CFGScopeMarker() = default;
313
314 explicit CFGScopeMarker(Kind K, const Stmt *S, const void *Ptr2 = nullptr)
315 : CFGElement(K, S, Ptr2) {
316 assert(isKind(*this));
317 }
318};
319
320/// Represents the point where the lifetime of an automatic object ends
322public:
323 explicit CFGLifetimeEnds(const VarDecl *Var, const Stmt *Stmt)
325
326 const VarDecl *getVarDecl() const {
327 return static_cast<const VarDecl *>(Data2.getPointer());
328 }
329
330private:
331 friend class CFGElement;
332
333 CFGLifetimeEnds() = default;
334
335 static bool isKind(const CFGElement &elem) {
336 return elem.getKind() == LifetimeEnds;
337 }
338};
339
341
342public:
344 explicit CFGFullExprCleanup(const MTEVecTy *MTEs,
345 const ExprWithCleanups *CleanupExpr)
346 : CFGElement(FullExprCleanup, MTEs, CleanupExpr) {}
347
349 return static_cast<const ExprWithCleanups *>(Data2.getPointer());
350 }
351
353
355 const MTEVecTy *ExpiringMTEs =
356 static_cast<const MTEVecTy *>(Data1.getPointer());
357 if (!ExpiringMTEs)
358 return {};
360 ExpiringMTEs->end());
361 }
362
363private:
364 friend class CFGElement;
365
366 CFGFullExprCleanup() = default;
367
368 static bool isKind(const CFGElement &elem) {
369 return elem.getKind() == FullExprCleanup;
370 }
371};
372
373/// Represents beginning of a scope implicitly generated
374/// by the compiler on encountering a CompoundStmt
376public:
378 CFGScopeBegin(const VarDecl *VD, const Stmt *S)
379 : CFGScopeMarker(ScopeBegin, S, VD) {}
380
381 // Get VD that triggered a new scope.
382 const VarDecl *getVarDecl() const {
383 return static_cast<const VarDecl *>(Data2.getPointer());
384 }
385
386private:
387 friend class CFGElement;
388 static bool isKind(const CFGElement &Elem) {
389 return Elem.getKind() == ScopeBegin;
390 }
391};
392
393/// Represents end of a scope implicitly generated by
394/// the compiler after the last Stmt in a CompoundStmt's body
396public:
398 CFGScopeEnd(const VarDecl *VD, const Stmt *S)
399 : CFGScopeMarker(ScopeEnd, S, VD) {}
400
401 const VarDecl *getVarDecl() const {
402 return static_cast<const VarDecl *>(Data2.getPointer());
403 }
404
405private:
406 friend class CFGElement;
407 static bool isKind(const CFGElement &elem) {
408 return elem.getKind() == ScopeEnd;
409 }
410};
411
412/// Represents C++ object destructor implicitly generated by compiler on various
413/// occasions.
415protected:
416 CFGImplicitDtor() = default;
417
418 CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr)
419 : CFGElement(kind, data1, data2) {
420 assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
421 }
422
423public:
424 const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const;
425 bool isNoReturn(ASTContext &astContext) const;
426
427private:
428 friend class CFGElement;
429
430 static bool isKind(const CFGElement &E) {
431 Kind kind = E.getKind();
432 return kind >= DTOR_BEGIN && kind <= DTOR_END;
433 }
434};
435
436class CFGCleanupFunction final : public CFGElement {
437public:
441 assert(VD->hasAttr<CleanupAttr>());
442 }
443
444 const VarDecl *getVarDecl() const {
445 return static_cast<const VarDecl *>(Data1.getPointer());
446 }
447
448 /// Returns the function to be called when cleaning up the var decl.
450 const CleanupAttr *A = getVarDecl()->getAttr<CleanupAttr>();
451 return A->getFunctionDecl();
452 }
453
454private:
455 friend class CFGElement;
456
457 static bool isKind(const CFGElement E) {
458 return E.getKind() == Kind::CleanupFunction;
459 }
460};
461
462/// Represents C++ object destructor implicitly generated for automatic object
463/// or temporary bound to const reference at the point of leaving its local
464/// scope.
466public:
469
470 const VarDecl *getVarDecl() const {
471 return static_cast<const VarDecl *>(Data1.getPointer());
472 }
473
474 // Get statement end of which triggered the destructor call.
475 const Stmt *getTriggerStmt() const {
476 return static_cast<const Stmt *>(Data2.getPointer());
477 }
478
479private:
480 friend class CFGElement;
481
482 CFGAutomaticObjDtor() = default;
483
484 static bool isKind(const CFGElement &elem) {
485 return elem.getKind() == AutomaticObjectDtor;
486 }
487};
488
489/// Represents C++ object destructor generated from a call to delete.
491public:
493 : CFGImplicitDtor(DeleteDtor, RD, DE) {}
494
496 return static_cast<const CXXRecordDecl *>(Data1.getPointer());
497 }
498
499 // Get Delete expression which triggered the destructor call.
501 return static_cast<const CXXDeleteExpr *>(Data2.getPointer());
502 }
503
504private:
505 friend class CFGElement;
506
507 CFGDeleteDtor() = default;
508
509 static bool isKind(const CFGElement &elem) {
510 return elem.getKind() == DeleteDtor;
511 }
512};
513
514/// Represents C++ object destructor implicitly generated for base object in
515/// destructor.
517public:
520
522 return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
523 }
524
525private:
526 friend class CFGElement;
527
528 CFGBaseDtor() = default;
529
530 static bool isKind(const CFGElement &E) {
531 return E.getKind() == BaseDtor;
532 }
533};
534
535/// Represents C++ object destructor implicitly generated for member object in
536/// destructor.
538public:
541
542 const FieldDecl *getFieldDecl() const {
543 return static_cast<const FieldDecl*>(Data1.getPointer());
544 }
545
546private:
547 friend class CFGElement;
548
549 CFGMemberDtor() = default;
550
551 static bool isKind(const CFGElement &E) {
552 return E.getKind() == MemberDtor;
553 }
554};
555
556/// Represents C++ object destructor implicitly generated at the end of full
557/// expression for temporary object.
559public:
562
564 return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
565 }
566
567private:
568 friend class CFGElement;
569
570 CFGTemporaryDtor() = default;
571
572 static bool isKind(const CFGElement &E) {
573 return E.getKind() == TemporaryDtor;
574 }
575};
576
577/// Represents CFGBlock terminator statement.
578///
580public:
581 enum Kind {
582 /// A branch that corresponds to a statement in the code,
583 /// such as an if-statement.
585 /// A branch in control flow of destructors of temporaries. In this case
586 /// terminator statement is the same statement that branches control flow
587 /// in evaluation of matching full expression.
589 /// A shortcut around virtual base initializers. It gets taken when
590 /// virtual base classes have already been initialized by the constructor
591 /// of the most derived class while we're in the base class.
593
594 /// Number of different kinds, for assertions. We subtract 1 so that
595 /// to keep receiving compiler warnings when we don't cover all enum values
596 /// in a switch.
598 };
599
600private:
601 static constexpr int KindBits = 2;
602 static_assert((1 << KindBits) > NumKindsMinusOne,
603 "Not enough room for kind!");
604 llvm::PointerIntPair<Stmt *, KindBits> Data;
605
606public:
607 CFGTerminator() { assert(!isValid()); }
608 CFGTerminator(Stmt *S, Kind K = StmtBranch) : Data(S, K) {}
609
610 bool isValid() const { return Data.getOpaqueValue() != nullptr; }
611 Stmt *getStmt() { return Data.getPointer(); }
612 const Stmt *getStmt() const { return Data.getPointer(); }
613 Kind getKind() const { return static_cast<Kind>(Data.getInt()); }
614
615 bool isStmtBranch() const {
616 return getKind() == StmtBranch;
617 }
619 return getKind() == TemporaryDtorsBranch;
620 }
621 bool isVirtualBaseBranch() const {
622 return getKind() == VirtualBaseBranch;
623 }
624};
625
626/// Represents a single basic block in a source-level CFG.
627/// It consists of:
628///
629/// (1) A set of statements/expressions (which may contain subexpressions).
630/// (2) A "terminator" statement (not in the set of statements).
631/// (3) A list of successors and predecessors.
632///
633/// Terminator: The terminator represents the type of control-flow that occurs
634/// at the end of the basic block. The terminator is a Stmt* referring to an
635/// AST node that has control-flow: if-statements, breaks, loops, etc.
636/// If the control-flow is conditional, the condition expression will appear
637/// within the set of statements in the block (usually the last statement).
638///
639/// Predecessors: the order in the set of predecessors is arbitrary.
640///
641/// Successors: the order in the set of successors is NOT arbitrary. We
642/// currently have the following orderings based on the terminator:
643///
644/// Terminator | Successor Ordering
645/// ------------------|------------------------------------
646/// if | Then Block; Else Block
647/// ? operator | LHS expression; RHS expression
648/// logical and/or | expression that consumes the op, RHS
649/// vbase inits | already handled by the most derived class; not yet
650///
651/// But note that any of that may be NULL in case of optimized-out edges.
652class CFGBlock {
653 class ElementList {
654 using ImplTy = BumpVector<CFGElement>;
655
656 ImplTy Impl;
657
658 public:
659 ElementList(BumpVectorContext &C) : Impl(C, 4) {}
660
661 using iterator = std::reverse_iterator<ImplTy::iterator>;
662 using const_iterator = std::reverse_iterator<ImplTy::const_iterator>;
665 using const_reference = ImplTy::const_reference;
666
667 void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
668
669 reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
671 return Impl.insert(I, Cnt, E, C);
672 }
673
674 const_reference front() const { return Impl.back(); }
675 const_reference back() const { return Impl.front(); }
676
677 iterator begin() { return Impl.rbegin(); }
678 iterator end() { return Impl.rend(); }
679 const_iterator begin() const { return Impl.rbegin(); }
680 const_iterator end() const { return Impl.rend(); }
681 reverse_iterator rbegin() { return Impl.begin(); }
682 reverse_iterator rend() { return Impl.end(); }
683 const_reverse_iterator rbegin() const { return Impl.begin(); }
684 const_reverse_iterator rend() const { return Impl.end(); }
685
686 CFGElement operator[](size_t i) const {
687 assert(i < Impl.size());
688 return Impl[Impl.size() - 1 - i];
689 }
690
691 size_t size() const { return Impl.size(); }
692 bool empty() const { return Impl.empty(); }
693 };
694
695 /// A convenience class for comparing CFGElements, since methods of CFGBlock
696 /// like operator[] return CFGElements by value. This is practically a wrapper
697 /// around a (CFGBlock, Index) pair.
698 template <bool IsConst> class ElementRefImpl {
699
700 template <bool IsOtherConst> friend class ElementRefImpl;
701
702 using CFGBlockPtr =
703 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;
704
705 using CFGElementPtr =
706 std::conditional_t<IsConst, const CFGElement *, CFGElement *>;
707
708 protected:
709 CFGBlockPtr Parent;
710 size_t Index;
711
712 public:
713 ElementRefImpl(CFGBlockPtr Parent, size_t Index)
714 : Parent(Parent), Index(Index) {}
715
716 template <bool IsOtherConst>
717 ElementRefImpl(ElementRefImpl<IsOtherConst> Other)
718 : ElementRefImpl(Other.Parent, Other.Index) {}
719
720 size_t getIndexInBlock() const { return Index; }
721
722 CFGBlockPtr getParent() { return Parent; }
723 CFGBlockPtr getParent() const { return Parent; }
724
725 bool operator<(ElementRefImpl Other) const {
726 return std::make_pair(Parent, Index) <
727 std::make_pair(Other.Parent, Other.Index);
728 }
729
730 bool operator==(ElementRefImpl Other) const {
731 return Parent == Other.Parent && Index == Other.Index;
732 }
733
734 bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
735 CFGElement operator*() const { return (*Parent)[Index]; }
736 CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
737
738 void dumpToStream(llvm::raw_ostream &OS) const {
739 OS << getIndexInBlock() + 1 << ": ";
740 (*this)->dumpToStream(OS);
741 }
742
743 void dump() const {
744 dumpToStream(llvm::errs());
745 }
746
747 void Profile(llvm::FoldingSetNodeID &ID) const {
748 ID.AddPointer(Parent);
749 ID.AddInteger(Index);
750 }
751 };
752
753 template <bool IsReverse, bool IsConst> class ElementRefIterator {
754
755 template <bool IsOtherReverse, bool IsOtherConst>
756 friend class ElementRefIterator;
757
758 using CFGBlockRef =
759 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;
760
761 using UnderlayingIteratorTy = std::conditional_t<
762 IsConst,
763 std::conditional_t<IsReverse, ElementList::const_reverse_iterator,
764 ElementList::const_iterator>,
765 std::conditional_t<IsReverse, ElementList::reverse_iterator,
766 ElementList::iterator>>;
767
768 using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
769 using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;
770
771 public:
772 using difference_type = typename IteratorTraits::difference_type;
773 using value_type = ElementRef;
774 using pointer = ElementRef *;
775 using iterator_category = typename IteratorTraits::iterator_category;
776
777 private:
778 CFGBlockRef Parent;
779 UnderlayingIteratorTy Pos;
780
781 public:
782 ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos)
783 : Parent(Parent), Pos(Pos) {}
784
785 template <bool IsOtherConst>
786 ElementRefIterator(ElementRefIterator<false, IsOtherConst> E)
787 : ElementRefIterator(E.Parent, E.Pos.base()) {}
788
789 template <bool IsOtherConst>
790 ElementRefIterator(ElementRefIterator<true, IsOtherConst> E)
791 : ElementRefIterator(E.Parent, std::make_reverse_iterator(E.Pos)) {}
792
793 bool operator<(ElementRefIterator Other) const {
794 assert(Parent == Other.Parent);
795 return Pos < Other.Pos;
796 }
797
798 bool operator==(ElementRefIterator Other) const {
799 return Parent == Other.Parent && Pos == Other.Pos;
800 }
801
802 bool operator!=(ElementRefIterator Other) const {
803 return !(*this == Other);
804 }
805
806 private:
807 template <bool IsOtherConst>
808 static size_t
809 getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) {
810 return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1;
811 }
812
813 template <bool IsOtherConst>
814 static size_t
815 getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) {
816 return E.Pos - E.Parent->begin();
817 }
818
819 public:
820 value_type operator*() { return {Parent, getIndexInBlock(*this)}; }
821
822 difference_type operator-(ElementRefIterator Other) const {
823 return Pos - Other.Pos;
824 }
825
826 ElementRefIterator operator++() {
827 ++this->Pos;
828 return *this;
829 }
830 ElementRefIterator operator++(int) {
831 ElementRefIterator Ret = *this;
832 ++*this;
833 return Ret;
834 }
835 ElementRefIterator operator+(size_t count) {
836 this->Pos += count;
837 return *this;
838 }
839 ElementRefIterator operator-(size_t count) {
840 this->Pos -= count;
841 return *this;
842 }
843 };
844
845public:
846 /// The set of statements in the basic block.
847 ElementList Elements;
848
849 /// An (optional) label that prefixes the executable statements in the block.
850 /// When this variable is non-NULL, it is either an instance of LabelStmt,
851 /// SwitchCase or CXXCatchStmt.
852 Stmt *Label = nullptr;
853
854 /// The terminator for a basic block that indicates the type of control-flow
855 /// that occurs between a block and its successors.
857
858 /// Some blocks are used to represent the "loop edge" to the start of a loop
859 /// from within the loop body. This Stmt* will be refer to the loop statement
860 /// for such blocks (and be null otherwise).
861 const Stmt *LoopTarget = nullptr;
862
863 /// A numerical ID assigned to a CFGBlock during construction of the CFG.
864 unsigned BlockID;
865
866public:
867 /// This class represents a potential adjacent block in the CFG. It encodes
868 /// whether or not the block is actually reachable, or can be proved to be
869 /// trivially unreachable. For some cases it allows one to encode scenarios
870 /// where a block was substituted because the original (now alternate) block
871 /// is unreachable.
873 enum Kind {
874 AB_Normal,
875 AB_Unreachable,
876 AB_Alternate
877 };
878
879 CFGBlock *ReachableBlock;
880 llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock;
881
882 public:
883 /// Construct an AdjacentBlock with a possibly unreachable block.
884 AdjacentBlock(CFGBlock *B, bool IsReachable);
885
886 /// Construct an AdjacentBlock with a reachable block and an alternate
887 /// unreachable block.
888 AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
889
890 /// Get the reachable block, if one exists.
892 return ReachableBlock;
893 }
894
895 /// Get the potentially unreachable block.
897 return UnreachableBlock.getPointer();
898 }
899
900 /// Provide an implicit conversion to CFGBlock* so that
901 /// AdjacentBlock can be substituted for CFGBlock*.
902 operator CFGBlock*() const {
903 return getReachableBlock();
904 }
905
907 return *getReachableBlock();
908 }
909
911 return getReachableBlock();
912 }
913
914 bool isReachable() const {
915 Kind K = (Kind) UnreachableBlock.getInt();
916 return K == AB_Normal || K == AB_Alternate;
917 }
918 };
919
920private:
921 /// Keep track of the predecessor / successor CFG blocks.
922 using AdjacentBlocks = BumpVector<AdjacentBlock>;
923 AdjacentBlocks Preds;
924 AdjacentBlocks Succs;
925
926 /// The kind of noreturn element a block contains.
927 enum class NoReturnKind : unsigned {
928 None,
929 /// A function call attributed as 'analyzer_noreturn'.
930 AnalyzerOnly,
931 /// A function call or implicit destructor attributed as 'noreturn'.
932 Real
933 };
934
935 /// This bit is set when the basic block contains a function call
936 /// or implicit destructor that is attributed as 'noreturn' or
937 /// 'analyzer_noreturn'. In that case, control cannot technically ever
938 /// proceed past this block. All such blocks will have a single immediate
939 /// successor: the exit block. This allows them to be easily reached from the
940 /// exit block and using this bit quickly recognized without scanning the
941 /// contents of the block.
942 ///
943 /// Optimization Note: These bits could be profitably folded with Terminator's
944 /// storage if the memory usage of CFGBlock becomes an issue.
945 NoReturnKind NoReturn : 2;
946
947 /// The parent CFG that owns this CFGBlock.
948 CFG *Parent;
949
950public:
951 explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
952 : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1),
953 Succs(C, 1), NoReturn(NoReturnKind::None), Parent(parent) {}
954
955 // Statement iterators
956 using iterator = ElementList::iterator;
957 using const_iterator = ElementList::const_iterator;
958 using reverse_iterator = ElementList::reverse_iterator;
959 using const_reverse_iterator = ElementList::const_reverse_iterator;
960
961 size_t getIndexInCFG() const;
962
963 CFGElement front() const { return Elements.front(); }
964 CFGElement back() const { return Elements.back(); }
965
966 iterator begin() { return Elements.begin(); }
967 iterator end() { return Elements.end(); }
968 const_iterator begin() const { return Elements.begin(); }
969 const_iterator end() const { return Elements.end(); }
970
971 reverse_iterator rbegin() { return Elements.rbegin(); }
972 reverse_iterator rend() { return Elements.rend(); }
973 const_reverse_iterator rbegin() const { return Elements.rbegin(); }
974 const_reverse_iterator rend() const { return Elements.rend(); }
975
976 using CFGElementRef = ElementRefImpl<false>;
977 using ConstCFGElementRef = ElementRefImpl<true>;
978
979 using ref_iterator = ElementRefIterator<false, false>;
980 using ref_iterator_range = llvm::iterator_range<ref_iterator>;
981 using const_ref_iterator = ElementRefIterator<false, true>;
982 using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>;
983
984 using reverse_ref_iterator = ElementRefIterator<true, false>;
985 using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>;
986
987 using const_reverse_ref_iterator = ElementRefIterator<true, true>;
989 llvm::iterator_range<const_reverse_ref_iterator>;
990
991 ref_iterator ref_begin() { return {this, begin()}; }
992 ref_iterator ref_end() { return {this, end()}; }
993 const_ref_iterator ref_begin() const { return {this, begin()}; }
994 const_ref_iterator ref_end() const { return {this, end()}; }
995
996 reverse_ref_iterator rref_begin() { return {this, rbegin()}; }
997 reverse_ref_iterator rref_end() { return {this, rend()}; }
998 const_reverse_ref_iterator rref_begin() const { return {this, rbegin()}; }
999 const_reverse_ref_iterator rref_end() const { return {this, rend()}; }
1000
1005 return {rref_begin(), rref_end()};
1006 }
1007
1008 unsigned size() const { return Elements.size(); }
1009 bool empty() const { return Elements.empty(); }
1010
1011 CFGElement operator[](size_t i) const { return Elements[i]; }
1012
1013 // CFG iterators
1018 using pred_range = llvm::iterator_range<pred_iterator>;
1019 using pred_const_range = llvm::iterator_range<const_pred_iterator>;
1020
1025 using succ_range = llvm::iterator_range<succ_iterator>;
1026 using succ_const_range = llvm::iterator_range<const_succ_iterator>;
1027
1028 pred_iterator pred_begin() { return Preds.begin(); }
1029 pred_iterator pred_end() { return Preds.end(); }
1030 const_pred_iterator pred_begin() const { return Preds.begin(); }
1031 const_pred_iterator pred_end() const { return Preds.end(); }
1032
1033 pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); }
1034 pred_reverse_iterator pred_rend() { return Preds.rend(); }
1035 const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
1036 const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
1037
1039 return pred_range(pred_begin(), pred_end());
1040 }
1041
1044 }
1045
1046 succ_iterator succ_begin() { return Succs.begin(); }
1047 succ_iterator succ_end() { return Succs.end(); }
1048 const_succ_iterator succ_begin() const { return Succs.begin(); }
1049 const_succ_iterator succ_end() const { return Succs.end(); }
1050
1051 succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); }
1052 succ_reverse_iterator succ_rend() { return Succs.rend(); }
1053 const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
1054 const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
1055
1057 return succ_range(succ_begin(), succ_end());
1058 }
1059
1062 }
1063
1064 unsigned succ_size() const { return Succs.size(); }
1065 bool succ_empty() const { return Succs.empty(); }
1066
1067 unsigned pred_size() const { return Preds.size(); }
1068 bool pred_empty() const { return Preds.empty(); }
1069
1070
1072 public:
1073 LLVM_PREFERRED_TYPE(bool)
1075 LLVM_PREFERRED_TYPE(bool)
1077
1080 };
1081
1082 static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
1083 const CFGBlock *Dst);
1084
1085 template <typename IMPL, bool IsPred>
1087 private:
1088 IMPL I, E;
1089 const FilterOptions F;
1090 const CFGBlock *From;
1091
1092 public:
1093 explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
1094 const CFGBlock *from,
1095 const FilterOptions &f)
1096 : I(i), E(e), F(f), From(from) {
1097 while (hasMore() && Filter(*I))
1098 ++I;
1099 }
1100
1101 bool hasMore() const { return I != E; }
1102
1104 do { ++I; } while (hasMore() && Filter(*I));
1105 return *this;
1106 }
1107
1108 const CFGBlock *operator*() const { return *I; }
1109
1110 private:
1111 bool Filter(const CFGBlock *To) {
1112 return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
1113 }
1114 };
1115
1118
1121
1125
1129
1130 // Manipulation of block contents
1131
1133 void setLabel(Stmt *Statement) { Label = Statement; }
1134 void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
1135 /// Mark the block as ending in a noreturn element.
1136 void setHasNoReturnElement(bool AnalyzerOnly = false) {
1137 assert(NoReturn == NoReturnKind::None &&
1138 "block already has a noreturn element");
1139 NoReturn = AnalyzerOnly ? NoReturnKind::AnalyzerOnly : NoReturnKind::Real;
1140 }
1141
1142 /// Returns true if the block would eventually end with a sink (a noreturn
1143 /// node).
1144 bool isInevitablySinking() const;
1145
1147
1148 Stmt *getTerminatorStmt() { return Terminator.getStmt(); }
1149 const Stmt *getTerminatorStmt() const { return Terminator.getStmt(); }
1150
1151 /// \returns the last (\c rbegin()) condition, e.g. observe the following code
1152 /// snippet:
1153 /// if (A && B && C)
1154 /// A block would be created for \c A, \c B, and \c C. For the latter,
1155 /// \c getTerminatorStmt() would retrieve the entire condition, rather than
1156 /// C itself, while this method would only return C.
1157 const Expr *getLastCondition() const;
1158
1159 const Stmt *getTerminatorCondition(bool StripParens = true) const;
1160
1161 const Stmt *getLoopTarget() const { return LoopTarget; }
1162
1163 Stmt *getLabel() { return Label; }
1164 const Stmt *getLabel() const { return Label; }
1165
1166 /// Returns true if the block has a noreturn element, whether it is a real
1167 /// 'noreturn' or an 'analyzer_noreturn'.
1168 bool hasNoReturnElement() const { return NoReturn != NoReturnKind::None; }
1169
1170 /// Returns true if the block ends in an 'analyzer_noreturn' call (as opposed
1171 /// to a real 'noreturn' one). Most analyses treat the two indistinguishably
1172 /// (see hasNoReturnElement). This is for clients that need to tell them
1173 /// apart (e.g., -Wunreachable-code).
1175 return NoReturn == NoReturnKind::AnalyzerOnly;
1176 }
1177
1178 unsigned getBlockID() const { return BlockID; }
1179
1180 CFG *getParent() const { return Parent; }
1181
1182 void dump() const;
1183
1184 void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
1185 void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
1186 bool ShowColors) const;
1187
1188 void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
1189 void printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
1190 bool AddQuotes) const;
1191
1192 void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
1193 OS << "BB#" << getBlockID();
1194 }
1195
1196 /// Adds a (potentially unreachable) successor block to the current block.
1197 void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C);
1198
1199 void appendStmt(Stmt *statement, BumpVectorContext &C) {
1200 Elements.push_back(CFGStmt(statement), C);
1201 }
1202
1205 Elements.push_back(CFGConstructor(CE, CC), C);
1206 }
1207
1209 const ConstructionContext *CC,
1211 Elements.push_back(CFGCXXRecordTypedCall(E, CC), C);
1212 }
1213
1216 Elements.push_back(CFGInitializer(initializer), C);
1217 }
1218
1221 Elements.push_back(CFGNewAllocator(NE), C);
1222 }
1223
1224 void appendScopeBegin(const VarDecl *VD, const Stmt *S,
1226 Elements.push_back(CFGScopeBegin(VD, S), C);
1227 }
1228
1229 void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) {
1230 Elements.push_back(CFGScopeEnd(VD, S), C);
1231 }
1232
1234 Elements.push_back(CFGBaseDtor(BS), C);
1235 }
1236
1238 Elements.push_back(CFGMemberDtor(FD), C);
1239 }
1240
1244
1246 Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
1247 }
1248
1250 Elements.push_back(CFGCleanupFunction(VD), C);
1251 }
1252
1254 Elements.push_back(CFGLifetimeEnds(VD, S), C);
1255 }
1256
1258 const ExprWithCleanups *CleanupExpr,
1260 Elements.push_back(CFGFullExprCleanup(BV, CleanupExpr), C);
1261 }
1262
1263 void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) {
1264 Elements.push_back(CFGLoopExit(LoopStmt), C);
1265 }
1266
1268 Elements.push_back(CFGDeleteDtor(RD, DE), C);
1269 }
1270};
1271
1273
1274/// CFGCallback defines methods that should be called when a logical
1275/// operator error is found when building the CFG.
1277public:
1278 CFGCallback() = default;
1279 virtual ~CFGCallback() = default;
1280
1281 virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
1282 virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
1284 bool isAlwaysTrue) {}
1285 virtual void compareBitwiseOr(const BinaryOperator *B) {}
1286};
1287
1288/// Represents a source-level, intra-procedural CFG that represents the
1289/// control-flow of a Stmt. The Stmt can represent an entire function body,
1290/// or a single expression. A CFG will always contain one empty block that
1291/// represents the Exit point of the CFG. A CFG will also contain a designated
1292/// Entry block. The CFG solely represents control-flow; it consists of
1293/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
1294/// was constructed from.
1295class CFG {
1296public:
1297 //===--------------------------------------------------------------------===//
1298 // CFG Construction & Manipulation.
1299 //===--------------------------------------------------------------------===//
1300
1302 // Stmt::lastStmtConstant has the same value as the last Stmt kind,
1303 // so make sure we add one to account for this!
1304 std::bitset<Stmt::lastStmtConstant + 1> alwaysAddMask;
1305
1306 public:
1307 using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>;
1308
1312 bool AddEHEdges = false;
1313 bool AddInitializers = false;
1314 bool AddImplicitDtors = false;
1315 bool AddLifetime = false;
1316 // Add lifetime markers for function parameters. In principle, function
1317 // parameters are constructed and destructed in the caller context but
1318 // analyses could still choose to include these in the callee's CFG to
1319 // represent the lifetime ends of parameters on function exit.
1321 bool AddLoopExit = false;
1322 bool AddTemporaryDtors = false;
1323 bool AddScopes = false;
1333
1334 BuildOptions() = default;
1335
1336 bool alwaysAdd(const Stmt *stmt) const {
1337 return alwaysAddMask[stmt->getStmtClass()];
1338 }
1339
1340 BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) {
1341 alwaysAddMask[stmtClass] = val;
1342 return *this;
1343 }
1344
1346 alwaysAddMask.set();
1347 return *this;
1348 }
1349 };
1350
1351 /// Builds a CFG from an AST.
1352 static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
1353 const BuildOptions &BO);
1354
1355 /// Create a new block in the CFG. The CFG owns the block; the caller should
1356 /// not directly free it.
1358
1359 /// Set the entry block of the CFG. This is typically used only during CFG
1360 /// construction. Most CFG clients expect that the entry block has no
1361 /// predecessors and contains no statements.
1362 void setEntry(CFGBlock *B) { Entry = B; }
1363
1364 /// Set the block used for indirect goto jumps. This is typically used only
1365 /// during CFG construction.
1366 void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
1367
1368 //===--------------------------------------------------------------------===//
1369 // Block Iterators
1370 //===--------------------------------------------------------------------===//
1371
1375 using reverse_iterator = std::reverse_iterator<iterator>;
1376 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1377
1378 CFGBlock & front() { return *Blocks.front(); }
1379 CFGBlock & back() { return *Blocks.back(); }
1380
1381 iterator begin() { return Blocks.begin(); }
1382 iterator end() { return Blocks.end(); }
1383 const_iterator begin() const { return Blocks.begin(); }
1384 const_iterator end() const { return Blocks.end(); }
1385
1386 iterator nodes_begin() { return iterator(Blocks.begin()); }
1387 iterator nodes_end() { return iterator(Blocks.end()); }
1388
1389 llvm::iterator_range<iterator> nodes() { return {begin(), end()}; }
1390 llvm::iterator_range<const_iterator> const_nodes() const {
1391 return {begin(), end()};
1392 }
1393
1394 const_iterator nodes_begin() const { return const_iterator(Blocks.begin()); }
1395 const_iterator nodes_end() const { return const_iterator(Blocks.end()); }
1396
1397 reverse_iterator rbegin() { return Blocks.rbegin(); }
1398 reverse_iterator rend() { return Blocks.rend(); }
1399 const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
1400 const_reverse_iterator rend() const { return Blocks.rend(); }
1401
1402 llvm::iterator_range<reverse_iterator> reverse_nodes() {
1403 return {rbegin(), rend()};
1404 }
1405 llvm::iterator_range<const_reverse_iterator> const_reverse_nodes() const {
1406 return {rbegin(), rend()};
1407 }
1408
1409 CFGBlock & getEntry() { return *Entry; }
1410 const CFGBlock & getEntry() const { return *Entry; }
1411 CFGBlock & getExit() { return *Exit; }
1412 const CFGBlock & getExit() const { return *Exit; }
1413
1414 CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; }
1415 const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; }
1416
1417 using try_block_iterator = std::vector<const CFGBlock *>::const_iterator;
1418 using try_block_range = llvm::iterator_range<try_block_iterator>;
1419
1421 return TryDispatchBlocks.begin();
1422 }
1423
1425 return TryDispatchBlocks.end();
1426 }
1427
1431
1432 void addTryDispatchBlock(const CFGBlock *block) {
1433 TryDispatchBlocks.push_back(block);
1434 }
1435
1436 /// Records a synthetic DeclStmt and the DeclStmt it was constructed from.
1437 ///
1438 /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains
1439 /// multiple decls.
1440 void addSyntheticDeclStmt(const DeclStmt *Synthetic,
1441 const DeclStmt *Source) {
1442 assert(Synthetic->isSingleDecl() && "Can handle single declarations only");
1443 assert(Synthetic != Source && "Don't include original DeclStmts in map");
1444 assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map");
1445 SyntheticDeclStmts[Synthetic] = Source;
1446 }
1447
1449 llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator;
1450 using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>;
1451
1452 /// Iterates over synthetic DeclStmts in the CFG.
1453 ///
1454 /// Each element is a (synthetic statement, source statement) pair.
1455 ///
1456 /// \sa addSyntheticDeclStmt
1458 return SyntheticDeclStmts.begin();
1459 }
1460
1461 /// \sa synthetic_stmt_begin
1463 return SyntheticDeclStmts.end();
1464 }
1465
1466 /// \sa synthetic_stmt_begin
1470
1471 //===--------------------------------------------------------------------===//
1472 // Member templates useful for various batch operations over CFGs.
1473 //===--------------------------------------------------------------------===//
1474
1475 template <typename Callback> void VisitBlockStmts(Callback &O) const {
1476 for (CFGBlock *BB : *this)
1477 for (const CFGElement &Elem : *BB) {
1478 if (std::optional<CFGStmt> stmt = Elem.getAs<CFGStmt>())
1479 O(stmt->getStmt());
1480 }
1481 }
1482
1483 //===--------------------------------------------------------------------===//
1484 // CFG Introspection.
1485 //===--------------------------------------------------------------------===//
1486
1487 /// Returns the total number of BlockIDs allocated (which start at 0).
1488 unsigned getNumBlockIDs() const { return NumBlockIDs; }
1489
1490 /// Return the total number of CFGBlocks within the CFG This is simply a
1491 /// renaming of the getNumBlockIDs(). This is necessary because the dominator
1492 /// implementation needs such an interface.
1493 unsigned size() const { return NumBlockIDs; }
1494
1495 /// Returns true if the CFG has no branches. Usually it boils down to the CFG
1496 /// having exactly three blocks (entry, the actual code, exit), but sometimes
1497 /// more blocks appear due to having control flow that can be fully
1498 /// resolved in compile time.
1499 bool isLinear() const;
1500
1501 //===--------------------------------------------------------------------===//
1502 // CFG Debugging: Pretty-Printing and Visualization.
1503 //===--------------------------------------------------------------------===//
1504
1505 void viewCFG(const LangOptions &LO) const;
1506 void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const;
1507 void dump(const LangOptions &LO, bool ShowColors) const;
1508
1509 //===--------------------------------------------------------------------===//
1510 // Internal: constructors and data.
1511 //===--------------------------------------------------------------------===//
1512
1513 CFG() : Blocks(BlkBVC, 10) {}
1514
1515 llvm::BumpPtrAllocator& getAllocator() {
1516 return BlkBVC.getAllocator();
1517 }
1518
1520 return BlkBVC;
1521 }
1522
1523private:
1524 CFGBlock *Entry = nullptr;
1525 CFGBlock *Exit = nullptr;
1526
1527 // Special block to contain collective dispatch for indirect gotos
1528 CFGBlock* IndirectGotoBlock = nullptr;
1529
1530 unsigned NumBlockIDs = 0;
1531
1532 BumpVectorContext BlkBVC;
1533
1534 CFGBlockListTy Blocks;
1535
1536 /// C++ 'try' statements are modeled with an indirect dispatch block.
1537 /// This is the collection of such blocks present in the CFG.
1538 std::vector<const CFGBlock *> TryDispatchBlocks;
1539
1540 /// Collects DeclStmts synthesized for this CFG and maps each one back to its
1541 /// source DeclStmt.
1542 llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
1543};
1544
1545Expr *extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE);
1546
1547//===----------------------------------------------------------------------===//
1548// GraphTraits specializations for CFG basic block graphs (source-level CFGs)
1549//===----------------------------------------------------------------------===//
1550
1551namespace detail {
1552// The GraphTraits below present a CFGBlock's successors and predecessors as
1553// plain CFGBlock *, so generic graph algorithms need not know about
1554// AdjacentBlock. AB_Unreachable edges, whose reachable target is null, are kept
1555// in the CFG to preserve terminator successor positions but are not real
1556// control-flow edges and are skipped here.
1558 bool operator()(const CFGBlock::AdjacentBlock &AB) const {
1559 return AB.getReachableBlock() != nullptr;
1560 }
1561};
1562template <typename BlockT> struct CFGBlockEdgeTarget {
1563 BlockT *operator()(const CFGBlock::AdjacentBlock &AB) const {
1564 return AB.getReachableBlock();
1565 }
1566};
1567
1568// A GraphTraits child iterator over BlockT: each AdjacentBlock edge projected
1569// to its reachable target, with unreachable (null) edges skipped.
1570template <typename IterT, typename BlockT>
1572 llvm::mapped_iterator<llvm::filter_iterator<IterT, CFGBlockReachableEdge>,
1574
1575template <typename BlockT, typename RangeT>
1576auto cfgReachableChildren(RangeT Edges) {
1577 return llvm::map_range(
1578 llvm::make_filter_range(Edges, CFGBlockReachableEdge()),
1580}
1581} // namespace detail
1582} // namespace clang
1583
1584namespace llvm {
1585
1586/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
1587/// CFGTerminator to a specific Stmt class.
1588template <> struct simplify_type< ::clang::CFGTerminator> {
1590
1592 return Val.getStmt();
1593 }
1594};
1595
1596// Traits for: CFGBlock
1597
1598// CFGBlocks are numbered densely from 0 by their BlockID, so dominator tree
1599// construction can index by number instead of using a DenseMap.
1600template <> struct GraphTraits<clang::CFGBlock *> {
1605
1606 static NodeRef getEntryNode(clang::CFGBlock *BB) { return BB; }
1615
1616 static unsigned getNumber(const clang::CFGBlock *BB) {
1617 return BB->getBlockID();
1618 }
1619};
1620
1621static_assert(GraphHasNodeNumbers<clang::CFGBlock *>,
1622 "GraphTraits getNumber() not detected");
1623
1624template <> struct GraphTraits<const clang::CFGBlock *> {
1625 using NodeRef = const clang::CFGBlock *;
1628
1629 static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; }
1640
1641 static unsigned getNumber(const clang::CFGBlock *BB) {
1642 return BB->getBlockID();
1643 }
1644};
1645
1646static_assert(GraphHasNodeNumbers<const clang::CFGBlock *>,
1647 "GraphTraits getNumber() not detected");
1648
1649template <> struct GraphTraits<Inverse<clang::CFGBlock *>> {
1654
1655 static NodeRef getEntryNode(Inverse<clang::CFGBlock *> G) { return G.Graph; }
1664
1665 static unsigned getNumber(const clang::CFGBlock *BB) {
1666 return BB->getBlockID();
1667 }
1668};
1669
1670static_assert(GraphHasNodeNumbers<Inverse<clang::CFGBlock *>>,
1671 "GraphTraits getNumber() not detected");
1672
1673template <> struct GraphTraits<Inverse<const clang::CFGBlock *>> {
1674 using NodeRef = const clang::CFGBlock *;
1677
1678 static NodeRef getEntryNode(Inverse<const clang::CFGBlock *> G) {
1679 return G.Graph;
1680 }
1691
1692 static unsigned getNumber(const clang::CFGBlock *BB) {
1693 return BB->getBlockID();
1694 }
1695};
1696
1697static_assert(GraphHasNodeNumbers<Inverse<const clang::CFGBlock *>>,
1698 "GraphTraits getNumber() not detected");
1699
1700// Traits for: CFG
1701
1702template <>
1703struct GraphTraits<::clang::CFG *> : public GraphTraits<clang::CFGBlock *> {
1705
1706 static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); }
1709 static unsigned size(::clang::CFG* F) { return F->size(); }
1710
1711 static unsigned getMaxNumber(const ::clang::CFG *F) {
1712 return F->getNumBlockIDs();
1713 }
1714 // Block numbers are fixed when the CFG is built and never change afterwards.
1715 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1716};
1717
1718template <>
1719struct GraphTraits<const ::clang::CFG *>
1720 : public GraphTraits<const clang::CFGBlock *> {
1722
1723 static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); }
1724
1725 static nodes_iterator nodes_begin( const ::clang::CFG* F) {
1726 return F->nodes_begin();
1727 }
1728
1729 static nodes_iterator nodes_end( const ::clang::CFG* F) {
1730 return F->nodes_end();
1731 }
1732
1733 static unsigned size(const ::clang::CFG* F) {
1734 return F->size();
1735 }
1736
1737 static unsigned getMaxNumber(const ::clang::CFG *F) {
1738 return F->getNumBlockIDs();
1739 }
1740 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1741};
1742
1743template <>
1744struct GraphTraits<Inverse<::clang::CFG *>>
1745 : public GraphTraits<Inverse<clang::CFGBlock *>> {
1747
1748 static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); }
1750 static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
1751
1752 static unsigned getMaxNumber(const ::clang::CFG *F) {
1753 return F->getNumBlockIDs();
1754 }
1755 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1756};
1757
1758template <>
1759struct GraphTraits<Inverse<const ::clang::CFG *>>
1760 : public GraphTraits<Inverse<const clang::CFGBlock *>> {
1762
1763 static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); }
1764
1765 static nodes_iterator nodes_begin(const ::clang::CFG* F) {
1766 return F->nodes_begin();
1767 }
1768
1769 static nodes_iterator nodes_end(const ::clang::CFG* F) {
1770 return F->nodes_end();
1771 }
1772
1773 static unsigned getMaxNumber(const ::clang::CFG *F) {
1774 return F->getNumBlockIDs();
1775 }
1776 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1777};
1778
1779} // namespace llvm
1780
1781#endif // LLVM_CLANG_ANALYSIS_CFG_H
#define IMPL(Index)
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, clang::CharUnits CU)
Definition CharUnits.h:194
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4086
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition BumpVector.h:92
const CFGElement & const_reference
Definition BumpVector.h:96
std::reverse_iterator< iterator > reverse_iterator
Definition BumpVector.h:93
const CFGElement * const_iterator
Definition BumpVector.h:90
iterator begin()
Definition BumpVector.h:101
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Definition CFG.h:465
const VarDecl * getVarDecl() const
Definition CFG.h:470
const Stmt * getTriggerStmt() const
Definition CFG.h:475
friend class CFGElement
Definition CFG.h:480
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
Definition CFG.h:467
Represents C++ object destructor implicitly generated for base object in destructor.
Definition CFG.h:516
friend class CFGElement
Definition CFG.h:526
CFGBaseDtor(const CXXBaseSpecifier *base)
Definition CFG.h:518
const CXXBaseSpecifier * getBaseSpecifier() const
Definition CFG.h:521
This class represents a potential adjacent block in the CFG.
Definition CFG.h:872
CFGBlock & operator*() const
Definition CFG.h:906
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Definition CFG.cpp:5600
CFGBlock * operator->() const
Definition CFG.h:910
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
Definition CFG.h:891
bool isReachable() const
Definition CFG.h:914
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
Definition CFG.h:896
unsigned IgnoreDefaultsWithCoveredEnums
Definition CFG.h:1076
FilteredCFGBlockIterator & operator++()
Definition CFG.h:1103
const CFGBlock * operator*() const
Definition CFG.h:1108
FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, const FilterOptions &f)
Definition CFG.h:1093
Represents a single basic block in a source-level CFG.
Definition CFG.h:652
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
Definition CFG.h:1245
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
Definition CFG.cpp:6424
ElementList::reverse_iterator reverse_iterator
Definition CFG.h:958
ElementList::iterator iterator
Definition CFG.h:956
void setLoopTarget(const Stmt *loopTarget)
Definition CFG.h:1134
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
Definition CFG.cpp:6468
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const
Definition CFG.h:1122
pred_iterator pred_end()
Definition CFG.h:1029
size_t getIndexInCFG() const
Definition CFG.cpp:6400
succ_iterator succ_end()
Definition CFG.h:1047
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
Definition CFG.h:1224
AdjacentBlocks::reverse_iterator pred_reverse_iterator
Definition CFG.h:1016
const_reverse_iterator rend() const
Definition CFG.h:974
CFGElement operator[](size_t i) const
Definition CFG.h:1011
llvm::iterator_range< pred_iterator > pred_range
Definition CFG.h:1018
const_reverse_ref_iterator_range rrefs() const
Definition CFG.h:1004
llvm::iterator_range< const_succ_iterator > succ_const_range
Definition CFG.h:1026
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Definition CFG.cpp:5621
ElementRefIterator< false, false > ref_iterator
Definition CFG.h:979
ref_iterator ref_begin()
Definition CFG.h:991
reverse_iterator rbegin()
Definition CFG.h:971
bool hasOnlyAnalyzerNoReturnElement() const
Returns true if the block ends in an 'analyzer_noreturn' call (as opposed to a real 'noreturn' one).
Definition CFG.h:1174
void setTerminator(CFGTerminator Term)
Definition CFG.h:1132
void printAsOperand(raw_ostream &OS, bool)
Definition CFG.h:1192
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
Definition CFG.h:1237
filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const
Definition CFG.h:1126
llvm::iterator_range< reverse_ref_iterator > reverse_ref_iterator_range
Definition CFG.h:985
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)
Definition CFG.h:1253
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:6416
ElementList::const_iterator const_iterator
Definition CFG.h:957
const Stmt * getLabel() const
Definition CFG.h:1164
reverse_iterator rend()
Definition CFG.h:972
AdjacentBlocks::iterator pred_iterator
Definition CFG.h:1014
pred_reverse_iterator pred_rend()
Definition CFG.h:1034
bool hasNoReturnElement() const
Returns true if the block has a noreturn element, whether it is a real 'noreturn' or an 'analyzer_nor...
Definition CFG.h:1168
CFGElement back() const
Definition CFG.h:964
ElementList::const_reverse_iterator const_reverse_iterator
Definition CFG.h:959
succ_reverse_iterator succ_rend()
Definition CFG.h:1052
ElementRefIterator< true, false > reverse_ref_iterator
Definition CFG.h:984
CFGElement front() const
Definition CFG.h:963
const_reverse_ref_iterator rref_end() const
Definition CFG.h:999
unsigned size() const
Definition CFG.h:1008
const_succ_iterator succ_begin() const
Definition CFG.h:1048
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
Definition CFG.h:1267
void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
Definition CFG.h:1229
const_pred_iterator pred_end() const
Definition CFG.h:1031
const_iterator begin() const
Definition CFG.h:968
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
Definition CFG.h:1214
unsigned BlockID
A numerical ID assigned to a CFGBlock during construction of the CFG.
Definition CFG.h:864
iterator begin()
Definition CFG.h:966
FilteredCFGBlockIterator< const_pred_iterator, true > filtered_pred_iterator
Definition CFG.h:1116
const_pred_reverse_iterator pred_rbegin() const
Definition CFG.h:1035
succ_reverse_iterator succ_rbegin()
Definition CFG.h:1051
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const
printTerminatorJson - Pretty-prints the terminator in JSON format.
Definition CFG.cpp:6431
llvm::iterator_range< ref_iterator > ref_iterator_range
Definition CFG.h:980
succ_range succs()
Definition CFG.h:1056
void dump() const
Definition CFG.cpp:6410
bool empty() const
Definition CFG.h:1009
AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator
Definition CFG.h:1024
ref_iterator_range refs()
Definition CFG.h:1001
ElementRefIterator< false, true > const_ref_iterator
Definition CFG.h:981
ElementRefImpl< true > ConstCFGElementRef
Definition CFG.h:977
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
Definition CFG.h:1219
CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
Definition CFG.h:951
Stmt * Label
An (optional) label that prefixes the executable statements in the block.
Definition CFG.h:852
const_ref_iterator ref_begin() const
Definition CFG.h:993
Stmt * getLabel()
Definition CFG.h:1163
CFGTerminator getTerminator() const
Definition CFG.h:1146
succ_iterator succ_begin()
Definition CFG.h:1046
Stmt * getTerminatorStmt()
Definition CFG.h:1148
const_succ_reverse_iterator succ_rend() const
Definition CFG.h:1054
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
Definition CFG.h:1241
void setHasNoReturnElement(bool AnalyzerOnly=false)
Mark the block as ending in a noreturn element.
Definition CFG.h:1136
const Stmt * getLoopTarget() const
Definition CFG.h:1161
AdjacentBlocks::const_iterator const_pred_iterator
Definition CFG.h:1015
succ_const_range succs() const
Definition CFG.h:1060
unsigned pred_size() const
Definition CFG.h:1067
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
Definition CFG.h:1233
AdjacentBlocks::iterator succ_iterator
Definition CFG.h:1021
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
Definition CFG.h:1208
FilteredCFGBlockIterator< const_succ_iterator, false > filtered_succ_iterator
Definition CFG.h:1119
pred_const_range preds() const
Definition CFG.h:1042
ElementList Elements
The set of statements in the basic block.
Definition CFG.h:847
llvm::iterator_range< const_reverse_ref_iterator > const_reverse_ref_iterator_range
Definition CFG.h:988
const_reverse_iterator rbegin() const
Definition CFG.h:973
ElementRefImpl< false > CFGElementRef
Definition CFG.h:976
ref_iterator ref_end()
Definition CFG.h:992
pred_reverse_iterator pred_rbegin()
Definition CFG.h:1033
const Stmt * getTerminatorCondition(bool StripParens=true) const
Definition CFG.cpp:6533
ElementRefIterator< true, true > const_reverse_ref_iterator
Definition CFG.h:987
pred_iterator pred_begin()
Definition CFG.h:1028
const Stmt * LoopTarget
Some blocks are used to represent the "loop edge" to the start of a loop from within the loop body.
Definition CFG.h:861
reverse_ref_iterator rref_begin()
Definition CFG.h:996
iterator end()
Definition CFG.h:967
CFG * getParent() const
Definition CFG.h:1180
void appendCleanupFunction(const VarDecl *VD, BumpVectorContext &C)
Definition CFG.h:1249
pred_range preds()
Definition CFG.h:1038
reverse_ref_iterator rref_end()
Definition CFG.h:997
const Stmt * getTerminatorStmt() const
Definition CFG.h:1149
const_ref_iterator_range refs() const
Definition CFG.h:1002
const_iterator end() const
Definition CFG.h:969
const_ref_iterator ref_end() const
Definition CFG.h:994
void setLabel(Stmt *Statement)
Definition CFG.h:1133
unsigned getBlockID() const
Definition CFG.h:1178
const_succ_reverse_iterator succ_rbegin() const
Definition CFG.h:1053
void appendStmt(Stmt *statement, BumpVectorContext &C)
Definition CFG.h:1199
void appendFullExprCleanup(BumpVector< const MaterializeTemporaryExpr * > *BV, const ExprWithCleanups *CleanupExpr, BumpVectorContext &C)
Definition CFG.h:1257
llvm::iterator_range< const_ref_iterator > const_ref_iterator_range
Definition CFG.h:982
const_pred_iterator pred_begin() const
Definition CFG.h:1030
const_succ_iterator succ_end() const
Definition CFG.h:1049
const Expr * getLastCondition() const
Definition CFG.cpp:6505
const_pred_reverse_iterator pred_rend() const
Definition CFG.h:1036
void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, BumpVectorContext &C)
Definition CFG.h:1203
AdjacentBlocks::reverse_iterator succ_reverse_iterator
Definition CFG.h:1023
AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator
Definition CFG.h:1017
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
Definition CFG.cpp:5610
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
Definition CFG.h:1263
AdjacentBlocks::const_iterator const_succ_iterator
Definition CFG.h:1022
reverse_ref_iterator_range rrefs()
Definition CFG.h:1003
bool pred_empty() const
Definition CFG.h:1068
CFGTerminator Terminator
The terminator for a basic block that indicates the type of control-flow that occurs between a block ...
Definition CFG.h:856
llvm::iterator_range< succ_iterator > succ_range
Definition CFG.h:1025
unsigned succ_size() const
Definition CFG.h:1064
bool succ_empty() const
Definition CFG.h:1065
const_reverse_ref_iterator rref_begin() const
Definition CFG.h:998
llvm::iterator_range< const_pred_iterator > pred_const_range
Definition CFG.h:1019
Represents a function call that returns a C++ object by value.
Definition CFG.h:190
const ConstructionContext * getConstructionContext() const
Definition CFG.h:216
CFGCXXRecordTypedCall(const Expr *E, const ConstructionContext *C)
Definition CFG.h:203
friend class CFGElement
Definition CFG.h:221
static bool isCXXRecordTypedCall(const Expr *E)
Returns true when call expression CE needs to be represented by CFGCXXRecordTypedCall,...
Definition CFG.h:194
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
Definition CFG.h:1276
CFGCallback()=default
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
Definition CFG.h:1283
virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition CFG.h:1281
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition CFG.h:1282
virtual void compareBitwiseOr(const BinaryOperator *B)
Definition CFG.h:1285
virtual ~CFGCallback()=default
CFGCleanupFunction(const VarDecl *VD)
Definition CFG.h:439
const VarDecl * getVarDecl() const
Definition CFG.h:444
const FunctionDecl * getFunctionDecl() const
Returns the function to be called when cleaning up the var decl.
Definition CFG.h:449
friend class CFGElement
Definition CFG.h:455
Represents C++ constructor call.
Definition CFG.h:161
const ConstructionContext * getConstructionContext() const
Definition CFG.h:170
friend class CFGElement
Definition CFG.h:175
CFGConstructor(const CXXConstructExpr *CE, const ConstructionContext *C)
Definition CFG.h:163
Represents C++ object destructor generated from a call to delete.
Definition CFG.h:490
CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
Definition CFG.h:492
friend class CFGElement
Definition CFG.h:505
const CXXDeleteExpr * getDeleteExpr() const
Definition CFG.h:500
const CXXRecordDecl * getCXXRecordDecl() const
Definition CFG.h:495
Represents a top-level expression in a basic block.
Definition CFG.h:55
llvm::PointerIntPair< const void *, 2 > Data2
Definition CFG.h:89
@ CleanupFunction
Definition CFG.h:83
@ CXXRecordTypedCall
Definition CFG.h:72
@ FullExprCleanup
Definition CFG.h:62
@ AutomaticObjectDtor
Definition CFG.h:76
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Definition CFG.h:103
void dumpToStream(llvm::raw_ostream &OS, bool TerminateWithNewLine=true) const
Definition CFG.cpp:5998
llvm::PointerIntPair< const void *, 2 > Data1
Definition CFG.h:88
Kind getKind() const
Definition CFG.h:122
void dump() const
Definition CFG.h:132
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Definition CFG.h:113
CFGElement(Kind kind, const void *Ptr1, const void *Ptr2=nullptr)
Definition CFG.h:91
CFGElement()=default
ArrayRef< const MaterializeTemporaryExpr * > getExpiringMTEs() const
Definition CFG.h:354
const ExprWithCleanups * getCleanupExpr() const
Definition CFG.h:348
CFGFullExprCleanup(const MTEVecTy *MTEs, const ExprWithCleanups *CleanupExpr)
Definition CFG.h:344
friend class CFGElement
Definition CFG.h:364
BumpVector< const MaterializeTemporaryExpr * > MTEVecTy
Definition CFG.h:343
SourceLocation getCleanupLoc() const
Definition CFG.h:352
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Definition CFG.cpp:5522
CFGImplicitDtor(Kind kind, const void *data1, const void *data2=nullptr)
Definition CFG.h:418
friend class CFGElement
Definition CFG.h:428
bool isNoReturn(ASTContext &astContext) const
Represents C++ base or member initializer from constructor's initialization list.
Definition CFG.h:232
CFGInitializer(const CXXCtorInitializer *initializer)
Definition CFG.h:234
friend class CFGElement
Definition CFG.h:242
const CXXCtorInitializer * getInitializer() const
Definition CFG.h:237
Represents the point where the lifetime of an automatic object ends.
Definition CFG.h:321
CFGLifetimeEnds(const VarDecl *Var, const Stmt *Stmt)
Definition CFG.h:323
friend class CFGElement
Definition CFG.h:331
const VarDecl * getVarDecl() const
Definition CFG.h:326
Represents the point where a loop ends.
Definition CFG.h:278
const Stmt * getLoopStmt() const
Definition CFG.h:282
friend class CFGElement
Definition CFG.h:287
CFGLoopExit(const Stmt *stmt)
Definition CFG.h:280
Represents C++ object destructor implicitly generated for member object in destructor.
Definition CFG.h:537
friend class CFGElement
Definition CFG.h:547
const FieldDecl * getFieldDecl() const
Definition CFG.h:542
CFGMemberDtor(const FieldDecl *field)
Definition CFG.h:539
Represents C++ allocator call.
Definition CFG.h:252
const CXXNewExpr * getAllocatorExpr() const
Definition CFG.h:258
friend class CFGElement
Definition CFG.h:263
CFGNewAllocator(const CXXNewExpr *S)
Definition CFG.h:254
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt.
Definition CFG.h:375
friend class CFGElement
Definition CFG.h:387
const VarDecl * getVarDecl() const
Definition CFG.h:382
CFGScopeBegin(const VarDecl *VD, const Stmt *S)
Definition CFG.h:378
Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...
Definition CFG.h:395
CFGScopeEnd(const VarDecl *VD, const Stmt *S)
Definition CFG.h:398
friend class CFGElement
Definition CFG.h:406
const VarDecl * getVarDecl() const
Definition CFG.h:401
LLVM_ATTRIBUTE_RETURNS_NONNULL const Stmt * getTriggerStmt() const
Definition CFG.h:300
friend class CFGElement
Definition CFG.h:305
CFGScopeMarker(Kind K, const Stmt *S, const void *Ptr2=nullptr)
Definition CFG.h:314
CFGStmt(const Stmt *S, Kind K=Statement)
Definition CFG.h:139
friend class CFGElement
Definition CFG.h:148
CFGStmt()=default
const Stmt * getStmt() const
Definition CFG.h:143
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
Definition CFG.h:558
const CXXBindTemporaryExpr * getBindTemporaryExpr() const
Definition CFG.h:563
CFGTemporaryDtor(const CXXBindTemporaryExpr *expr)
Definition CFG.h:560
friend class CFGElement
Definition CFG.h:568
Represents CFGBlock terminator statement.
Definition CFG.h:579
Stmt * getStmt()
Definition CFG.h:611
bool isVirtualBaseBranch() const
Definition CFG.h:621
bool isTemporaryDtorsBranch() const
Definition CFG.h:618
bool isValid() const
Definition CFG.h:610
bool isStmtBranch() const
Definition CFG.h:615
Kind getKind() const
Definition CFG.h:613
CFGTerminator(Stmt *S, Kind K=StmtBranch)
Definition CFG.h:608
const Stmt * getStmt() const
Definition CFG.h:612
@ TemporaryDtorsBranch
A branch in control flow of destructors of temporaries.
Definition CFG.h:588
@ VirtualBaseBranch
A shortcut around virtual base initializers.
Definition CFG.h:592
@ StmtBranch
A branch that corresponds to a statement in the code, such as an if-statement.
Definition CFG.h:584
@ NumKindsMinusOne
Number of different kinds, for assertions.
Definition CFG.h:597
bool PruneTriviallyFalseEdges
Definition CFG.h:1311
bool OmitImplicitValueInitializers
Definition CFG.h:1331
ForcedBlkExprs ** forcedBlkExprs
Definition CFG.h:1309
bool AddCXXDefaultInitExprInAggregates
Definition CFG.h:1327
bool AddCXXDefaultInitExprInCtors
Definition CFG.h:1326
BuildOptions & setAllAlwaysAdd()
Definition CFG.h:1345
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
Definition CFG.h:1340
bool AssumeReachableDefaultInSwitchStatements
Definition CFG.h:1332
CFGCallback * Observer
Definition CFG.h:1310
bool alwaysAdd(const Stmt *stmt) const
Definition CFG.h:1336
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
Definition CFG.h:1307
bool MarkElidedCXXConstructors
Definition CFG.h:1329
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1295
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Definition CFG.h:1493
llvm::iterator_range< synthetic_stmt_iterator > synthetic_stmt_range
Definition CFG.h:1450
CFGBlockListTy::const_iterator const_iterator
Definition CFG.h:1374
const_iterator nodes_end() const
Definition CFG.h:1395
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:6379
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition CFG.h:1376
try_block_range try_blocks() const
Definition CFG.h:1428
iterator end()
Definition CFG.h:1382
bool isLinear() const
Returns true if the CFG has no branches.
Definition CFG.cpp:5476
synthetic_stmt_range synthetic_stmts() const
Definition CFG.h:1467
void VisitBlockStmts(Callback &O) const
Definition CFG.h:1475
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:5469
llvm::BumpPtrAllocator & getAllocator()
Definition CFG.h:1515
std::reverse_iterator< iterator > reverse_iterator
Definition CFG.h:1375
CFGBlockListTy::iterator iterator
Definition CFG.h:1373
const_reverse_iterator rbegin() const
Definition CFG.h:1399
const_iterator end() const
Definition CFG.h:1384
CFGBlock * createBlock()
Create a new block in the CFG.
Definition CFG.cpp:5453
void addSyntheticDeclStmt(const DeclStmt *Synthetic, const DeclStmt *Source)
Records a synthetic DeclStmt and the DeclStmt it was constructed from.
Definition CFG.h:1440
const CFGBlock * getIndirectGotoBlock() const
Definition CFG.h:1415
llvm::iterator_range< try_block_iterator > try_block_range
Definition CFG.h:1418
const_iterator begin() const
Definition CFG.h:1383
CFGBlock & getExit()
Definition CFG.h:1411
iterator begin()
Definition CFG.h:1381
void setIndirectGotoBlock(CFGBlock *B)
Set the block used for indirect goto jumps.
Definition CFG.h:1366
void addTryDispatchBlock(const CFGBlock *block)
Definition CFG.h:1432
try_block_iterator try_blocks_end() const
Definition CFG.h:1424
synthetic_stmt_iterator synthetic_stmt_end() const
Definition CFG.h:1462
void setEntry(CFGBlock *B)
Set the entry block of the CFG.
Definition CFG.h:1362
CFGBlock & getEntry()
Definition CFG.h:1409
llvm::iterator_range< const_iterator > const_nodes() const
Definition CFG.h:1390
const CFGBlock & getEntry() const
Definition CFG.h:1410
CFGBlock * getIndirectGotoBlock()
Definition CFG.h:1414
llvm::iterator_range< reverse_iterator > reverse_nodes()
Definition CFG.h:1402
std::vector< const CFGBlock * >::const_iterator try_block_iterator
Definition CFG.h:1417
CFGBlock & front()
Definition CFG.h:1378
const CFGBlock & getExit() const
Definition CFG.h:1412
llvm::iterator_range< const_reverse_iterator > const_reverse_nodes() const
Definition CFG.h:1405
const_reverse_iterator rend() const
Definition CFG.h:1400
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
Definition CFG.cpp:6374
iterator nodes_begin()
Definition CFG.h:1386
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1488
const_iterator nodes_begin() const
Definition CFG.h:1394
void viewCFG(const LangOptions &LO) const
Definition CFG.cpp:6604
try_block_iterator try_blocks_begin() const
Definition CFG.h:1420
BumpVector< CFGBlock * > CFGBlockListTy
Definition CFG.h:1372
iterator nodes_end()
Definition CFG.h:1387
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
Definition CFG.h:1457
reverse_iterator rbegin()
Definition CFG.h:1397
reverse_iterator rend()
Definition CFG.h:1398
CFGBlock & back()
Definition CFG.h:1379
llvm::iterator_range< iterator > nodes()
Definition CFG.h:1389
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
Definition CFG.h:1448
BumpVectorContext & getBumpVectorContext()
Definition CFG.h:1519
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents binding an expression to a temporary.
Definition ExprCXX.h:1498
Represents a call to a C++ constructor.
Definition ExprCXX.h:1553
Represents a C++ base or member initializer.
Definition DeclCXX.h:2407
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2631
Represents a C++ destructor within a class.
Definition DeclCXX.h:2907
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2360
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
ConstructionContext's subclasses describe different ways of constructing an object in C++.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1643
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1656
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
bool hasAttr() const
Definition DeclBase.h:585
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
Definition ExprCXX.h:3715
SourceLocation getEndLoc() const LLVM_READONLY
Definition ExprCXX.h:3758
This represents one expression.
Definition Expr.h:113
bool isGLValue() const
Definition Expr.h:288
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3299
Represents a function declaration or definition.
Definition Decl.h:2059
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
QualType getCanonicalType() const
Definition TypeBase.h:8498
Encodes a location in the source.
Stmt - This represents one statement.
Definition Stmt.h:85
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
Represents a variable declaration or definition.
Definition Decl.h:933
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
llvm::mapped_iterator< llvm::filter_iterator< IterT, CFGBlockReachableEdge >, CFGBlockEdgeTarget< BlockT > > CFGReachableChildIterator
Definition CFG.h:1571
auto cfgReachableChildren(RangeT Edges)
Definition CFG.h:1576
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CFGBlock::ConstCFGElementRef ConstCFGElementRef
Definition CFG.h:1272
Stmt Stmt * Callback
Definition StmtOpenMP.h:930
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition CallGraph.h:218
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
const FunctionProtoType * T
bool operator!=(CanQual< T > x, CanQual< U > y)
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
Definition CFG.cpp:1461
@ Other
Other implicit parameter.
Definition Decl.h:1775
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
BlockT * operator()(const CFGBlock::AdjacentBlock &AB) const
Definition CFG.h:1563
bool operator()(const CFGBlock::AdjacentBlock &AB) const
Definition CFG.h:1558
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1665
clang::detail::CFGReachableChildIterator< clang::CFGBlock::pred_iterator, clang::CFGBlock > ChildIteratorType
Definition CFG.h:1651
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1660
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1656
static NodeRef getEntryNode(Inverse< clang::CFGBlock * > G)
Definition CFG.h:1655
static NodeRef getEntryNode(const ::clang::CFG *F)
Definition CFG.h:1763
static nodes_iterator nodes_begin(const ::clang::CFG *F)
Definition CFG.h:1765
static nodes_iterator nodes_end(const ::clang::CFG *F)
Definition CFG.h:1769
::clang::CFG::const_iterator nodes_iterator
Definition CFG.h:1761
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1776
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1773
clang::detail::CFGReachableChildIterator< clang::CFGBlock::const_pred_iterator, const clang::CFGBlock > ChildIteratorType
Definition CFG.h:1675
static NodeRef getEntryNode(Inverse< const clang::CFGBlock * > G)
Definition CFG.h:1678
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1692
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1681
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1686
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1755
static nodes_iterator nodes_end(::clang::CFG *F)
Definition CFG.h:1750
::clang::CFG::iterator nodes_iterator
Definition CFG.h:1746
static NodeRef getEntryNode(::clang::CFG *F)
Definition CFG.h:1748
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1752
static nodes_iterator nodes_begin(::clang::CFG *F)
Definition CFG.h:1749
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1611
static NodeRef getEntryNode(clang::CFGBlock *BB)
Definition CFG.h:1606
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1607
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1616
clang::detail::CFGReachableChildIterator< clang::CFGBlock::succ_iterator, clang::CFGBlock > ChildIteratorType
Definition CFG.h:1602
::clang::CFG::const_iterator nodes_iterator
Definition CFG.h:1721
static nodes_iterator nodes_begin(const ::clang::CFG *F)
Definition CFG.h:1725
static unsigned size(const ::clang::CFG *F)
Definition CFG.h:1733
static nodes_iterator nodes_end(const ::clang::CFG *F)
Definition CFG.h:1729
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1740
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1737
static NodeRef getEntryNode(const ::clang::CFG *F)
Definition CFG.h:1723
static NodeRef getEntryNode(const clang::CFGBlock *BB)
Definition CFG.h:1629
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1641
clang::detail::CFGReachableChildIterator< clang::CFGBlock::const_succ_iterator, const clang::CFGBlock > ChildIteratorType
Definition CFG.h:1626
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1630
const clang::CFGBlock * NodeRef
Definition CFG.h:1625
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1635
static nodes_iterator nodes_end(::clang::CFG *F)
Definition CFG.h:1708
static unsigned size(::clang::CFG *F)
Definition CFG.h:1709
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1711
::clang::CFG::iterator nodes_iterator
Definition CFG.h:1704
static NodeRef getEntryNode(::clang::CFG *F)
Definition CFG.h:1706
static nodes_iterator nodes_begin(::clang::CFG *F)
Definition CFG.h:1707
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1715
static SimpleType getSimplifiedValue(::clang::CFGTerminator Val)
Definition CFG.h:1591