diff options
Diffstat (limited to 'include/clang/Analysis/CFG.h')
-rw-r--r-- | include/clang/Analysis/CFG.h | 358 |
1 files changed, 204 insertions, 154 deletions
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 97639bbfade2..cfedb2aa8ed5 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -1,4 +1,4 @@ -//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===// +//===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,38 +17,38 @@ #include "clang/AST/Stmt.h" #include "clang/Analysis/Support/BumpVector.h" -#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include <bitset> #include <cassert> +#include <cstddef> #include <iterator> #include <memory> +#include <vector> namespace clang { - class CXXDestructorDecl; - class Decl; - class Stmt; - class Expr; - class FieldDecl; - class VarDecl; - class CXXCtorInitializer; - class CXXBaseSpecifier; - class CXXBindTemporaryExpr; - class CFG; - class PrinterHelper; - class LangOptions; - class ASTContext; - class CXXRecordDecl; - class CXXDeleteExpr; - class CXXNewExpr; - class BinaryOperator; + +class ASTContext; +class BinaryOperator; +class CFG; +class CXXBaseSpecifier; +class CXXBindTemporaryExpr; +class CXXCtorInitializer; +class CXXDeleteExpr; +class CXXDestructorDecl; +class CXXNewExpr; +class CXXRecordDecl; +class Decl; +class FieldDecl; +class LangOptions; +class VarDecl; /// CFGElement - Represents a top-level expression in a basic block. class CFGElement { @@ -59,6 +59,7 @@ public: Initializer, NewAllocator, LifetimeEnds, + LoopExit, // dtor kind AutomaticObjectDtor, DeleteDtor, @@ -75,14 +76,14 @@ protected: llvm::PointerIntPair<void *, 2> Data2; CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) - : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), - Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { + : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { assert(getKind() == kind); } - CFGElement() {} -public: + CFGElement() = default; +public: /// \brief Convert to the specified CFGElement type, asserting that this /// CFGElement is of the desired type. template<typename T> @@ -124,7 +125,9 @@ public: private: friend class CFGElement; - CFGStmt() {} + + CFGStmt() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Statement; } @@ -143,7 +146,9 @@ public: private: friend class CFGElement; - CFGInitializer() {} + + CFGInitializer() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Initializer; } @@ -162,12 +167,38 @@ public: private: friend class CFGElement; - CFGNewAllocator() {} + + CFGNewAllocator() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == NewAllocator; } }; +/// Represents the point where a loop ends. +/// This element is is only produced when building the CFG for the static +/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag. +/// +/// Note: a loop exit element can be reached even when the loop body was never +/// entered. +class CFGLoopExit : public CFGElement { +public: + explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {} + + const Stmt *getLoopStmt() const { + return static_cast<Stmt *>(Data1.getPointer()); + } + +private: + friend class CFGElement; + + CFGLoopExit() = default; + + static bool isKind(const CFGElement &elem) { + return elem.getKind() == LoopExit; + } +}; + /// Represents the point where the lifetime of an automatic object ends class CFGLifetimeEnds : public CFGElement { public: @@ -184,7 +215,9 @@ public: private: friend class CFGElement; - CFGLifetimeEnds() {} + + CFGLifetimeEnds() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == LifetimeEnds; } @@ -194,7 +227,8 @@ private: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor() {} + CFGImplicitDtor() = default; + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr) : CFGElement(kind, data1, data2) { assert(kind >= DTOR_BEGIN && kind <= DTOR_END); @@ -206,6 +240,7 @@ public: private: friend class CFGElement; + static bool isKind(const CFGElement &E) { Kind kind = E.getKind(); return kind >= DTOR_BEGIN && kind <= DTOR_END; @@ -231,7 +266,9 @@ public: private: friend class CFGElement; - CFGAutomaticObjDtor() {} + + CFGAutomaticObjDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == AutomaticObjectDtor; } @@ -255,7 +292,9 @@ public: private: friend class CFGElement; - CFGDeleteDtor() {} + + CFGDeleteDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == DeleteDtor; } @@ -274,7 +313,9 @@ public: private: friend class CFGElement; - CFGBaseDtor() {} + + CFGBaseDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == BaseDtor; } @@ -293,7 +334,9 @@ public: private: friend class CFGElement; - CFGMemberDtor() {} + + CFGMemberDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == MemberDtor; } @@ -312,7 +355,9 @@ public: private: friend class CFGElement; - CFGTemporaryDtor() {} + + CFGTemporaryDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == TemporaryDtor; } @@ -326,8 +371,9 @@ private: /// of matching full expression. class CFGTerminator { llvm::PointerIntPair<Stmt *, 1> Data; + public: - CFGTerminator() {} + CFGTerminator() = default; CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false) : Data(S, TemporaryDtorsBranch) {} @@ -373,21 +419,23 @@ public: /// &&, || expression that uses result of && or ||, RHS /// /// But note that any of that may be NULL in case of optimized-out edges. -/// class CFGBlock { class ElementList { - typedef BumpVector<CFGElement> ImplTy; + using ImplTy = BumpVector<CFGElement>; + ImplTy Impl; + public: ElementList(BumpVectorContext &C) : Impl(C, 4) {} - typedef std::reverse_iterator<ImplTy::iterator> iterator; - typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator; - typedef ImplTy::iterator reverse_iterator; - typedef ImplTy::const_iterator const_reverse_iterator; - typedef ImplTy::const_reference const_reference; + using iterator = std::reverse_iterator<ImplTy::iterator>; + using const_iterator = std::reverse_iterator<ImplTy::const_iterator>; + using reverse_iterator = ImplTy::iterator; + using const_reverse_iterator = ImplTy::const_iterator; + using const_reference = ImplTy::const_reference; void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } + reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, BumpVectorContext &C) { return Impl.insert(I, Cnt, E, C); @@ -405,10 +453,10 @@ class CFGBlock { const_reverse_iterator rbegin() const { return Impl.begin(); } const_reverse_iterator rend() const { return Impl.end(); } - CFGElement operator[](size_t i) const { - assert(i < Impl.size()); - return Impl[Impl.size() - 1 - i]; - } + CFGElement operator[](size_t i) const { + assert(i < Impl.size()); + return Impl[Impl.size() - 1 - i]; + } size_t size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } @@ -420,7 +468,7 @@ class CFGBlock { /// Label - An (optional) label that prefixes the executable /// statements in the block. When this variable is non-NULL, it is /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt. - Stmt *Label; + Stmt *Label = nullptr; /// Terminator - The terminator for a basic block that /// indicates the type of control-flow that occurs between a block @@ -430,7 +478,7 @@ class CFGBlock { /// LoopTarget - Some blocks are used to represent the "loop edge" to /// the start of a loop from within the loop body. This Stmt* will be /// refer to the loop statement for such blocks (and be null otherwise). - const Stmt *LoopTarget; + const Stmt *LoopTarget = nullptr; /// BlockID - A numerical ID assigned to a CFGBlock during construction /// of the CFG. @@ -450,7 +498,7 @@ public: }; CFGBlock *ReachableBlock; - llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock; + llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock; public: /// Construct an AdjacentBlock with a possibly unreachable block. @@ -493,7 +541,7 @@ public: private: /// Predecessors/Successors - Keep track of the predecessor / successor /// CFG blocks. - typedef BumpVector<AdjacentBlock> AdjacentBlocks; + using AdjacentBlocks = BumpVector<AdjacentBlock>; AdjacentBlocks Preds; AdjacentBlocks Succs; @@ -513,15 +561,14 @@ private: public: explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) - : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr), - BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false), - Parent(parent) {} + : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1), + Succs(C, 1), HasNoReturnElement(false), Parent(parent) {} // Statement iterators - typedef ElementList::iterator iterator; - typedef ElementList::const_iterator const_iterator; - typedef ElementList::reverse_iterator reverse_iterator; - typedef ElementList::const_reverse_iterator const_reverse_iterator; + using iterator = ElementList::iterator; + using const_iterator = ElementList::const_iterator; + using reverse_iterator = ElementList::reverse_iterator; + using const_reverse_iterator = ElementList::const_reverse_iterator; CFGElement front() const { return Elements.front(); } CFGElement back() const { return Elements.back(); } @@ -542,19 +589,19 @@ public: CFGElement operator[](size_t i) const { return Elements[i]; } // CFG iterators - typedef AdjacentBlocks::iterator pred_iterator; - typedef AdjacentBlocks::const_iterator const_pred_iterator; - typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator; - typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator; - typedef llvm::iterator_range<pred_iterator> pred_range; - typedef llvm::iterator_range<const_pred_iterator> pred_const_range; - - typedef AdjacentBlocks::iterator succ_iterator; - typedef AdjacentBlocks::const_iterator const_succ_iterator; - typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator; - typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator; - typedef llvm::iterator_range<succ_iterator> succ_range; - typedef llvm::iterator_range<const_succ_iterator> succ_const_range; + using pred_iterator = AdjacentBlocks::iterator; + using const_pred_iterator = AdjacentBlocks::const_iterator; + using pred_reverse_iterator = AdjacentBlocks::reverse_iterator; + using const_pred_reverse_iterator = AdjacentBlocks::const_reverse_iterator; + using pred_range = llvm::iterator_range<pred_iterator>; + using pred_const_range = llvm::iterator_range<const_pred_iterator>; + + using succ_iterator = AdjacentBlocks::iterator; + using const_succ_iterator = AdjacentBlocks::const_iterator; + using succ_reverse_iterator = AdjacentBlocks::reverse_iterator; + using const_succ_reverse_iterator = AdjacentBlocks::const_reverse_iterator; + using succ_range = llvm::iterator_range<succ_iterator>; + using succ_const_range = llvm::iterator_range<const_succ_iterator>; pred_iterator pred_begin() { return Preds.begin(); } pred_iterator pred_end() { return Preds.end(); } @@ -566,10 +613,11 @@ public: const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } - pred_range preds() { + pred_range preds() { return pred_range(pred_begin(), pred_end()); } - pred_const_range preds() const { + + pred_const_range preds() const { return pred_const_range(pred_begin(), pred_end()); } @@ -583,10 +631,11 @@ public: const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } - succ_range succs() { + succ_range succs() { return succ_range(succ_begin(), succ_end()); } - succ_const_range succs() const { + + succ_const_range succs() const { return succ_const_range(succ_begin(), succ_end()); } @@ -599,13 +648,11 @@ public: class FilterOptions { public: - FilterOptions() { - IgnoreNullPredecessors = 1; - IgnoreDefaultsWithCoveredEnums = 0; - } - unsigned IgnoreNullPredecessors : 1; unsigned IgnoreDefaultsWithCoveredEnums : 1; + + FilterOptions() + : IgnoreNullPredecessors(1), IgnoreDefaultsWithCoveredEnums(0) {} }; static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, @@ -617,6 +664,7 @@ public: IMPL I, E; const FilterOptions F; const CFGBlock *From; + public: explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, @@ -634,17 +682,18 @@ public: } const CFGBlock *operator*() const { return *I; } + private: bool Filter(const CFGBlock *To) { return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To); } }; - typedef FilteredCFGBlockIterator<const_pred_iterator, true> - filtered_pred_iterator; + using filtered_pred_iterator = + FilteredCFGBlockIterator<const_pred_iterator, true>; - typedef FilteredCFGBlockIterator<const_succ_iterator, false> - filtered_succ_iterator; + using filtered_succ_iterator = + FilteredCFGBlockIterator<const_succ_iterator, false>; filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const { return filtered_pred_iterator(pred_begin(), pred_end(), this, f); @@ -728,6 +777,10 @@ public: Elements.push_back(CFGLifetimeEnds(VD, S), C); } + void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) { + Elements.push_back(CFGLoopExit(LoopStmt), C); + } + void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) { Elements.push_back(CFGDeleteDtor(RD, DE), C); } @@ -763,11 +816,12 @@ public: /// operator error is found when building the CFG. class CFGCallback { public: - CFGCallback() {} + CFGCallback() = default; + virtual ~CFGCallback() = default; + virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {} - virtual ~CFGCallback() {} }; /// CFG - Represents a source-level, intra-procedural CFG that represents the @@ -785,19 +839,24 @@ public: class BuildOptions { std::bitset<Stmt::lastStmtConstant> alwaysAddMask; + public: - typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; - ForcedBlkExprs **forcedBlkExprs; - CFGCallback *Observer; - bool PruneTriviallyFalseEdges; - bool AddEHEdges; - bool AddInitializers; - bool AddImplicitDtors; - bool AddLifetime; - bool AddTemporaryDtors; - bool AddStaticInitBranches; - bool AddCXXNewAllocator; - bool AddCXXDefaultInitExprInCtors; + using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>; + + ForcedBlkExprs **forcedBlkExprs = nullptr; + CFGCallback *Observer = nullptr; + bool PruneTriviallyFalseEdges = true; + bool AddEHEdges = false; + bool AddInitializers = false; + bool AddImplicitDtors = false; + bool AddLifetime = false; + bool AddLoopExit = false; + bool AddTemporaryDtors = false; + bool AddStaticInitBranches = false; + bool AddCXXNewAllocator = false; + bool AddCXXDefaultInitExprInCtors = false; + + BuildOptions() = default; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -812,15 +871,6 @@ public: alwaysAddMask.set(); return *this; } - - BuildOptions() - : forcedBlkExprs(nullptr), Observer(nullptr), - PruneTriviallyFalseEdges(true), - AddEHEdges(false), - AddInitializers(false), AddImplicitDtors(false), - AddLifetime(false), - AddTemporaryDtors(false), AddStaticInitBranches(false), - AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {} }; /// buildCFG - Builds a CFG from an AST. @@ -844,11 +894,11 @@ public: // Block Iterators //===--------------------------------------------------------------------===// - typedef BumpVector<CFGBlock*> CFGBlockListTy; - typedef CFGBlockListTy::iterator iterator; - typedef CFGBlockListTy::const_iterator const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + using CFGBlockListTy = BumpVector<CFGBlock *>; + using iterator = CFGBlockListTy::iterator; + using const_iterator = CFGBlockListTy::const_iterator; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; CFGBlock & front() { return *Blocks.front(); } CFGBlock & back() { return *Blocks.back(); } @@ -876,10 +926,12 @@ public: CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } - typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator; + using try_block_iterator = std::vector<const CFGBlock *>::const_iterator; + try_block_iterator try_blocks_begin() const { return TryDispatchBlocks.begin(); } + try_block_iterator try_blocks_end() const { return TryDispatchBlocks.end(); } @@ -900,9 +952,9 @@ public: SyntheticDeclStmts[Synthetic] = Source; } - typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator - synthetic_stmt_iterator; - typedef llvm::iterator_range<synthetic_stmt_iterator> synthetic_stmt_range; + using synthetic_stmt_iterator = + llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator; + using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>; /// Iterates over synthetic DeclStmts in the CFG. /// @@ -962,9 +1014,7 @@ public: // Internal: constructors and data. //===--------------------------------------------------------------------===// - CFG() - : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0), - Blocks(BlkBVC, 10) {} + CFG() : Blocks(BlkBVC, 10) {} llvm::BumpPtrAllocator& getAllocator() { return BlkBVC.getAllocator(); @@ -975,11 +1025,13 @@ public: } private: - CFGBlock *Entry; - CFGBlock *Exit; - CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch - // for indirect gotos - unsigned NumBlockIDs; + CFGBlock *Entry = nullptr; + CFGBlock *Exit = nullptr; + + // Special block to contain collective dispatch for indirect gotos + CFGBlock* IndirectGotoBlock = nullptr; + + unsigned NumBlockIDs = 0; BumpVectorContext BlkBVC; @@ -993,7 +1045,8 @@ private: /// source DeclStmt. llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts; }; -} // end namespace clang + +} // namespace clang //===----------------------------------------------------------------------===// // GraphTraits specializations for CFG basic block graphs (source-level CFGs) @@ -1004,7 +1057,8 @@ namespace llvm { /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from /// CFGTerminator to a specific Stmt class. template <> struct simplify_type< ::clang::CFGTerminator> { - typedef ::clang::Stmt *SimpleType; + using SimpleType = ::clang::Stmt *; + static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) { return Val.getStmt(); } @@ -1013,50 +1067,44 @@ template <> struct simplify_type< ::clang::CFGTerminator> { // Traits for: CFGBlock template <> struct GraphTraits< ::clang::CFGBlock *> { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; + using NodeRef = ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::succ_iterator; static NodeRef getEntryNode(::clang::CFGBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } }; template <> struct GraphTraits< const ::clang::CFGBlock *> { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_succ_iterator; static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } }; -template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> { + using NodeRef = ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; -template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> { + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse<const ::clang::CFGBlock *> G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; @@ -1064,8 +1112,7 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { template <> struct GraphTraits< ::clang::CFG* > : public GraphTraits< ::clang::CFGBlock *> { - - typedef ::clang::CFG::iterator nodes_iterator; + using nodes_iterator = ::clang::CFG::iterator; static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); } static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();} @@ -1075,44 +1122,47 @@ template <> struct GraphTraits< ::clang::CFG* > template <> struct GraphTraits<const ::clang::CFG* > : public GraphTraits<const ::clang::CFGBlock *> { - - typedef ::clang::CFG::const_iterator nodes_iterator; + using nodes_iterator = ::clang::CFG::const_iterator; static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); } + static nodes_iterator nodes_begin( const ::clang::CFG* F) { return F->nodes_begin(); } + static nodes_iterator nodes_end( const ::clang::CFG* F) { return F->nodes_end(); } + static unsigned size(const ::clang::CFG* F) { return F->size(); } }; -template <> struct GraphTraits<Inverse< ::clang::CFG*> > - : public GraphTraits<Inverse< ::clang::CFGBlock*> > { - - typedef ::clang::CFG::iterator nodes_iterator; +template <> struct GraphTraits<Inverse< ::clang::CFG *>> + : public GraphTraits<Inverse< ::clang::CFGBlock *>> { + using nodes_iterator = ::clang::CFG::iterator; static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); } static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();} static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); } }; -template <> struct GraphTraits<Inverse<const ::clang::CFG*> > - : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { - - typedef ::clang::CFG::const_iterator nodes_iterator; +template <> struct GraphTraits<Inverse<const ::clang::CFG *>> + : public GraphTraits<Inverse<const ::clang::CFGBlock *>> { + using nodes_iterator = ::clang::CFG::const_iterator; static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); } + static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->nodes_begin(); } + static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->nodes_end(); } }; -} // end llvm namespace + +} // namespace llvm #endif // LLVM_CLANG_ANALYSIS_CFG_H |