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
426private:
427 friend class CFGElement;
428
429 static bool isKind(const CFGElement &E) {
430 Kind kind = E.getKind();
431 return kind >= DTOR_BEGIN && kind <= DTOR_END;
432 }
433};
434
435class CFGCleanupFunction final : public CFGElement {
436public:
440 assert(VD->hasAttr<CleanupAttr>());
441 }
442
443 const VarDecl *getVarDecl() const {
444 return static_cast<const VarDecl *>(Data1.getPointer());
445 }
446
447 /// Returns the function to be called when cleaning up the var decl.
449 const CleanupAttr *A = getVarDecl()->getAttr<CleanupAttr>();
450 return A->getFunctionDecl();
451 }
452
453private:
454 friend class CFGElement;
455
456 static bool isKind(const CFGElement E) {
457 return E.getKind() == Kind::CleanupFunction;
458 }
459};
460
461/// Represents C++ object destructor implicitly generated for automatic object
462/// or temporary bound to const reference at the point of leaving its local
463/// scope.
465public:
468
469 const VarDecl *getVarDecl() const {
470 return static_cast<const VarDecl *>(Data1.getPointer());
471 }
472
473 // Get statement end of which triggered the destructor call.
474 const Stmt *getTriggerStmt() const {
475 return static_cast<const Stmt *>(Data2.getPointer());
476 }
477
478private:
479 friend class CFGElement;
480
481 CFGAutomaticObjDtor() = default;
482
483 static bool isKind(const CFGElement &elem) {
484 return elem.getKind() == AutomaticObjectDtor;
485 }
486};
487
488/// Represents C++ object destructor generated from a call to delete.
490public:
492 : CFGImplicitDtor(DeleteDtor, RD, DE) {}
493
495 return static_cast<const CXXRecordDecl *>(Data1.getPointer());
496 }
497
498 // Get Delete expression which triggered the destructor call.
500 return static_cast<const CXXDeleteExpr *>(Data2.getPointer());
501 }
502
503private:
504 friend class CFGElement;
505
506 CFGDeleteDtor() = default;
507
508 static bool isKind(const CFGElement &elem) {
509 return elem.getKind() == DeleteDtor;
510 }
511};
512
513/// Represents C++ object destructor implicitly generated for base object in
514/// destructor.
516public:
519
521 return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
522 }
523
524private:
525 friend class CFGElement;
526
527 CFGBaseDtor() = default;
528
529 static bool isKind(const CFGElement &E) {
530 return E.getKind() == BaseDtor;
531 }
532};
533
534/// Represents C++ object destructor implicitly generated for member object in
535/// destructor.
537public:
540
541 const FieldDecl *getFieldDecl() const {
542 return static_cast<const FieldDecl*>(Data1.getPointer());
543 }
544
545private:
546 friend class CFGElement;
547
548 CFGMemberDtor() = default;
549
550 static bool isKind(const CFGElement &E) {
551 return E.getKind() == MemberDtor;
552 }
553};
554
555/// Represents C++ object destructor implicitly generated at the end of full
556/// expression for temporary object.
558public:
561
563 return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
564 }
565
566private:
567 friend class CFGElement;
568
569 CFGTemporaryDtor() = default;
570
571 static bool isKind(const CFGElement &E) {
572 return E.getKind() == TemporaryDtor;
573 }
574};
575
576/// Represents CFGBlock terminator statement.
577///
579public:
580 enum Kind {
581 /// A branch that corresponds to a statement in the code,
582 /// such as an if-statement.
584 /// A branch in control flow of destructors of temporaries. In this case
585 /// terminator statement is the same statement that branches control flow
586 /// in evaluation of matching full expression.
588 /// A shortcut around virtual base initializers. It gets taken when
589 /// virtual base classes have already been initialized by the constructor
590 /// of the most derived class while we're in the base class.
592
593 /// Number of different kinds, for assertions. We subtract 1 so that
594 /// to keep receiving compiler warnings when we don't cover all enum values
595 /// in a switch.
597 };
598
599private:
600 static constexpr int KindBits = 2;
601 static_assert((1 << KindBits) > NumKindsMinusOne,
602 "Not enough room for kind!");
603 llvm::PointerIntPair<Stmt *, KindBits> Data;
604
605public:
606 CFGTerminator() { assert(!isValid()); }
607 CFGTerminator(Stmt *S, Kind K = StmtBranch) : Data(S, K) {}
608
609 bool isValid() const { return Data.getOpaqueValue() != nullptr; }
610 Stmt *getStmt() { return Data.getPointer(); }
611 const Stmt *getStmt() const { return Data.getPointer(); }
612 Kind getKind() const { return static_cast<Kind>(Data.getInt()); }
613
614 bool isStmtBranch() const {
615 return getKind() == StmtBranch;
616 }
618 return getKind() == TemporaryDtorsBranch;
619 }
620 bool isVirtualBaseBranch() const {
621 return getKind() == VirtualBaseBranch;
622 }
623};
624
625/// Represents a single basic block in a source-level CFG.
626/// It consists of:
627///
628/// (1) A set of statements/expressions (which may contain subexpressions).
629/// (2) A "terminator" statement (not in the set of statements).
630/// (3) A list of successors and predecessors.
631///
632/// Terminator: The terminator represents the type of control-flow that occurs
633/// at the end of the basic block. The terminator is a Stmt* referring to an
634/// AST node that has control-flow: if-statements, breaks, loops, etc.
635/// If the control-flow is conditional, the condition expression will appear
636/// within the set of statements in the block (usually the last statement).
637///
638/// Predecessors: the order in the set of predecessors is arbitrary.
639///
640/// Successors: the order in the set of successors is NOT arbitrary. We
641/// currently have the following orderings based on the terminator:
642///
643/// Terminator | Successor Ordering
644/// ------------------|------------------------------------
645/// if | Then Block; Else Block
646/// ? operator | LHS expression; RHS expression
647/// logical and/or | expression that consumes the op, RHS
648/// vbase inits | already handled by the most derived class; not yet
649///
650/// But note that any of that may be NULL in case of optimized-out edges.
651class CFGBlock {
652 class ElementList {
653 using ImplTy = BumpVector<CFGElement>;
654
655 ImplTy Impl;
656
657 public:
658 ElementList(BumpVectorContext &C) : Impl(C, 4) {}
659
660 using iterator = std::reverse_iterator<ImplTy::iterator>;
661 using const_iterator = std::reverse_iterator<ImplTy::const_iterator>;
664 using const_reference = ImplTy::const_reference;
665
666 void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
667
668 reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
670 return Impl.insert(I, Cnt, E, C);
671 }
672
673 const_reference front() const { return Impl.back(); }
674 const_reference back() const { return Impl.front(); }
675
676 iterator begin() { return Impl.rbegin(); }
677 iterator end() { return Impl.rend(); }
678 const_iterator begin() const { return Impl.rbegin(); }
679 const_iterator end() const { return Impl.rend(); }
680 reverse_iterator rbegin() { return Impl.begin(); }
681 reverse_iterator rend() { return Impl.end(); }
682 const_reverse_iterator rbegin() const { return Impl.begin(); }
683 const_reverse_iterator rend() const { return Impl.end(); }
684
685 CFGElement operator[](size_t i) const {
686 assert(i < Impl.size());
687 return Impl[Impl.size() - 1 - i];
688 }
689
690 size_t size() const { return Impl.size(); }
691 bool empty() const { return Impl.empty(); }
692 };
693
694 /// A convenience class for comparing CFGElements, since methods of CFGBlock
695 /// like operator[] return CFGElements by value. This is practically a wrapper
696 /// around a (CFGBlock, Index) pair.
697 template <bool IsConst> class ElementRefImpl {
698
699 template <bool IsOtherConst> friend class ElementRefImpl;
700
701 using CFGBlockPtr =
702 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;
703
704 using CFGElementPtr =
705 std::conditional_t<IsConst, const CFGElement *, CFGElement *>;
706
707 protected:
708 CFGBlockPtr Parent;
709 size_t Index;
710
711 public:
712 ElementRefImpl(CFGBlockPtr Parent, size_t Index)
713 : Parent(Parent), Index(Index) {}
714
715 template <bool IsOtherConst>
716 ElementRefImpl(ElementRefImpl<IsOtherConst> Other)
717 : ElementRefImpl(Other.Parent, Other.Index) {}
718
719 size_t getIndexInBlock() const { return Index; }
720
721 CFGBlockPtr getParent() { return Parent; }
722 CFGBlockPtr getParent() const { return Parent; }
723
724 bool operator<(ElementRefImpl Other) const {
725 return std::make_pair(Parent, Index) <
726 std::make_pair(Other.Parent, Other.Index);
727 }
728
729 bool operator==(ElementRefImpl Other) const {
730 return Parent == Other.Parent && Index == Other.Index;
731 }
732
733 bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
734 CFGElement operator*() const { return (*Parent)[Index]; }
735 CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
736
737 void dumpToStream(llvm::raw_ostream &OS) const {
738 OS << getIndexInBlock() + 1 << ": ";
739 (*this)->dumpToStream(OS);
740 }
741
742 void dump() const {
743 dumpToStream(llvm::errs());
744 }
745
746 void Profile(llvm::FoldingSetNodeID &ID) const {
747 ID.AddPointer(Parent);
748 ID.AddInteger(Index);
749 }
750 };
751
752 template <bool IsReverse, bool IsConst> class ElementRefIterator {
753
754 template <bool IsOtherReverse, bool IsOtherConst>
755 friend class ElementRefIterator;
756
757 using CFGBlockRef =
758 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;
759
760 using UnderlayingIteratorTy = std::conditional_t<
761 IsConst,
762 std::conditional_t<IsReverse, ElementList::const_reverse_iterator,
763 ElementList::const_iterator>,
764 std::conditional_t<IsReverse, ElementList::reverse_iterator,
765 ElementList::iterator>>;
766
767 using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
768 using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;
769
770 public:
771 using difference_type = typename IteratorTraits::difference_type;
772 using value_type = ElementRef;
773 using pointer = ElementRef *;
774 using iterator_category = typename IteratorTraits::iterator_category;
775
776 private:
777 CFGBlockRef Parent;
778 UnderlayingIteratorTy Pos;
779
780 public:
781 ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos)
782 : Parent(Parent), Pos(Pos) {}
783
784 template <bool IsOtherConst>
785 ElementRefIterator(ElementRefIterator<false, IsOtherConst> E)
786 : ElementRefIterator(E.Parent, E.Pos.base()) {}
787
788 template <bool IsOtherConst>
789 ElementRefIterator(ElementRefIterator<true, IsOtherConst> E)
790 : ElementRefIterator(E.Parent, std::make_reverse_iterator(E.Pos)) {}
791
792 bool operator<(ElementRefIterator Other) const {
793 assert(Parent == Other.Parent);
794 return Pos < Other.Pos;
795 }
796
797 bool operator==(ElementRefIterator Other) const {
798 return Parent == Other.Parent && Pos == Other.Pos;
799 }
800
801 bool operator!=(ElementRefIterator Other) const {
802 return !(*this == Other);
803 }
804
805 private:
806 template <bool IsOtherConst>
807 static size_t
808 getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) {
809 return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1;
810 }
811
812 template <bool IsOtherConst>
813 static size_t
814 getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) {
815 return E.Pos - E.Parent->begin();
816 }
817
818 public:
819 value_type operator*() { return {Parent, getIndexInBlock(*this)}; }
820
821 difference_type operator-(ElementRefIterator Other) const {
822 return Pos - Other.Pos;
823 }
824
825 ElementRefIterator operator++() {
826 ++this->Pos;
827 return *this;
828 }
829 ElementRefIterator operator++(int) {
830 ElementRefIterator Ret = *this;
831 ++*this;
832 return Ret;
833 }
834 ElementRefIterator operator+(size_t count) {
835 this->Pos += count;
836 return *this;
837 }
838 ElementRefIterator operator-(size_t count) {
839 this->Pos -= count;
840 return *this;
841 }
842 };
843
844public:
845 /// The set of statements in the basic block.
846 ElementList Elements;
847
848 /// An (optional) label that prefixes the executable statements in the block.
849 /// When this variable is non-NULL, it is either an instance of LabelStmt,
850 /// SwitchCase or CXXCatchStmt.
851 Stmt *Label = nullptr;
852
853 /// The terminator for a basic block that indicates the type of control-flow
854 /// that occurs between a block and its successors.
856
857 /// Some blocks are used to represent the "loop edge" to the start of a loop
858 /// from within the loop body. This Stmt* will be refer to the loop statement
859 /// for such blocks (and be null otherwise).
860 const Stmt *LoopTarget = nullptr;
861
862 /// A numerical ID assigned to a CFGBlock during construction of the CFG.
863 unsigned BlockID;
864
865public:
866 /// This class represents a potential adjacent block in the CFG. It encodes
867 /// whether or not the block is actually reachable, or can be proved to be
868 /// trivially unreachable. For some cases it allows one to encode scenarios
869 /// where a block was substituted because the original (now alternate) block
870 /// is unreachable.
872 enum Kind {
873 AB_Normal,
874 AB_Unreachable,
875 AB_Alternate
876 };
877
878 CFGBlock *ReachableBlock;
879 llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock;
880
881 public:
882 /// Construct an AdjacentBlock with a possibly unreachable block.
883 AdjacentBlock(CFGBlock *B, bool IsReachable);
884
885 /// Construct an AdjacentBlock with a reachable block and an alternate
886 /// unreachable block.
887 AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
888
889 /// Get the reachable block, if one exists.
891 return ReachableBlock;
892 }
893
894 /// Get the potentially unreachable block.
896 return UnreachableBlock.getPointer();
897 }
898
899 /// Provide an implicit conversion to CFGBlock* so that
900 /// AdjacentBlock can be substituted for CFGBlock*.
901 operator CFGBlock*() const {
902 return getReachableBlock();
903 }
904
906 return *getReachableBlock();
907 }
908
910 return getReachableBlock();
911 }
912
913 bool isReachable() const {
914 Kind K = (Kind) UnreachableBlock.getInt();
915 return K == AB_Normal || K == AB_Alternate;
916 }
917 };
918
919private:
920 /// Keep track of the predecessor / successor CFG blocks.
921 using AdjacentBlocks = BumpVector<AdjacentBlock>;
922 AdjacentBlocks Preds;
923 AdjacentBlocks Succs;
924
925 /// The kind of noreturn element a block contains.
926 enum class NoReturnKind : unsigned {
927 None,
928 /// A function call attributed as 'analyzer_noreturn'.
929 AnalyzerOnly,
930 /// A function call or implicit destructor attributed as 'noreturn'.
931 Real
932 };
933
934 /// This bit is set when the basic block contains a function call
935 /// or implicit destructor that is attributed as 'noreturn' or
936 /// 'analyzer_noreturn'. In that case, control cannot technically ever
937 /// proceed past this block. All such blocks will have a single immediate
938 /// successor: the exit block. This allows them to be easily reached from the
939 /// exit block and using this bit quickly recognized without scanning the
940 /// contents of the block.
941 ///
942 /// Optimization Note: These bits could be profitably folded with Terminator's
943 /// storage if the memory usage of CFGBlock becomes an issue.
944 NoReturnKind NoReturn : 2;
945
946 /// The parent CFG that owns this CFGBlock.
947 CFG *Parent;
948
949public:
950 explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
951 : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1),
952 Succs(C, 1), NoReturn(NoReturnKind::None), Parent(parent) {}
953
954 // Statement iterators
955 using iterator = ElementList::iterator;
956 using const_iterator = ElementList::const_iterator;
957 using reverse_iterator = ElementList::reverse_iterator;
958 using const_reverse_iterator = ElementList::const_reverse_iterator;
959
960 size_t getIndexInCFG() const;
961
962 CFGElement front() const { return Elements.front(); }
963 CFGElement back() const { return Elements.back(); }
964
965 iterator begin() { return Elements.begin(); }
966 iterator end() { return Elements.end(); }
967 const_iterator begin() const { return Elements.begin(); }
968 const_iterator end() const { return Elements.end(); }
969
970 reverse_iterator rbegin() { return Elements.rbegin(); }
971 reverse_iterator rend() { return Elements.rend(); }
972 const_reverse_iterator rbegin() const { return Elements.rbegin(); }
973 const_reverse_iterator rend() const { return Elements.rend(); }
974
975 using CFGElementRef = ElementRefImpl<false>;
976 using ConstCFGElementRef = ElementRefImpl<true>;
977
978 using ref_iterator = ElementRefIterator<false, false>;
979 using ref_iterator_range = llvm::iterator_range<ref_iterator>;
980 using const_ref_iterator = ElementRefIterator<false, true>;
981 using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>;
982
983 using reverse_ref_iterator = ElementRefIterator<true, false>;
984 using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>;
985
986 using const_reverse_ref_iterator = ElementRefIterator<true, true>;
988 llvm::iterator_range<const_reverse_ref_iterator>;
989
990 ref_iterator ref_begin() { return {this, begin()}; }
991 ref_iterator ref_end() { return {this, end()}; }
992 const_ref_iterator ref_begin() const { return {this, begin()}; }
993 const_ref_iterator ref_end() const { return {this, end()}; }
994
995 reverse_ref_iterator rref_begin() { return {this, rbegin()}; }
996 reverse_ref_iterator rref_end() { return {this, rend()}; }
997 const_reverse_ref_iterator rref_begin() const { return {this, rbegin()}; }
998 const_reverse_ref_iterator rref_end() const { return {this, rend()}; }
999
1004 return {rref_begin(), rref_end()};
1005 }
1006
1007 unsigned size() const { return Elements.size(); }
1008 bool empty() const { return Elements.empty(); }
1009
1010 CFGElement operator[](size_t i) const { return Elements[i]; }
1011
1012 // CFG iterators
1017 using pred_range = llvm::iterator_range<pred_iterator>;
1018 using pred_const_range = llvm::iterator_range<const_pred_iterator>;
1019
1024 using succ_range = llvm::iterator_range<succ_iterator>;
1025 using succ_const_range = llvm::iterator_range<const_succ_iterator>;
1026
1027 pred_iterator pred_begin() { return Preds.begin(); }
1028 pred_iterator pred_end() { return Preds.end(); }
1029 const_pred_iterator pred_begin() const { return Preds.begin(); }
1030 const_pred_iterator pred_end() const { return Preds.end(); }
1031
1032 pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); }
1033 pred_reverse_iterator pred_rend() { return Preds.rend(); }
1034 const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
1035 const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
1036
1038 return pred_range(pred_begin(), pred_end());
1039 }
1040
1043 }
1044
1045 succ_iterator succ_begin() { return Succs.begin(); }
1046 succ_iterator succ_end() { return Succs.end(); }
1047 const_succ_iterator succ_begin() const { return Succs.begin(); }
1048 const_succ_iterator succ_end() const { return Succs.end(); }
1049
1050 succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); }
1051 succ_reverse_iterator succ_rend() { return Succs.rend(); }
1052 const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
1053 const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
1054
1056 return succ_range(succ_begin(), succ_end());
1057 }
1058
1061 }
1062
1063 unsigned succ_size() const { return Succs.size(); }
1064 bool succ_empty() const { return Succs.empty(); }
1065
1066 unsigned pred_size() const { return Preds.size(); }
1067 bool pred_empty() const { return Preds.empty(); }
1068
1069
1071 public:
1072 LLVM_PREFERRED_TYPE(bool)
1074 LLVM_PREFERRED_TYPE(bool)
1076
1079 };
1080
1081 static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
1082 const CFGBlock *Dst);
1083
1084 template <typename IMPL, bool IsPred>
1086 private:
1087 IMPL I, E;
1088 const FilterOptions F;
1089 const CFGBlock *From;
1090
1091 public:
1092 explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
1093 const CFGBlock *from,
1094 const FilterOptions &f)
1095 : I(i), E(e), F(f), From(from) {
1096 while (hasMore() && Filter(*I))
1097 ++I;
1098 }
1099
1100 bool hasMore() const { return I != E; }
1101
1103 do { ++I; } while (hasMore() && Filter(*I));
1104 return *this;
1105 }
1106
1107 const CFGBlock *operator*() const { return *I; }
1108
1109 private:
1110 bool Filter(const CFGBlock *To) {
1111 return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
1112 }
1113 };
1114
1117
1120
1124
1128
1129 // Manipulation of block contents
1130
1132 void setLabel(Stmt *Statement) { Label = Statement; }
1133 void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
1134 /// Mark the block as ending in a noreturn element.
1135 void setHasNoReturnElement(bool AnalyzerOnly = false) {
1136 assert(NoReturn == NoReturnKind::None &&
1137 "block already has a noreturn element");
1138 NoReturn = AnalyzerOnly ? NoReturnKind::AnalyzerOnly : NoReturnKind::Real;
1139 }
1140
1141 /// Returns true if the block would eventually end with a sink (a noreturn
1142 /// node).
1143 bool isInevitablySinking() const;
1144
1146
1147 Stmt *getTerminatorStmt() { return Terminator.getStmt(); }
1148 const Stmt *getTerminatorStmt() const { return Terminator.getStmt(); }
1149
1150 /// \returns the last (\c rbegin()) condition, e.g. observe the following code
1151 /// snippet:
1152 /// if (A && B && C)
1153 /// A block would be created for \c A, \c B, and \c C. For the latter,
1154 /// \c getTerminatorStmt() would retrieve the entire condition, rather than
1155 /// C itself, while this method would only return C.
1156 const Expr *getLastCondition() const;
1157
1158 const Stmt *getTerminatorCondition(bool StripParens = true) const;
1159
1160 const Stmt *getLoopTarget() const { return LoopTarget; }
1161
1162 Stmt *getLabel() { return Label; }
1163 const Stmt *getLabel() const { return Label; }
1164
1165 /// Returns true if the block has a noreturn element, whether it is a real
1166 /// 'noreturn' or an 'analyzer_noreturn'.
1167 bool hasNoReturnElement() const { return NoReturn != NoReturnKind::None; }
1168
1169 /// Returns true if the block ends in an 'analyzer_noreturn' call (as opposed
1170 /// to a real 'noreturn' one). Most analyses treat the two indistinguishably
1171 /// (see hasNoReturnElement). This is for clients that need to tell them
1172 /// apart (e.g., -Wunreachable-code).
1174 return NoReturn == NoReturnKind::AnalyzerOnly;
1175 }
1176
1177 unsigned getBlockID() const { return BlockID; }
1178
1179 CFG *getParent() const { return Parent; }
1180
1181 void dump() const;
1182
1183 void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
1184 void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
1185 bool ShowColors) const;
1186
1187 void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
1188 void printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
1189 bool AddQuotes) const;
1190
1191 void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
1192 OS << "BB#" << getBlockID();
1193 }
1194
1195 /// Adds a (potentially unreachable) successor block to the current block.
1196 void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C);
1197
1198 void appendStmt(Stmt *statement, BumpVectorContext &C) {
1199 Elements.push_back(CFGStmt(statement), C);
1200 }
1201
1204 Elements.push_back(CFGConstructor(CE, CC), C);
1205 }
1206
1208 const ConstructionContext *CC,
1210 Elements.push_back(CFGCXXRecordTypedCall(E, CC), C);
1211 }
1212
1215 Elements.push_back(CFGInitializer(initializer), C);
1216 }
1217
1220 Elements.push_back(CFGNewAllocator(NE), C);
1221 }
1222
1223 void appendScopeBegin(const VarDecl *VD, const Stmt *S,
1225 Elements.push_back(CFGScopeBegin(VD, S), C);
1226 }
1227
1228 void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) {
1229 Elements.push_back(CFGScopeEnd(VD, S), C);
1230 }
1231
1233 Elements.push_back(CFGBaseDtor(BS), C);
1234 }
1235
1237 Elements.push_back(CFGMemberDtor(FD), C);
1238 }
1239
1243
1245 Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
1246 }
1247
1249 Elements.push_back(CFGCleanupFunction(VD), C);
1250 }
1251
1253 Elements.push_back(CFGLifetimeEnds(VD, S), C);
1254 }
1255
1257 const ExprWithCleanups *CleanupExpr,
1259 Elements.push_back(CFGFullExprCleanup(BV, CleanupExpr), C);
1260 }
1261
1262 void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) {
1263 Elements.push_back(CFGLoopExit(LoopStmt), C);
1264 }
1265
1267 Elements.push_back(CFGDeleteDtor(RD, DE), C);
1268 }
1269};
1270
1272
1273/// CFGCallback defines methods that should be called when a logical
1274/// operator error is found when building the CFG.
1276public:
1277 CFGCallback() = default;
1278 virtual ~CFGCallback() = default;
1279
1280 virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
1281 virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
1283 bool isAlwaysTrue) {}
1284 virtual void compareBitwiseOr(const BinaryOperator *B) {}
1285};
1286
1287/// Represents a source-level, intra-procedural CFG that represents the
1288/// control-flow of a Stmt. The Stmt can represent an entire function body,
1289/// or a single expression. A CFG will always contain one empty block that
1290/// represents the Exit point of the CFG. A CFG will also contain a designated
1291/// Entry block. The CFG solely represents control-flow; it consists of
1292/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
1293/// was constructed from.
1294class CFG {
1295public:
1296 //===--------------------------------------------------------------------===//
1297 // CFG Construction & Manipulation.
1298 //===--------------------------------------------------------------------===//
1299
1301 // Stmt::lastStmtConstant has the same value as the last Stmt kind,
1302 // so make sure we add one to account for this!
1303 std::bitset<Stmt::lastStmtConstant + 1> alwaysAddMask;
1304
1305 public:
1306 using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>;
1307
1311 bool AddEHEdges = false;
1312 bool AddInitializers = false;
1313 bool AddImplicitDtors = false;
1314 bool AddLifetime = false;
1315 // Add lifetime markers for function parameters. In principle, function
1316 // parameters are constructed and destructed in the caller context but
1317 // analyses could still choose to include these in the callee's CFG to
1318 // represent the lifetime ends of parameters on function exit.
1320 bool AddLoopExit = false;
1321 bool AddTemporaryDtors = false;
1322 bool AddScopes = false;
1332
1333 BuildOptions() = default;
1334
1335 bool alwaysAdd(const Stmt *stmt) const {
1336 return alwaysAddMask[stmt->getStmtClass()];
1337 }
1338
1339 BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) {
1340 alwaysAddMask[stmtClass] = val;
1341 return *this;
1342 }
1343
1345 alwaysAddMask.set();
1346 return *this;
1347 }
1348 };
1349
1350 /// Builds a CFG from an AST.
1351 static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
1352 const BuildOptions &BO);
1353
1354 /// Create a new block in the CFG. The CFG owns the block; the caller should
1355 /// not directly free it.
1357
1358 /// Set the entry block of the CFG. This is typically used only during CFG
1359 /// construction. Most CFG clients expect that the entry block has no
1360 /// predecessors and contains no statements.
1361 void setEntry(CFGBlock *B) { Entry = B; }
1362
1363 /// Set the block used for indirect goto jumps. This is typically used only
1364 /// during CFG construction.
1365 void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
1366
1367 //===--------------------------------------------------------------------===//
1368 // Block Iterators
1369 //===--------------------------------------------------------------------===//
1370
1374 using reverse_iterator = std::reverse_iterator<iterator>;
1375 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1376
1377 CFGBlock & front() { return *Blocks.front(); }
1378 CFGBlock & back() { return *Blocks.back(); }
1379
1380 iterator begin() { return Blocks.begin(); }
1381 iterator end() { return Blocks.end(); }
1382 const_iterator begin() const { return Blocks.begin(); }
1383 const_iterator end() const { return Blocks.end(); }
1384
1385 iterator nodes_begin() { return iterator(Blocks.begin()); }
1386 iterator nodes_end() { return iterator(Blocks.end()); }
1387
1388 llvm::iterator_range<iterator> nodes() { return {begin(), end()}; }
1389 llvm::iterator_range<const_iterator> const_nodes() const {
1390 return {begin(), end()};
1391 }
1392
1393 const_iterator nodes_begin() const { return const_iterator(Blocks.begin()); }
1394 const_iterator nodes_end() const { return const_iterator(Blocks.end()); }
1395
1396 reverse_iterator rbegin() { return Blocks.rbegin(); }
1397 reverse_iterator rend() { return Blocks.rend(); }
1398 const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
1399 const_reverse_iterator rend() const { return Blocks.rend(); }
1400
1401 llvm::iterator_range<reverse_iterator> reverse_nodes() {
1402 return {rbegin(), rend()};
1403 }
1404 llvm::iterator_range<const_reverse_iterator> const_reverse_nodes() const {
1405 return {rbegin(), rend()};
1406 }
1407
1408 CFGBlock & getEntry() { return *Entry; }
1409 const CFGBlock & getEntry() const { return *Entry; }
1410 CFGBlock & getExit() { return *Exit; }
1411 const CFGBlock & getExit() const { return *Exit; }
1412
1413 CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; }
1414 const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; }
1415
1416 using try_block_iterator = std::vector<const CFGBlock *>::const_iterator;
1417 using try_block_range = llvm::iterator_range<try_block_iterator>;
1418
1420 return TryDispatchBlocks.begin();
1421 }
1422
1424 return TryDispatchBlocks.end();
1425 }
1426
1430
1431 void addTryDispatchBlock(const CFGBlock *block) {
1432 TryDispatchBlocks.push_back(block);
1433 }
1434
1435 /// Records a synthetic DeclStmt and the DeclStmt it was constructed from.
1436 ///
1437 /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains
1438 /// multiple decls.
1439 void addSyntheticDeclStmt(const DeclStmt *Synthetic,
1440 const DeclStmt *Source) {
1441 assert(Synthetic->isSingleDecl() && "Can handle single declarations only");
1442 assert(Synthetic != Source && "Don't include original DeclStmts in map");
1443 assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map");
1444 SyntheticDeclStmts[Synthetic] = Source;
1445 }
1446
1448 llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator;
1449 using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>;
1450
1451 /// Iterates over synthetic DeclStmts in the CFG.
1452 ///
1453 /// Each element is a (synthetic statement, source statement) pair.
1454 ///
1455 /// \sa addSyntheticDeclStmt
1457 return SyntheticDeclStmts.begin();
1458 }
1459
1460 /// \sa synthetic_stmt_begin
1462 return SyntheticDeclStmts.end();
1463 }
1464
1465 /// \sa synthetic_stmt_begin
1469
1470 //===--------------------------------------------------------------------===//
1471 // Member templates useful for various batch operations over CFGs.
1472 //===--------------------------------------------------------------------===//
1473
1474 template <typename Callback> void VisitBlockStmts(Callback &O) const {
1475 for (CFGBlock *BB : *this)
1476 for (const CFGElement &Elem : *BB) {
1477 if (std::optional<CFGStmt> stmt = Elem.getAs<CFGStmt>())
1478 O(stmt->getStmt());
1479 }
1480 }
1481
1482 //===--------------------------------------------------------------------===//
1483 // CFG Introspection.
1484 //===--------------------------------------------------------------------===//
1485
1486 /// Returns the total number of BlockIDs allocated (which start at 0).
1487 unsigned getNumBlockIDs() const { return NumBlockIDs; }
1488
1489 /// Return the total number of CFGBlocks within the CFG This is simply a
1490 /// renaming of the getNumBlockIDs(). This is necessary because the dominator
1491 /// implementation needs such an interface.
1492 unsigned size() const { return NumBlockIDs; }
1493
1494 /// Returns true if the CFG has no branches. Usually it boils down to the CFG
1495 /// having exactly three blocks (entry, the actual code, exit), but sometimes
1496 /// more blocks appear due to having control flow that can be fully
1497 /// resolved in compile time.
1498 bool isLinear() const;
1499
1500 //===--------------------------------------------------------------------===//
1501 // CFG Debugging: Pretty-Printing and Visualization.
1502 //===--------------------------------------------------------------------===//
1503
1504 void viewCFG(const LangOptions &LO) const;
1505 void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const;
1506 void dump(const LangOptions &LO, bool ShowColors) const;
1507
1508 //===--------------------------------------------------------------------===//
1509 // Internal: constructors and data.
1510 //===--------------------------------------------------------------------===//
1511
1512 CFG() : Blocks(BlkBVC, 10) {}
1513
1514 llvm::BumpPtrAllocator& getAllocator() {
1515 return BlkBVC.getAllocator();
1516 }
1517
1519 return BlkBVC;
1520 }
1521
1522private:
1523 CFGBlock *Entry = nullptr;
1524 CFGBlock *Exit = nullptr;
1525
1526 // Special block to contain collective dispatch for indirect gotos
1527 CFGBlock* IndirectGotoBlock = nullptr;
1528
1529 unsigned NumBlockIDs = 0;
1530
1531 BumpVectorContext BlkBVC;
1532
1533 CFGBlockListTy Blocks;
1534
1535 /// C++ 'try' statements are modeled with an indirect dispatch block.
1536 /// This is the collection of such blocks present in the CFG.
1537 std::vector<const CFGBlock *> TryDispatchBlocks;
1538
1539 /// Collects DeclStmts synthesized for this CFG and maps each one back to its
1540 /// source DeclStmt.
1541 llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
1542};
1543
1544Expr *extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE);
1545
1546//===----------------------------------------------------------------------===//
1547// GraphTraits specializations for CFG basic block graphs (source-level CFGs)
1548//===----------------------------------------------------------------------===//
1549
1550namespace detail {
1551// The GraphTraits below present a CFGBlock's successors and predecessors as
1552// plain CFGBlock *, so generic graph algorithms need not know about
1553// AdjacentBlock. AB_Unreachable edges, whose reachable target is null, are kept
1554// in the CFG to preserve terminator successor positions but are not real
1555// control-flow edges and are skipped here.
1557 bool operator()(const CFGBlock::AdjacentBlock &AB) const {
1558 return AB.getReachableBlock() != nullptr;
1559 }
1560};
1561template <typename BlockT> struct CFGBlockEdgeTarget {
1562 BlockT *operator()(const CFGBlock::AdjacentBlock &AB) const {
1563 return AB.getReachableBlock();
1564 }
1565};
1566
1567// A GraphTraits child iterator over BlockT: each AdjacentBlock edge projected
1568// to its reachable target, with unreachable (null) edges skipped.
1569template <typename IterT, typename BlockT>
1571 llvm::mapped_iterator<llvm::filter_iterator<IterT, CFGBlockReachableEdge>,
1573
1574template <typename BlockT, typename RangeT>
1575auto cfgReachableChildren(RangeT Edges) {
1576 return llvm::map_range(
1577 llvm::make_filter_range(Edges, CFGBlockReachableEdge()),
1579}
1580} // namespace detail
1581} // namespace clang
1582
1583namespace llvm {
1584
1585/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
1586/// CFGTerminator to a specific Stmt class.
1587template <> struct simplify_type< ::clang::CFGTerminator> {
1589
1591 return Val.getStmt();
1592 }
1593};
1594
1595// Traits for: CFGBlock
1596
1597// CFGBlocks are numbered densely from 0 by their BlockID, so dominator tree
1598// construction can index by number instead of using a DenseMap.
1599template <> struct GraphTraits<clang::CFGBlock *> {
1604
1605 static NodeRef getEntryNode(clang::CFGBlock *BB) { return BB; }
1614
1615 static unsigned getNumber(const clang::CFGBlock *BB) {
1616 return BB->getBlockID();
1617 }
1618};
1619
1620static_assert(GraphHasNodeNumbers<clang::CFGBlock *>,
1621 "GraphTraits getNumber() not detected");
1622
1623template <> struct GraphTraits<const clang::CFGBlock *> {
1624 using NodeRef = const clang::CFGBlock *;
1627
1628 static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; }
1639
1640 static unsigned getNumber(const clang::CFGBlock *BB) {
1641 return BB->getBlockID();
1642 }
1643};
1644
1645static_assert(GraphHasNodeNumbers<const clang::CFGBlock *>,
1646 "GraphTraits getNumber() not detected");
1647
1648template <> struct GraphTraits<Inverse<clang::CFGBlock *>> {
1653
1654 static NodeRef getEntryNode(Inverse<clang::CFGBlock *> G) { return G.Graph; }
1663
1664 static unsigned getNumber(const clang::CFGBlock *BB) {
1665 return BB->getBlockID();
1666 }
1667};
1668
1669static_assert(GraphHasNodeNumbers<Inverse<clang::CFGBlock *>>,
1670 "GraphTraits getNumber() not detected");
1671
1672template <> struct GraphTraits<Inverse<const clang::CFGBlock *>> {
1673 using NodeRef = const clang::CFGBlock *;
1676
1677 static NodeRef getEntryNode(Inverse<const clang::CFGBlock *> G) {
1678 return G.Graph;
1679 }
1690
1691 static unsigned getNumber(const clang::CFGBlock *BB) {
1692 return BB->getBlockID();
1693 }
1694};
1695
1696static_assert(GraphHasNodeNumbers<Inverse<const clang::CFGBlock *>>,
1697 "GraphTraits getNumber() not detected");
1698
1699// Traits for: CFG
1700
1701template <>
1702struct GraphTraits<::clang::CFG *> : public GraphTraits<clang::CFGBlock *> {
1704
1705 static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); }
1708 static unsigned size(::clang::CFG* F) { return F->size(); }
1709
1710 static unsigned getMaxNumber(const ::clang::CFG *F) {
1711 return F->getNumBlockIDs();
1712 }
1713 // Block numbers are fixed when the CFG is built and never change afterwards.
1714 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1715};
1716
1717template <>
1718struct GraphTraits<const ::clang::CFG *>
1719 : public GraphTraits<const clang::CFGBlock *> {
1721
1722 static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); }
1723
1724 static nodes_iterator nodes_begin( const ::clang::CFG* F) {
1725 return F->nodes_begin();
1726 }
1727
1728 static nodes_iterator nodes_end( const ::clang::CFG* F) {
1729 return F->nodes_end();
1730 }
1731
1732 static unsigned size(const ::clang::CFG* F) {
1733 return F->size();
1734 }
1735
1736 static unsigned getMaxNumber(const ::clang::CFG *F) {
1737 return F->getNumBlockIDs();
1738 }
1739 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1740};
1741
1742template <>
1743struct GraphTraits<Inverse<::clang::CFG *>>
1744 : public GraphTraits<Inverse<clang::CFGBlock *>> {
1746
1747 static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); }
1749 static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
1750
1751 static unsigned getMaxNumber(const ::clang::CFG *F) {
1752 return F->getNumBlockIDs();
1753 }
1754 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1755};
1756
1757template <>
1758struct GraphTraits<Inverse<const ::clang::CFG *>>
1759 : public GraphTraits<Inverse<const clang::CFGBlock *>> {
1761
1762 static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); }
1763
1764 static nodes_iterator nodes_begin(const ::clang::CFG* F) {
1765 return F->nodes_begin();
1766 }
1767
1768 static nodes_iterator nodes_end(const ::clang::CFG* F) {
1769 return F->nodes_end();
1770 }
1771
1772 static unsigned getMaxNumber(const ::clang::CFG *F) {
1773 return F->getNumBlockIDs();
1774 }
1775 static unsigned getNumberEpoch(const ::clang::CFG *F) { return 0; }
1776};
1777
1778} // namespace llvm
1779
1780#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:4107
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:464
const VarDecl * getVarDecl() const
Definition CFG.h:469
const Stmt * getTriggerStmt() const
Definition CFG.h:474
friend class CFGElement
Definition CFG.h:479
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
Definition CFG.h:466
Represents C++ object destructor implicitly generated for base object in destructor.
Definition CFG.h:515
friend class CFGElement
Definition CFG.h:525
CFGBaseDtor(const CXXBaseSpecifier *base)
Definition CFG.h:517
const CXXBaseSpecifier * getBaseSpecifier() const
Definition CFG.h:520
This class represents a potential adjacent block in the CFG.
Definition CFG.h:871
CFGBlock & operator*() const
Definition CFG.h:905
AdjacentBlock(CFGBlock *B, bool IsReachable)
Construct an AdjacentBlock with a possibly unreachable block.
Definition CFG.cpp:5601
CFGBlock * operator->() const
Definition CFG.h:909
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
Definition CFG.h:890
bool isReachable() const
Definition CFG.h:913
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
Definition CFG.h:895
unsigned IgnoreDefaultsWithCoveredEnums
Definition CFG.h:1075
FilteredCFGBlockIterator & operator++()
Definition CFG.h:1102
const CFGBlock * operator*() const
Definition CFG.h:1107
FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, const FilterOptions &f)
Definition CFG.h:1092
Represents a single basic block in a source-level CFG.
Definition CFG.h:651
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
Definition CFG.h:1244
void printTerminator(raw_ostream &OS, const LangOptions &LO) const
printTerminator - A simple pretty printer of the terminator of a CFGBlock.
Definition CFG.cpp:6425
ElementList::reverse_iterator reverse_iterator
Definition CFG.h:957
ElementList::iterator iterator
Definition CFG.h:955
void setLoopTarget(const Stmt *loopTarget)
Definition CFG.h:1133
bool isInevitablySinking() const
Returns true if the block would eventually end with a sink (a noreturn node).
Definition CFG.cpp:6469
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const
Definition CFG.h:1121
pred_iterator pred_end()
Definition CFG.h:1028
size_t getIndexInCFG() const
Definition CFG.cpp:6401
succ_iterator succ_end()
Definition CFG.h:1046
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
Definition CFG.h:1223
AdjacentBlocks::reverse_iterator pred_reverse_iterator
Definition CFG.h:1015
const_reverse_iterator rend() const
Definition CFG.h:973
CFGElement operator[](size_t i) const
Definition CFG.h:1010
llvm::iterator_range< pred_iterator > pred_range
Definition CFG.h:1017
const_reverse_ref_iterator_range rrefs() const
Definition CFG.h:1003
llvm::iterator_range< const_succ_iterator > succ_const_range
Definition CFG.h:1025
static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, const CFGBlock *Dst)
Definition CFG.cpp:5622
ElementRefIterator< false, false > ref_iterator
Definition CFG.h:978
ref_iterator ref_begin()
Definition CFG.h:990
reverse_iterator rbegin()
Definition CFG.h:970
bool hasOnlyAnalyzerNoReturnElement() const
Returns true if the block ends in an 'analyzer_noreturn' call (as opposed to a real 'noreturn' one).
Definition CFG.h:1173
void setTerminator(CFGTerminator Term)
Definition CFG.h:1131
void printAsOperand(raw_ostream &OS, bool)
Definition CFG.h:1191
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
Definition CFG.h:1236
filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const
Definition CFG.h:1125
llvm::iterator_range< reverse_ref_iterator > reverse_ref_iterator_range
Definition CFG.h:984
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)
Definition CFG.h:1252
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:6417
ElementList::const_iterator const_iterator
Definition CFG.h:956
const Stmt * getLabel() const
Definition CFG.h:1163
reverse_iterator rend()
Definition CFG.h:971
AdjacentBlocks::iterator pred_iterator
Definition CFG.h:1013
pred_reverse_iterator pred_rend()
Definition CFG.h:1033
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:1167
CFGElement back() const
Definition CFG.h:963
ElementList::const_reverse_iterator const_reverse_iterator
Definition CFG.h:958
succ_reverse_iterator succ_rend()
Definition CFG.h:1051
ElementRefIterator< true, false > reverse_ref_iterator
Definition CFG.h:983
CFGElement front() const
Definition CFG.h:962
const_reverse_ref_iterator rref_end() const
Definition CFG.h:998
unsigned size() const
Definition CFG.h:1007
const_succ_iterator succ_begin() const
Definition CFG.h:1047
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
Definition CFG.h:1266
void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
Definition CFG.h:1228
const_pred_iterator pred_end() const
Definition CFG.h:1030
const_iterator begin() const
Definition CFG.h:967
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
Definition CFG.h:1213
unsigned BlockID
A numerical ID assigned to a CFGBlock during construction of the CFG.
Definition CFG.h:863
iterator begin()
Definition CFG.h:965
FilteredCFGBlockIterator< const_pred_iterator, true > filtered_pred_iterator
Definition CFG.h:1115
const_pred_reverse_iterator pred_rbegin() const
Definition CFG.h:1034
succ_reverse_iterator succ_rbegin()
Definition CFG.h:1050
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const
printTerminatorJson - Pretty-prints the terminator in JSON format.
Definition CFG.cpp:6432
llvm::iterator_range< ref_iterator > ref_iterator_range
Definition CFG.h:979
succ_range succs()
Definition CFG.h:1055
void dump() const
Definition CFG.cpp:6411
bool empty() const
Definition CFG.h:1008
AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator
Definition CFG.h:1023
ref_iterator_range refs()
Definition CFG.h:1000
ElementRefIterator< false, true > const_ref_iterator
Definition CFG.h:980
ElementRefImpl< true > ConstCFGElementRef
Definition CFG.h:976
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
Definition CFG.h:1218
CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
Definition CFG.h:950
Stmt * Label
An (optional) label that prefixes the executable statements in the block.
Definition CFG.h:851
const_ref_iterator ref_begin() const
Definition CFG.h:992
Stmt * getLabel()
Definition CFG.h:1162
CFGTerminator getTerminator() const
Definition CFG.h:1145
succ_iterator succ_begin()
Definition CFG.h:1045
Stmt * getTerminatorStmt()
Definition CFG.h:1147
const_succ_reverse_iterator succ_rend() const
Definition CFG.h:1053
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
Definition CFG.h:1240
void setHasNoReturnElement(bool AnalyzerOnly=false)
Mark the block as ending in a noreturn element.
Definition CFG.h:1135
const Stmt * getLoopTarget() const
Definition CFG.h:1160
AdjacentBlocks::const_iterator const_pred_iterator
Definition CFG.h:1014
succ_const_range succs() const
Definition CFG.h:1059
unsigned pred_size() const
Definition CFG.h:1066
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
Definition CFG.h:1232
AdjacentBlocks::iterator succ_iterator
Definition CFG.h:1020
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
Definition CFG.h:1207
FilteredCFGBlockIterator< const_succ_iterator, false > filtered_succ_iterator
Definition CFG.h:1118
pred_const_range preds() const
Definition CFG.h:1041
ElementList Elements
The set of statements in the basic block.
Definition CFG.h:846
llvm::iterator_range< const_reverse_ref_iterator > const_reverse_ref_iterator_range
Definition CFG.h:987
const_reverse_iterator rbegin() const
Definition CFG.h:972
ElementRefImpl< false > CFGElementRef
Definition CFG.h:975
ref_iterator ref_end()
Definition CFG.h:991
pred_reverse_iterator pred_rbegin()
Definition CFG.h:1032
const Stmt * getTerminatorCondition(bool StripParens=true) const
Definition CFG.cpp:6534
ElementRefIterator< true, true > const_reverse_ref_iterator
Definition CFG.h:986
pred_iterator pred_begin()
Definition CFG.h:1027
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:860
reverse_ref_iterator rref_begin()
Definition CFG.h:995
iterator end()
Definition CFG.h:966
CFG * getParent() const
Definition CFG.h:1179
void appendCleanupFunction(const VarDecl *VD, BumpVectorContext &C)
Definition CFG.h:1248
pred_range preds()
Definition CFG.h:1037
reverse_ref_iterator rref_end()
Definition CFG.h:996
const Stmt * getTerminatorStmt() const
Definition CFG.h:1148
const_ref_iterator_range refs() const
Definition CFG.h:1001
const_iterator end() const
Definition CFG.h:968
const_ref_iterator ref_end() const
Definition CFG.h:993
void setLabel(Stmt *Statement)
Definition CFG.h:1132
unsigned getBlockID() const
Definition CFG.h:1177
const_succ_reverse_iterator succ_rbegin() const
Definition CFG.h:1052
void appendStmt(Stmt *statement, BumpVectorContext &C)
Definition CFG.h:1198
void appendFullExprCleanup(BumpVector< const MaterializeTemporaryExpr * > *BV, const ExprWithCleanups *CleanupExpr, BumpVectorContext &C)
Definition CFG.h:1256
llvm::iterator_range< const_ref_iterator > const_ref_iterator_range
Definition CFG.h:981
const_pred_iterator pred_begin() const
Definition CFG.h:1029
const_succ_iterator succ_end() const
Definition CFG.h:1048
const Expr * getLastCondition() const
Definition CFG.cpp:6506
const_pred_reverse_iterator pred_rend() const
Definition CFG.h:1035
void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, BumpVectorContext &C)
Definition CFG.h:1202
AdjacentBlocks::reverse_iterator succ_reverse_iterator
Definition CFG.h:1022
AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator
Definition CFG.h:1016
void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C)
Adds a (potentially unreachable) successor block to the current block.
Definition CFG.cpp:5611
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
Definition CFG.h:1262
AdjacentBlocks::const_iterator const_succ_iterator
Definition CFG.h:1021
reverse_ref_iterator_range rrefs()
Definition CFG.h:1002
bool pred_empty() const
Definition CFG.h:1067
CFGTerminator Terminator
The terminator for a basic block that indicates the type of control-flow that occurs between a block ...
Definition CFG.h:855
llvm::iterator_range< succ_iterator > succ_range
Definition CFG.h:1024
unsigned succ_size() const
Definition CFG.h:1063
bool succ_empty() const
Definition CFG.h:1064
const_reverse_ref_iterator rref_begin() const
Definition CFG.h:997
llvm::iterator_range< const_pred_iterator > pred_const_range
Definition CFG.h:1018
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:1275
CFGCallback()=default
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
Definition CFG.h:1282
virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition CFG.h:1280
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
Definition CFG.h:1281
virtual void compareBitwiseOr(const BinaryOperator *B)
Definition CFG.h:1284
virtual ~CFGCallback()=default
CFGCleanupFunction(const VarDecl *VD)
Definition CFG.h:438
const VarDecl * getVarDecl() const
Definition CFG.h:443
const FunctionDecl * getFunctionDecl() const
Returns the function to be called when cleaning up the var decl.
Definition CFG.h:448
friend class CFGElement
Definition CFG.h:454
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:489
CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
Definition CFG.h:491
friend class CFGElement
Definition CFG.h:504
const CXXDeleteExpr * getDeleteExpr() const
Definition CFG.h:499
const CXXRecordDecl * getCXXRecordDecl() const
Definition CFG.h:494
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:5999
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:5523
CFGImplicitDtor(Kind kind, const void *data1, const void *data2=nullptr)
Definition CFG.h:418
friend class CFGElement
Definition CFG.h:427
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:536
friend class CFGElement
Definition CFG.h:546
const FieldDecl * getFieldDecl() const
Definition CFG.h:541
CFGMemberDtor(const FieldDecl *field)
Definition CFG.h:538
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:557
const CXXBindTemporaryExpr * getBindTemporaryExpr() const
Definition CFG.h:562
CFGTemporaryDtor(const CXXBindTemporaryExpr *expr)
Definition CFG.h:559
friend class CFGElement
Definition CFG.h:567
Represents CFGBlock terminator statement.
Definition CFG.h:578
Stmt * getStmt()
Definition CFG.h:610
bool isVirtualBaseBranch() const
Definition CFG.h:620
bool isTemporaryDtorsBranch() const
Definition CFG.h:617
bool isValid() const
Definition CFG.h:609
bool isStmtBranch() const
Definition CFG.h:614
Kind getKind() const
Definition CFG.h:612
CFGTerminator(Stmt *S, Kind K=StmtBranch)
Definition CFG.h:607
const Stmt * getStmt() const
Definition CFG.h:611
@ TemporaryDtorsBranch
A branch in control flow of destructors of temporaries.
Definition CFG.h:587
@ VirtualBaseBranch
A shortcut around virtual base initializers.
Definition CFG.h:591
@ StmtBranch
A branch that corresponds to a statement in the code, such as an if-statement.
Definition CFG.h:583
@ NumKindsMinusOne
Number of different kinds, for assertions.
Definition CFG.h:596
bool PruneTriviallyFalseEdges
Definition CFG.h:1310
bool OmitImplicitValueInitializers
Definition CFG.h:1330
ForcedBlkExprs ** forcedBlkExprs
Definition CFG.h:1308
bool AddCXXDefaultInitExprInAggregates
Definition CFG.h:1326
bool AddCXXDefaultInitExprInCtors
Definition CFG.h:1325
BuildOptions & setAllAlwaysAdd()
Definition CFG.h:1344
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
Definition CFG.h:1339
bool AssumeReachableDefaultInSwitchStatements
Definition CFG.h:1331
CFGCallback * Observer
Definition CFG.h:1309
bool alwaysAdd(const Stmt *stmt) const
Definition CFG.h:1335
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
Definition CFG.h:1306
bool MarkElidedCXXConstructors
Definition CFG.h:1328
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1294
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Definition CFG.h:1492
llvm::iterator_range< synthetic_stmt_iterator > synthetic_stmt_range
Definition CFG.h:1449
CFGBlockListTy::const_iterator const_iterator
Definition CFG.h:1373
const_iterator nodes_end() const
Definition CFG.h:1394
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:6380
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition CFG.h:1375
try_block_range try_blocks() const
Definition CFG.h:1427
iterator end()
Definition CFG.h:1381
bool isLinear() const
Returns true if the CFG has no branches.
Definition CFG.cpp:5477
synthetic_stmt_range synthetic_stmts() const
Definition CFG.h:1466
void VisitBlockStmts(Callback &O) const
Definition CFG.h:1474
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:5470
llvm::BumpPtrAllocator & getAllocator()
Definition CFG.h:1514
std::reverse_iterator< iterator > reverse_iterator
Definition CFG.h:1374
CFGBlockListTy::iterator iterator
Definition CFG.h:1372
const_reverse_iterator rbegin() const
Definition CFG.h:1398
const_iterator end() const
Definition CFG.h:1383
CFGBlock * createBlock()
Create a new block in the CFG.
Definition CFG.cpp:5454
void addSyntheticDeclStmt(const DeclStmt *Synthetic, const DeclStmt *Source)
Records a synthetic DeclStmt and the DeclStmt it was constructed from.
Definition CFG.h:1439
const CFGBlock * getIndirectGotoBlock() const
Definition CFG.h:1414
llvm::iterator_range< try_block_iterator > try_block_range
Definition CFG.h:1417
const_iterator begin() const
Definition CFG.h:1382
CFGBlock & getExit()
Definition CFG.h:1410
iterator begin()
Definition CFG.h:1380
void setIndirectGotoBlock(CFGBlock *B)
Set the block used for indirect goto jumps.
Definition CFG.h:1365
void addTryDispatchBlock(const CFGBlock *block)
Definition CFG.h:1431
try_block_iterator try_blocks_end() const
Definition CFG.h:1423
synthetic_stmt_iterator synthetic_stmt_end() const
Definition CFG.h:1461
void setEntry(CFGBlock *B)
Set the entry block of the CFG.
Definition CFG.h:1361
CFGBlock & getEntry()
Definition CFG.h:1408
llvm::iterator_range< const_iterator > const_nodes() const
Definition CFG.h:1389
const CFGBlock & getEntry() const
Definition CFG.h:1409
CFGBlock * getIndirectGotoBlock()
Definition CFG.h:1413
llvm::iterator_range< reverse_iterator > reverse_nodes()
Definition CFG.h:1401
std::vector< const CFGBlock * >::const_iterator try_block_iterator
Definition CFG.h:1416
CFGBlock & front()
Definition CFG.h:1377
const CFGBlock & getExit() const
Definition CFG.h:1411
llvm::iterator_range< const_reverse_iterator > const_reverse_nodes() const
Definition CFG.h:1404
const_reverse_iterator rend() const
Definition CFG.h:1399
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
Definition CFG.cpp:6375
iterator nodes_begin()
Definition CFG.h:1385
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1487
const_iterator nodes_begin() const
Definition CFG.h:1393
void viewCFG(const LangOptions &LO) const
Definition CFG.cpp:6605
try_block_iterator try_blocks_begin() const
Definition CFG.h:1419
BumpVector< CFGBlock * > CFGBlockListTy
Definition CFG.h:1371
iterator nodes_end()
Definition CFG.h:1386
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
Definition CFG.h:1456
reverse_iterator rbegin()
Definition CFG.h:1396
reverse_iterator rend()
Definition CFG.h:1397
CFGBlock & back()
Definition CFG.h:1378
llvm::iterator_range< iterator > nodes()
Definition CFG.h:1388
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
Definition CFG.h:1447
BumpVectorContext & getBumpVectorContext()
Definition CFG.h:1518
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:2410
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:2915
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:1642
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1655
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:582
bool hasAttr() const
Definition DeclBase.h:586
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:114
bool isGLValue() const
Definition Expr.h:289
QualType getType() const
Definition Expr.h:146
Represents a member of a struct/union/class.
Definition Decl.h:3311
Represents a function declaration or definition.
Definition Decl.h:2071
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:8630
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:934
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:1570
auto cfgReachableChildren(RangeT Edges)
Definition CFG.h:1575
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CFGBlock::ConstCFGElementRef ConstCFGElementRef
Definition CFG.h:1271
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:1787
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
BlockT * operator()(const CFGBlock::AdjacentBlock &AB) const
Definition CFG.h:1562
bool operator()(const CFGBlock::AdjacentBlock &AB) const
Definition CFG.h:1557
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1664
clang::detail::CFGReachableChildIterator< clang::CFGBlock::pred_iterator, clang::CFGBlock > ChildIteratorType
Definition CFG.h:1650
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1659
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1655
static NodeRef getEntryNode(Inverse< clang::CFGBlock * > G)
Definition CFG.h:1654
static NodeRef getEntryNode(const ::clang::CFG *F)
Definition CFG.h:1762
static nodes_iterator nodes_begin(const ::clang::CFG *F)
Definition CFG.h:1764
static nodes_iterator nodes_end(const ::clang::CFG *F)
Definition CFG.h:1768
::clang::CFG::const_iterator nodes_iterator
Definition CFG.h:1760
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1775
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1772
clang::detail::CFGReachableChildIterator< clang::CFGBlock::const_pred_iterator, const clang::CFGBlock > ChildIteratorType
Definition CFG.h:1674
static NodeRef getEntryNode(Inverse< const clang::CFGBlock * > G)
Definition CFG.h:1677
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1691
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1680
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1685
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1754
static nodes_iterator nodes_end(::clang::CFG *F)
Definition CFG.h:1749
::clang::CFG::iterator nodes_iterator
Definition CFG.h:1745
static NodeRef getEntryNode(::clang::CFG *F)
Definition CFG.h:1747
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1751
static nodes_iterator nodes_begin(::clang::CFG *F)
Definition CFG.h:1748
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1610
static NodeRef getEntryNode(clang::CFGBlock *BB)
Definition CFG.h:1605
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1606
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1615
clang::detail::CFGReachableChildIterator< clang::CFGBlock::succ_iterator, clang::CFGBlock > ChildIteratorType
Definition CFG.h:1601
::clang::CFG::const_iterator nodes_iterator
Definition CFG.h:1720
static nodes_iterator nodes_begin(const ::clang::CFG *F)
Definition CFG.h:1724
static unsigned size(const ::clang::CFG *F)
Definition CFG.h:1732
static nodes_iterator nodes_end(const ::clang::CFG *F)
Definition CFG.h:1728
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1739
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1736
static NodeRef getEntryNode(const ::clang::CFG *F)
Definition CFG.h:1722
static NodeRef getEntryNode(const clang::CFGBlock *BB)
Definition CFG.h:1628
static unsigned getNumber(const clang::CFGBlock *BB)
Definition CFG.h:1640
clang::detail::CFGReachableChildIterator< clang::CFGBlock::const_succ_iterator, const clang::CFGBlock > ChildIteratorType
Definition CFG.h:1625
static ChildIteratorType child_begin(NodeRef N)
Definition CFG.h:1629
const clang::CFGBlock * NodeRef
Definition CFG.h:1624
static ChildIteratorType child_end(NodeRef N)
Definition CFG.h:1634
static nodes_iterator nodes_end(::clang::CFG *F)
Definition CFG.h:1707
static unsigned size(::clang::CFG *F)
Definition CFG.h:1708
static unsigned getMaxNumber(const ::clang::CFG *F)
Definition CFG.h:1710
::clang::CFG::iterator nodes_iterator
Definition CFG.h:1703
static NodeRef getEntryNode(::clang::CFG *F)
Definition CFG.h:1705
static nodes_iterator nodes_begin(::clang::CFG *F)
Definition CFG.h:1706
static unsigned getNumberEpoch(const ::clang::CFG *F)
Definition CFG.h:1714
static SimpleType getSimplifiedValue(::clang::CFGTerminator Val)
Definition CFG.h:1590