From: Eugene Zelenko Date: Thu, 7 Dec 2017 21:55:09 +0000 (+0000) Subject: [Analysis] Fix some Clang-tidy modernize and Include What You Use warnings; other... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a5b4d42444b8fa762f84c8c2a707f7c90944475d;p=clang [Analysis] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@320091 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 8cdd782671..cfedb2aa8e 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 #include +#include #include #include +#include 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 { @@ -76,14 +76,14 @@ protected: llvm::PointerIntPair Data2; CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) - : Data1(const_cast(Ptr1), ((unsigned) kind) & 0x3), - Data2(const_cast(Ptr2), (((unsigned) kind) >> 2) & 0x3) { + : Data1(const_cast(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast(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 @@ -125,7 +125,9 @@ public: private: friend class CFGElement; - CFGStmt() {} + + CFGStmt() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Statement; } @@ -144,7 +146,9 @@ public: private: friend class CFGElement; - CFGInitializer() {} + + CFGInitializer() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Initializer; } @@ -163,7 +167,9 @@ public: private: friend class CFGElement; - CFGNewAllocator() {} + + CFGNewAllocator() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == NewAllocator; } @@ -177,19 +183,20 @@ private: /// entered. class CFGLoopExit : public CFGElement { public: - explicit CFGLoopExit(const Stmt *stmt) - : CFGElement(LoopExit, stmt) {} + explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {} - const Stmt *getLoopStmt() const { - return static_cast(Data1.getPointer()); - } + const Stmt *getLoopStmt() const { + return static_cast(Data1.getPointer()); + } private: - friend class CFGElement; - CFGLoopExit() {} - static bool isKind(const CFGElement &elem) { - return elem.getKind() == LoopExit; - } + 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 @@ -208,7 +215,9 @@ public: private: friend class CFGElement; - CFGLifetimeEnds() {} + + CFGLifetimeEnds() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == LifetimeEnds; } @@ -218,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); @@ -230,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; @@ -255,7 +266,9 @@ public: private: friend class CFGElement; - CFGAutomaticObjDtor() {} + + CFGAutomaticObjDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == AutomaticObjectDtor; } @@ -279,7 +292,9 @@ public: private: friend class CFGElement; - CFGDeleteDtor() {} + + CFGDeleteDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == DeleteDtor; } @@ -298,7 +313,9 @@ public: private: friend class CFGElement; - CFGBaseDtor() {} + + CFGBaseDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == BaseDtor; } @@ -317,7 +334,9 @@ public: private: friend class CFGElement; - CFGMemberDtor() {} + + CFGMemberDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == MemberDtor; } @@ -336,7 +355,9 @@ public: private: friend class CFGElement; - CFGTemporaryDtor() {} + + CFGTemporaryDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == TemporaryDtor; } @@ -350,8 +371,9 @@ private: /// of matching full expression. class CFGTerminator { llvm::PointerIntPair Data; + public: - CFGTerminator() {} + CFGTerminator() = default; CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false) : Data(S, TemporaryDtorsBranch) {} @@ -397,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 ImplTy; + using ImplTy = BumpVector; + ImplTy Impl; + public: ElementList(BumpVectorContext &C) : Impl(C, 4) {} - typedef std::reverse_iterator iterator; - typedef std::reverse_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; + using const_iterator = std::reverse_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); @@ -429,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(); } @@ -444,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 @@ -454,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. @@ -474,7 +498,7 @@ public: }; CFGBlock *ReachableBlock; - llvm::PointerIntPair UnreachableBlock; + llvm::PointerIntPair UnreachableBlock; public: /// Construct an AdjacentBlock with a possibly unreachable block. @@ -517,7 +541,7 @@ public: private: /// Predecessors/Successors - Keep track of the predecessor / successor /// CFG blocks. - typedef BumpVector AdjacentBlocks; + using AdjacentBlocks = BumpVector; AdjacentBlocks Preds; AdjacentBlocks Succs; @@ -537,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(); } @@ -566,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_range; - typedef llvm::iterator_range 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_range; - typedef llvm::iterator_range 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; + using pred_const_range = llvm::iterator_range; + + 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; + using succ_const_range = llvm::iterator_range; pred_iterator pred_begin() { return Preds.begin(); } pred_iterator pred_end() { return Preds.end(); } @@ -590,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()); } @@ -607,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()); } @@ -623,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, @@ -641,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, @@ -658,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 - filtered_pred_iterator; + using filtered_pred_iterator = + FilteredCFGBlockIterator; - typedef FilteredCFGBlockIterator - filtered_succ_iterator; + using filtered_succ_iterator = + FilteredCFGBlockIterator; filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const { return filtered_pred_iterator(pred_begin(), pred_end(), this, f); @@ -791,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 @@ -813,20 +839,24 @@ public: class BuildOptions { std::bitset alwaysAddMask; + public: - typedef llvm::DenseMap ForcedBlkExprs; - ForcedBlkExprs **forcedBlkExprs; - CFGCallback *Observer; - bool PruneTriviallyFalseEdges; - bool AddEHEdges; - bool AddInitializers; - bool AddImplicitDtors; - bool AddLifetime; - bool AddLoopExit; - bool AddTemporaryDtors; - bool AddStaticInitBranches; - bool AddCXXNewAllocator; - bool AddCXXDefaultInitExprInCtors; + using ForcedBlkExprs = llvm::DenseMap; + + 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()]; @@ -841,15 +871,6 @@ public: alwaysAddMask.set(); return *this; } - - BuildOptions() - : forcedBlkExprs(nullptr), Observer(nullptr), - PruneTriviallyFalseEdges(true), - AddEHEdges(false), - AddInitializers(false), AddImplicitDtors(false), - AddLifetime(false), AddLoopExit(false), - AddTemporaryDtors(false), AddStaticInitBranches(false), - AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {} }; /// buildCFG - Builds a CFG from an AST. @@ -873,11 +894,11 @@ public: // Block Iterators //===--------------------------------------------------------------------===// - typedef BumpVector CFGBlockListTy; - typedef CFGBlockListTy::iterator iterator; - typedef CFGBlockListTy::const_iterator const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + using CFGBlockListTy = BumpVector; + using iterator = CFGBlockListTy::iterator; + using const_iterator = CFGBlockListTy::const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; CFGBlock & front() { return *Blocks.front(); } CFGBlock & back() { return *Blocks.back(); } @@ -905,10 +926,12 @@ public: CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } - typedef std::vector::const_iterator try_block_iterator; + using try_block_iterator = std::vector::const_iterator; + try_block_iterator try_blocks_begin() const { return TryDispatchBlocks.begin(); } + try_block_iterator try_blocks_end() const { return TryDispatchBlocks.end(); } @@ -929,9 +952,9 @@ public: SyntheticDeclStmts[Synthetic] = Source; } - typedef llvm::DenseMap::const_iterator - synthetic_stmt_iterator; - typedef llvm::iterator_range synthetic_stmt_range; + using synthetic_stmt_iterator = + llvm::DenseMap::const_iterator; + using synthetic_stmt_range = llvm::iterator_range; /// Iterates over synthetic DeclStmts in the CFG. /// @@ -991,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(); @@ -1004,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; @@ -1022,7 +1045,8 @@ private: /// source DeclStmt. llvm::DenseMap SyntheticDeclStmts; }; -} // end namespace clang + +} // namespace clang //===----------------------------------------------------------------------===// // GraphTraits specializations for CFG basic block graphs (source-level CFGs) @@ -1033,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(); } @@ -1042,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 > { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits> { + 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 > { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits> { + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; @@ -1093,8 +1112,7 @@ template <> struct GraphTraits > { 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();} @@ -1104,44 +1122,47 @@ template <> struct GraphTraits< ::clang::CFG* > template <> struct GraphTraits : public GraphTraits { - - 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 > - : public GraphTraits > { - - typedef ::clang::CFG::iterator nodes_iterator; +template <> struct GraphTraits> + : public GraphTraits> { + 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 > - : public GraphTraits > { - - typedef ::clang::CFG::const_iterator nodes_iterator; +template <> struct GraphTraits> + : public GraphTraits> { + 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 diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index a2a27a8e47..bdcdfecddc 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -1,4 +1,4 @@ -//== CallGraph.h - AST-based Call graph ------------------------*- C++ -*--==// +//===- CallGraph.h - AST-based Call graph -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,19 +12,27 @@ // A call graph for functions whose definitions/bodies are available in the // current translation unit. The graph has a "virtual" root node that contains // edges to all externally available functions. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H -#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include namespace clang { + class CallGraphNode; +class Decl; +class DeclContext; +class Stmt; /// \brief The AST-based call graph. /// @@ -34,8 +42,8 @@ class CallGraphNode; class CallGraph : public RecursiveASTVisitor { friend class CallGraphNode; - typedef llvm::DenseMap> - FunctionMapTy; + using FunctionMapTy = + llvm::DenseMap>; /// FunctionMap owns all CallGraphNodes. FunctionMapTy FunctionMap; @@ -65,10 +73,11 @@ public: /// one into the graph. CallGraphNode *getOrInsertNode(Decl *); + using iterator = FunctionMapTy::iterator; + using const_iterator = FunctionMapTy::const_iterator; + /// Iterators through all the elements in the graph. Note, this gives /// non-deterministic order. - typedef FunctionMapTy::iterator iterator; - typedef FunctionMapTy::const_iterator const_iterator; iterator begin() { return FunctionMap.begin(); } iterator end() { return FunctionMap.end(); } const_iterator begin() const { return FunctionMap.begin(); } @@ -84,8 +93,8 @@ public: /// Iterators through all the nodes of the graph that have no parent. These /// are the unreachable nodes, which are either unused or are due to us /// failing to add a call edge due to the analysis imprecision. - typedef llvm::SetVector::iterator nodes_iterator; - typedef llvm::SetVector::const_iterator const_nodes_iterator; + using nodes_iterator = llvm::SetVector::iterator; + using const_nodes_iterator = llvm::SetVector::const_iterator; void print(raw_ostream &os) const; void dump() const; @@ -133,7 +142,7 @@ private: class CallGraphNode { public: - typedef CallGraphNode* CallRecord; + using CallRecord = CallGraphNode *; private: /// \brief The function/method declaration. @@ -145,17 +154,17 @@ private: public: CallGraphNode(Decl *D) : FD(D) {} - typedef SmallVectorImpl::iterator iterator; - typedef SmallVectorImpl::const_iterator const_iterator; + using iterator = SmallVectorImpl::iterator; + using const_iterator = SmallVectorImpl::const_iterator; /// Iterators through all the callees/children of the node. - inline iterator begin() { return CalledFunctions.begin(); } - inline iterator end() { return CalledFunctions.end(); } - inline const_iterator begin() const { return CalledFunctions.begin(); } - inline const_iterator end() const { return CalledFunctions.end(); } + iterator begin() { return CalledFunctions.begin(); } + iterator end() { return CalledFunctions.end(); } + const_iterator begin() const { return CalledFunctions.begin(); } + const_iterator end() const { return CalledFunctions.end(); } - inline bool empty() const {return CalledFunctions.empty(); } - inline unsigned size() const {return CalledFunctions.size(); } + bool empty() const { return CalledFunctions.empty(); } + unsigned size() const { return CalledFunctions.size(); } void addCallee(CallGraphNode *N) { CalledFunctions.push_back(N); @@ -167,35 +176,33 @@ public: void dump() const; }; -} // end clang namespace +} // namespace clang // Graph traits for iteration, viewing. namespace llvm { + template <> struct GraphTraits { - typedef clang::CallGraphNode NodeType; - typedef clang::CallGraphNode *NodeRef; - typedef NodeType::iterator ChildIteratorType; + using NodeType = clang::CallGraphNode; + using NodeRef = clang::CallGraphNode *; + using ChildIteratorType = NodeType::iterator; static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { - return N->begin(); - } - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static ChildIteratorType child_begin(NodeType *N) { return N->begin(); } + static ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits { - typedef const clang::CallGraphNode NodeType; - typedef const clang::CallGraphNode *NodeRef; - typedef NodeType::const_iterator ChildIteratorType; + using NodeType = const clang::CallGraphNode; + using NodeRef = const clang::CallGraphNode *; + using ChildIteratorType = NodeType::const_iterator; static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits : public GraphTraits { - static NodeType *getEntryNode(clang::CallGraph *CGN) { return CGN->getRoot(); // Start at the external node! } @@ -206,19 +213,18 @@ template <> struct GraphTraits } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef mapped_iterator - nodes_iterator; + using nodes_iterator = + mapped_iterator; static nodes_iterator nodes_begin(clang::CallGraph *CG) { return nodes_iterator(CG->begin(), &CGGetValue); } + static nodes_iterator nodes_end (clang::CallGraph *CG) { return nodes_iterator(CG->end(), &CGGetValue); } - static unsigned size(clang::CallGraph *CG) { - return CG->size(); - } + static unsigned size(clang::CallGraph *CG) { return CG->size(); } }; template <> struct GraphTraits : @@ -233,21 +239,20 @@ template <> struct GraphTraits : } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef mapped_iterator - nodes_iterator; + using nodes_iterator = + mapped_iterator; static nodes_iterator nodes_begin(const clang::CallGraph *CG) { return nodes_iterator(CG->begin(), &CGGetValue); } + static nodes_iterator nodes_end(const clang::CallGraph *CG) { return nodes_iterator(CG->end(), &CGGetValue); } - static unsigned size(const clang::CallGraph *CG) { - return CG->size(); - } + + static unsigned size(const clang::CallGraph *CG) { return CG->size(); } }; -} // end llvm namespace +} // namespace llvm -#endif +#endif // LLVM_CLANG_ANALYSIS_CALLGRAPH_H diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index 591d17b9bc..5940520855 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -1,4 +1,4 @@ -//===-- BumpVector.h - Vector-like ADT that uses bump allocation --*- C++ -*-=// +//===- BumpVector.h - Vector-like ADT that uses bump allocation -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,16 +21,18 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/type_traits.h" -#include +#include +#include #include #include #include +#include namespace clang { class BumpVectorContext { llvm::PointerIntPair Alloc; + public: /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator /// and destroys it when the BumpVectorContext object is destroyed. @@ -56,11 +58,13 @@ public: template class BumpVector { - T *Begin, *End, *Capacity; + T *Begin = nullptr; + T *End = nullptr; + T *Capacity = nullptr; + public: // Default ctor - Initialize to empty. - explicit BumpVector(BumpVectorContext &C, unsigned N) - : Begin(nullptr), End(nullptr), Capacity(nullptr) { + explicit BumpVector(BumpVectorContext &C, unsigned N) { reserve(C, N); } @@ -71,19 +75,19 @@ public: } } - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + using value_type = T; + using iterator = T *; + using const_iterator = const T *; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; + using reference = T &; + using const_reference = const T &; + using pointer = T *; + using const_pointer = const T *; // forward iterator creation methods. iterator begin() { return Begin; } @@ -92,10 +96,12 @@ public: const_iterator end() const { return End; } // reverse iterator creation methods. - reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } bool empty() const { return Begin == End; } size_type size() const { return End-Begin; } @@ -166,7 +172,7 @@ public: /// iterator to position after last inserted copy. iterator insert(iterator I, size_t Cnt, const_reference E, BumpVectorContext &C) { - assert (I >= Begin && I <= End && "Iterator out of bounds."); + assert(I >= Begin && I <= End && "Iterator out of bounds."); if (End + Cnt <= Capacity) { Retry: move_range_right(I, End, Cnt); @@ -246,5 +252,6 @@ void BumpVector::grow(BumpVectorContext &C, size_t MinSize) { Capacity = Begin+NewCapacity; } -} // end: clang namespace -#endif +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index c74ab5b08a..714b85d3a9 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1,4 +1,4 @@ -//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===// +//===- CFG.cpp - Classes for representing and building CFGs ---------------===// // // The LLVM Compiler Infrastructure // @@ -15,23 +15,53 @@ #include "clang/Analysis/CFG.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" -#include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/Type.h" +#include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DOTGraphTraits.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include using namespace clang; -namespace { - static SourceLocation GetEndLoc(Decl *D) { if (VarDecl *VD = dyn_cast(D)) if (Expr *Ex = VD->getInit()) @@ -41,7 +71,7 @@ static SourceLocation GetEndLoc(Decl *D) { /// Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral /// or EnumConstantDecl from the given Expr. If it fails, returns nullptr. -const Expr *tryTransformToIntOrEnumConstant(const Expr *E) { +static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) { E = E->IgnoreParens(); if (isa(E)) return E; @@ -111,6 +141,8 @@ static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) { return DC1 == DC2; } +namespace { + class CFGBuilder; /// The CFG builder uses a recursive algorithm to build the CFG. When @@ -125,7 +157,6 @@ class CFGBuilder; /// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then /// the builder has an option not to add a subexpression as a /// block-level expression. -/// class AddStmtChoice { public: enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; @@ -168,23 +199,24 @@ private: /// class LocalScope { public: - typedef BumpVector AutomaticVarsTy; + friend class const_iterator; + + using AutomaticVarsTy = BumpVector; /// const_iterator - Iterates local scope backwards and jumps to previous /// scope on reaching the beginning of currently iterated scope. class const_iterator { - const LocalScope* Scope; + const LocalScope* Scope = nullptr; /// VarIter is guaranteed to be greater then 0 for every valid iterator. /// Invalid iterator (with null Scope) has VarIter equal to 0. - unsigned VarIter; + unsigned VarIter = 0; public: /// Create invalid iterator. Dereferencing invalid iterator is not allowed. /// Incrementing invalid iterator is allowed and will result in invalid /// iterator. - const_iterator() - : Scope(nullptr), VarIter(0) {} + const_iterator() = default; /// Create valid iterator. In case when S.Prev is an invalid iterator and /// I is equal to 0, this will create invalid iterator. @@ -197,8 +229,8 @@ public: } VarDecl *const* operator->() const { - assert (Scope && "Dereferencing invalid iterator is not allowed"); - assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); + assert(Scope && "Dereferencing invalid iterator is not allowed"); + assert(VarIter != 0 && "Iterator has invalid value of VarIter member"); return &Scope->Vars[VarIter - 1]; } VarDecl *operator*() const { @@ -209,7 +241,7 @@ public: if (!Scope) return *this; - assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); + assert(VarIter != 0 && "Iterator has invalid value of VarIter member"); --VarIter; if (VarIter == 0) *this = Scope->Prev; @@ -236,13 +268,12 @@ public: const_iterator shared_parent(const_iterator L); }; - friend class const_iterator; - private: BumpVectorContext ctx; /// Automatic variables in order of declaration. AutomaticVarsTy Vars; + /// Iterator to variable in previous scope that was declared just before /// begin of this scope. const_iterator Prev; @@ -260,6 +291,8 @@ public: } }; +} // namespace + /// distance - Calculates distance from this to L. L must be reachable from this /// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. /// number of scopes between this and L. @@ -267,8 +300,8 @@ int LocalScope::const_iterator::distance(LocalScope::const_iterator L) { int D = 0; const_iterator F = *this; while (F.Scope != L.Scope) { - assert (F != const_iterator() - && "L iterator is not reachable from F iterator."); + assert(F != const_iterator() && + "L iterator is not reachable from F iterator."); D += F.VarIter; F = F.Scope->Prev; } @@ -300,16 +333,18 @@ LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) { } } +namespace { + /// Structure for specifying position in CFG during its build process. It /// consists of CFGBlock that specifies position in CFG and /// LocalScope::const_iterator that specifies position in LocalScope graph. struct BlockScopePosPair { - BlockScopePosPair() : block(nullptr) {} + CFGBlock *block = nullptr; + LocalScope::const_iterator scopePosition; + + BlockScopePosPair() = default; BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) : block(b), scopePosition(scopePos) {} - - CFGBlock *block; - LocalScope::const_iterator scopePosition; }; /// TryResult - a class representing a variant over the values @@ -317,37 +352,46 @@ struct BlockScopePosPair { /// and is used by the CFGBuilder to decide if a branch condition /// can be decided up front during CFG construction. class TryResult { - int X; + int X = -1; + public: + TryResult() = default; TryResult(bool b) : X(b ? 1 : 0) {} - TryResult() : X(-1) {} bool isTrue() const { return X == 1; } bool isFalse() const { return X == 0; } bool isKnown() const { return X >= 0; } + void negate() { assert(isKnown()); X ^= 0x1; } }; -TryResult bothKnownTrue(TryResult R1, TryResult R2) { +} // namespace + +static TryResult bothKnownTrue(TryResult R1, TryResult R2) { if (!R1.isKnown() || !R2.isKnown()) return TryResult(); return TryResult(R1.isTrue() && R2.isTrue()); } +namespace { + class reverse_children { llvm::SmallVector childrenBuf; - ArrayRef children; + ArrayRef children; + public: reverse_children(Stmt *S); - typedef ArrayRef::reverse_iterator iterator; + using iterator = ArrayRef::reverse_iterator; + iterator begin() const { return children.rbegin(); } iterator end() const { return children.rend(); } }; +} // namespace reverse_children::reverse_children(Stmt *S) { if (CallExpr *CE = dyn_cast(S)) { @@ -374,6 +418,8 @@ reverse_children::reverse_children(Stmt *S) { children = childrenBuf; } +namespace { + /// CFGBuilder - This class implements CFG construction from an AST. /// The builder is stateful: an instance of the builder should be used to only /// construct a single CFG. @@ -387,65 +433,65 @@ reverse_children::reverse_children(Stmt *S) { /// the AST in reverse order so that the successor of a basic block is /// constructed prior to its predecessor. This allows us to nicely capture /// implicit fall-throughs without extra basic blocks. -/// class CFGBuilder { - typedef BlockScopePosPair JumpTarget; - typedef BlockScopePosPair JumpSource; + using JumpTarget = BlockScopePosPair; + using JumpSource = BlockScopePosPair; ASTContext *Context; std::unique_ptr cfg; - CFGBlock *Block; // Current block. - CFGBlock *Succ; // Block after the current block. + // Current block. + CFGBlock *Block = nullptr; + + // Block after the current block. + CFGBlock *Succ = nullptr; + JumpTarget ContinueJumpTarget; JumpTarget BreakJumpTarget; JumpTarget SEHLeaveJumpTarget; - CFGBlock *SwitchTerminatedBlock; - CFGBlock *DefaultCaseBlock; + CFGBlock *SwitchTerminatedBlock = nullptr; + CFGBlock *DefaultCaseBlock = nullptr; // This can point either to a try or a __try block. The frontend forbids // mixing both kinds in one function, so having one for both is enough. - CFGBlock *TryTerminatedBlock; + CFGBlock *TryTerminatedBlock = nullptr; // Current position in local scope. LocalScope::const_iterator ScopePos; // LabelMap records the mapping from Label expressions to their jump targets. - typedef llvm::DenseMap LabelMapTy; + using LabelMapTy = llvm::DenseMap; LabelMapTy LabelMap; // A list of blocks that end with a "goto" that must be backpatched to their // resolved targets upon completion of CFG construction. - typedef std::vector BackpatchBlocksTy; + using BackpatchBlocksTy = std::vector; BackpatchBlocksTy BackpatchBlocks; // A list of labels whose address has been taken (for indirect gotos). - typedef llvm::SmallSetVector LabelSetTy; + using LabelSetTy = llvm::SmallSetVector; LabelSetTy AddressTakenLabels; - bool badCFG; + bool badCFG = false; const CFG::BuildOptions &BuildOpts; // State to track for building switch statements. - bool switchExclusivelyCovered; - Expr::EvalResult *switchCond; + bool switchExclusivelyCovered = false; + Expr::EvalResult *switchCond = nullptr; - CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; - const Stmt *lastLookup; + CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr; + const Stmt *lastLookup = nullptr; // Caches boolean evaluations of expressions to avoid multiple re-evaluations // during construction of branches for chained logical operators. - typedef llvm::DenseMap CachedBoolEvalsTy; + using CachedBoolEvalsTy = llvm::DenseMap; CachedBoolEvalsTy CachedBoolEvals; public: explicit CFGBuilder(ASTContext *astContext, const CFG::BuildOptions &buildOpts) : Context(astContext), cfg(new CFG()), // crew a new CFG - Block(nullptr), Succ(nullptr), SwitchTerminatedBlock(nullptr), - DefaultCaseBlock(nullptr), TryTerminatedBlock(nullptr), badCFG(false), - BuildOpts(buildOpts), switchExclusivelyCovered(false), - switchCond(nullptr), cachedEntry(nullptr), lastLookup(nullptr) {} + BuildOpts(buildOpts) {} // buildCFG - Used by external clients to construct the CFG. std::unique_ptr buildCFG(const Decl *D, Stmt *Statement); @@ -549,13 +595,9 @@ private: /// if the CXXBindTemporaryExpr was marked executed, and otherwise /// branches to the stored successor. struct TempDtorContext { - TempDtorContext() - : IsConditional(false), KnownExecuted(true), Succ(nullptr), - TerminatorExpr(nullptr) {} - + TempDtorContext() = default; TempDtorContext(TryResult KnownExecuted) - : IsConditional(true), KnownExecuted(KnownExecuted), Succ(nullptr), - TerminatorExpr(nullptr) {} + : IsConditional(true), KnownExecuted(KnownExecuted) {} /// Returns whether we need to start a new branch for a temporary destructor /// call. This is the case when the temporary destructor is @@ -574,10 +616,10 @@ private: TerminatorExpr = E; } - const bool IsConditional; - const TryResult KnownExecuted; - CFGBlock *Succ; - CXXBindTemporaryExpr *TerminatorExpr; + const bool IsConditional = false; + const TryResult KnownExecuted = true; + CFGBlock *Succ = nullptr; + CXXBindTemporaryExpr *TerminatorExpr = nullptr; }; // Visitors to walk an AST and generate destructors of temporaries in @@ -608,6 +650,7 @@ private: CFGBlock *addStmt(Stmt *S) { return Visit(S, AddStmtChoice::AlwaysAdd); } + CFGBlock *addInitializer(CXXCtorInitializer *I); void addLoopExit(const Stmt *LoopStmt); void addAutomaticObjDtors(LocalScope::const_iterator B, @@ -629,6 +672,7 @@ private: void addLocalScopeAndDtors(Stmt *S); // Interface to CFGBlock - adding CFGElements. + void appendStmt(CFGBlock *B, const Stmt *S) { if (alwaysAdd(S) && cachedEntry) cachedEntry->second = B; @@ -637,21 +681,27 @@ private: assert(!isa(S) || cast(S)->IgnoreParens() == S); B->appendStmt(const_cast(S), cfg->getBumpVectorContext()); } + void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { B->appendInitializer(I, cfg->getBumpVectorContext()); } + void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) { B->appendNewAllocator(NE, cfg->getBumpVectorContext()); } + void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { B->appendBaseDtor(BS, cfg->getBumpVectorContext()); } + void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { B->appendMemberDtor(FD, cfg->getBumpVectorContext()); } + void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); } + void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); } @@ -811,10 +861,10 @@ private: const BinaryOperator *RHS = dyn_cast(B->getRHS()->IgnoreParens()); if (!LHS || !RHS) - return TryResult(); + return {}; if (!LHS->isComparisonOp() || !RHS->isComparisonOp()) - return TryResult(); + return {}; const DeclRefExpr *Decl1; const Expr *Expr1; @@ -822,7 +872,7 @@ private: std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS); if (!Decl1 || !Expr1) - return TryResult(); + return {}; const DeclRefExpr *Decl2; const Expr *Expr2; @@ -830,26 +880,26 @@ private: std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS); if (!Decl2 || !Expr2) - return TryResult(); + return {}; // Check that it is the same variable on both sides. if (Decl1->getDecl() != Decl2->getDecl()) - return TryResult(); + return {}; // Make sure the user's intent is clear (e.g. they're comparing against two // int literals, or two things from the same enum) if (!areExprTypesCompatible(Expr1, Expr2)) - return TryResult(); + return {}; llvm::APSInt L1, L2; if (!Expr1->EvaluateAsInt(L1, *Context) || !Expr2->EvaluateAsInt(L2, *Context)) - return TryResult(); + return {}; // Can't compare signed with unsigned or with different bit width. if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth()) - return TryResult(); + return {}; // Values that will be used to determine if result of logical // operator is always true/false @@ -880,7 +930,7 @@ private: Res2 = analyzeLogicOperatorCondition(BO2, Value, L2); if (!Res1.isKnown() || !Res2.isKnown()) - return TryResult(); + return {}; if (B->getOpcode() == BO_LAnd) { AlwaysTrue &= (Res1.isTrue() && Res2.isTrue()); @@ -896,7 +946,7 @@ private: BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue); return TryResult(AlwaysTrue); } - return TryResult(); + return {}; } /// Try and evaluate an expression to an integer constant. @@ -913,7 +963,7 @@ private: TryResult tryEvaluateBool(Expr *S) { if (!BuildOpts.PruneTriviallyFalseEdges || S->isTypeDependent() || S->isValueDependent()) - return TryResult(); + return {}; if (BinaryOperator *Bop = dyn_cast(S)) { if (Bop->isLogicalOp()) { @@ -988,7 +1038,7 @@ private: } } - return TryResult(); + return {}; } else if (Bop->isEqualityOp()) { TryResult BopRes = checkIncorrectEqualityOperator(Bop); if (BopRes.isKnown()) @@ -1004,12 +1054,14 @@ private: if (E->EvaluateAsBooleanCondition(Result, *Context)) return Result; - return TryResult(); + return {}; } bool hasTrivialDestructor(VarDecl *VD); }; +} // namespace + inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, const Stmt *stmt) const { return builder.alwaysAdd(stmt) || kind == AlwaysAdd; @@ -1131,7 +1183,6 @@ std::unique_ptr CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { if (CFGBlock *B = cfg->getIndirectGotoBlock()) for (LabelSetTy::iterator I = AddressTakenLabels.begin(), E = AddressTakenLabels.end(); I != E; ++I ) { - // Lookup the target block. LabelMapTy::iterator LI = LabelMap.find(*I); @@ -1265,7 +1316,6 @@ static QualType getReferenceInitTemporaryType(ASTContext &Context, return Init->getType(); } - // TODO: Support adding LoopExit element to the CFG in case where the loop is // ended by ReturnStmt, GotoStmt or ThrowExpr. void CFGBuilder::addLoopExit(const Stmt *LoopStmt){ @@ -1373,8 +1423,8 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, /// addImplicitDtorsForDestructor - Add implicit destructors generated for /// base and member objects in destructor. void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { - assert (BuildOpts.AddImplicitDtors - && "Can be called only when dtors should be added"); + assert(BuildOpts.AddImplicitDtors && + "Can be called only when dtors should be added"); const CXXRecordDecl *RD = DD->getParent(); // At the end destroy virtual base objects. @@ -1577,6 +1627,7 @@ void CFGBuilder::prependAutomaticObjLifetimeWithTerminator( for (LocalScope::const_iterator I = B; I != E; ++I) InsertPos = Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminator()); } + /// Visit - Walk the subtree of a statement and add extra /// blocks for ternary operators, &&, and ||. We also process "," and /// DeclStmts (which may contain nested control-flow). @@ -1831,7 +1882,6 @@ CFGBuilder::VisitLogicalOperator(BinaryOperator *B, Stmt *Term, CFGBlock *TrueBlock, CFGBlock *FalseBlock) { - // Introspect the RHS. If it is a nested logical operation, we recursively // build the CFG using this function. Otherwise, resort to default // CFG construction behavior. @@ -1920,7 +1970,6 @@ CFGBuilder::VisitLogicalOperator(BinaryOperator *B, return std::make_pair(EntryLHSBlock, ExitBlock); } - CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc) { // && or || @@ -1982,7 +2031,6 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { } else badCFG = true; - return Block; } @@ -2106,7 +2154,6 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, return addStmt(C->getCond()); } - CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { LocalScope::const_iterator scopeBeginPos = ScopePos; addLocalScopeForStmt(C); @@ -2457,7 +2504,6 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { return LastBlock; } - CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { // If we were in the middle of a block we stop processing that block. // @@ -2815,7 +2861,6 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { // false branch). addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor); - } while (false); // Link up the loop-back block to the entry condition block. @@ -2877,7 +2922,6 @@ CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { // the same with newVariable replaced with existingItem; the binding works // the same except that for one ObjCForCollectionStmt::getElement() returns // a DeclStmt and the other returns a DeclRefExpr. - // CFGBlock *LoopSuccessor = nullptr; @@ -3129,7 +3173,6 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { // false branch). addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor); - } while(false); // Link up the loop-back block to the entry condition block. @@ -3144,7 +3187,6 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { return EntryConditionBlock; } - CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { // FIXME: For now we pretend that @catch and the code it contains does not // exit. @@ -3317,7 +3359,6 @@ CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, AddStmtChoice asc) { - if (asc.alwaysAdd(*this, E)) { autoCreateBlock(); appendStmt(Block, E); @@ -3838,7 +3879,6 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE, AddStmtChoice asc) { - autoCreateBlock(); appendStmt(Block, NE); @@ -4141,8 +4181,6 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( return Block; } -} // end anonymous namespace - /// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has /// no successors or predecessors. If this is the first block created in the /// CFG, it is automatically set to be the Entry and Exit of the CFG. @@ -4217,7 +4255,6 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { } case CFGElement::BaseDtor: case CFGElement::MemberDtor: - // Not yet supported. return nullptr; } @@ -4235,14 +4272,14 @@ bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { //===----------------------------------------------------------------------===// CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable) - : ReachableBlock(IsReachable ? B : nullptr), - UnreachableBlock(!IsReachable ? B : nullptr, - B && IsReachable ? AB_Normal : AB_Unreachable) {} + : ReachableBlock(IsReachable ? B : nullptr), + UnreachableBlock(!IsReachable ? B : nullptr, + B && IsReachable ? AB_Normal : AB_Unreachable) {} CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock) - : ReachableBlock(B), - UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock, - B == AlternateBlock ? AB_Alternate : AB_Normal) {} + : ReachableBlock(B), + UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock, + B == AlternateBlock ? AB_Alternate : AB_Normal) {} void CFGBlock::addSuccessor(AdjacentBlock Succ, BumpVectorContext &C) { @@ -4257,7 +4294,6 @@ void CFGBlock::addSuccessor(AdjacentBlock Succ, bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, const CFGBlock *From, const CFGBlock *To) { - if (F.IgnoreNullPredecessors && !From) return true; @@ -4284,18 +4320,18 @@ bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, namespace { class StmtPrinterHelper : public PrinterHelper { - typedef llvm::DenseMap > StmtMapTy; - typedef llvm::DenseMap > DeclMapTy; + using StmtMapTy = llvm::DenseMap>; + using DeclMapTy = llvm::DenseMap>; + StmtMapTy StmtMap; DeclMapTy DeclMap; - signed currentBlock; - unsigned currStmt; + signed currentBlock = 0; + unsigned currStmt = 0; const LangOptions &LangOpts; -public: +public: StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) - : currentBlock(0), currStmt(0), LangOpts(LO) - { + : LangOpts(LO) { for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { unsigned j = 1; for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; @@ -4350,7 +4386,7 @@ public: } } - ~StmtPrinterHelper() override {} + ~StmtPrinterHelper() override = default; const LangOptions &getLangOpts() const { return LangOpts; } void setBlockID(signed i) { currentBlock = i; } @@ -4386,20 +4422,17 @@ public: return true; } }; -} // end anonymous namespace - -namespace { class CFGBlockTerminatorPrint - : public StmtVisitor { - + : public StmtVisitor { raw_ostream &OS; StmtPrinterHelper* Helper; PrintingPolicy Policy; + public: CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, const PrintingPolicy &Policy) - : OS(os), Helper(helper), Policy(Policy) { + : OS(os), Helper(helper), Policy(Policy) { this->Policy.IncludeNewlines = false; } @@ -4508,7 +4541,8 @@ public: Visit(T.getStmt()); } }; -} // end anonymous namespace + +} // namespace static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E) { @@ -4558,7 +4592,6 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, // Expressions need a newline. if (isa(S)) OS << '\n'; - } else if (Optional IE = E.getAs()) { const CXXCtorInitializer *I = IE->getInitializer(); if (I->isBaseInitializer()) @@ -4577,7 +4610,6 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, else if (I->isDelegatingInitializer()) OS << " (Delegating initializer)\n"; else OS << " (Member initializer)\n"; - } else if (Optional DE = E.getAs()) { const VarDecl *VD = DE->getVarDecl(); @@ -4590,13 +4622,11 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; OS << " (Implicit destructor)\n"; - } else if (Optional DE = E.getAs()) { const VarDecl *VD = DE->getVarDecl(); Helper.handleDecl(VD, OS); OS << " (Lifetime ends)\n"; - } else if (Optional LE = E.getAs()) { const Stmt *LoopStmt = LE->getLoopStmt(); OS << LoopStmt->getStmtClassName() << " (LoopExit)\n"; @@ -4618,14 +4648,12 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; OS << " (Base object destructor)\n"; - } else if (Optional ME = E.getAs()) { const FieldDecl *FD = ME->getFieldDecl(); const Type *T = FD->getType()->getBaseElementTypeUnsafe(); OS << "this->" << FD->getName(); OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; OS << " (Member object destructor)\n"; - } else if (Optional TE = E.getAs()) { const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); OS << "~"; @@ -4638,7 +4666,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg, const CFGBlock &B, StmtPrinterHelper &Helper, bool print_edges, bool ShowColors) { - Helper.setBlockID(B.getBlockID()); // Print the header. @@ -4663,7 +4690,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg, // Print the label of this block. if (Stmt *Label = const_cast(B.getLabel())) { - if (print_edges) OS << " "; @@ -4705,7 +4731,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg, for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; I != E ; ++I, ++j ) { - // Print the statement # in the basic block and the statement itself. if (print_edges) OS << " "; @@ -4752,7 +4777,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg, for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); I != E; ++I, ++i) { - if (i % 10 == 8) OS << "\n "; @@ -4790,7 +4814,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg, for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); I != E; ++I, ++i) { - if (i % 10 == 8) OS << "\n "; @@ -4819,7 +4842,6 @@ static void print_block(raw_ostream &OS, const CFG* cfg, } } - /// dump - A simple pretty printer of a CFG that outputs to stderr. void CFG::dump(const LangOptions &LO, bool ShowColors) const { print(llvm::errs(), LO, ShowColors); @@ -4942,7 +4964,6 @@ Stmt *CFGBlock::getTerminatorCondition(bool StripParens) { // CFG Graphviz Visualization //===----------------------------------------------------------------------===// - #ifndef NDEBUG static StmtPrinterHelper* GraphHelper; #endif @@ -4957,13 +4978,12 @@ void CFG::viewCFG(const LangOptions &LO) const { } namespace llvm { + template<> struct DOTGraphTraits : public DefaultDOTGraphTraits { - - DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { - #ifndef NDEBUG std::string OutSStr; llvm::raw_string_ostream Out(OutSStr); @@ -4981,8 +5001,9 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { return OutStr; #else - return ""; + return {}; #endif } }; -} // end namespace llvm + +} // namespace llvm diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp index 6d9530bf0c..fb6d7e87a9 100644 --- a/lib/Analysis/CallGraph.cpp +++ b/lib/Analysis/CallGraph.cpp @@ -1,4 +1,4 @@ -//== CallGraph.cpp - AST-based Call graph ----------------------*- C++ -*--==// +//===- CallGraph.cpp - AST-based Call graph -------------------------------===// // // The LLVM Compiler Infrastructure // @@ -10,13 +10,28 @@ // This file defines the AST-based CallGraph. // //===----------------------------------------------------------------------===// + #include "clang/Analysis/CallGraph.h" -#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include using namespace clang; @@ -26,6 +41,7 @@ STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges"); STATISTIC(NumBlockCallEdges, "Number of block call edges"); namespace { + /// A helper class, which walks the AST and locates all the call sites in the /// given function body. class CGBuilder : public StmtVisitor { @@ -33,8 +49,7 @@ class CGBuilder : public StmtVisitor { CallGraphNode *CallerNode; public: - CGBuilder(CallGraph *g, CallGraphNode *N) - : G(g), CallerNode(N) {} + CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {} void VisitStmt(Stmt *S) { VisitChildren(S); } @@ -90,7 +105,7 @@ public: } }; -} // end anonymous namespace +} // namespace void CallGraph::addNodesForBlocks(DeclContext *D) { if (BlockDecl *BD = dyn_cast(D)) @@ -105,7 +120,7 @@ CallGraph::CallGraph() { Root = getOrInsertNode(nullptr); } -CallGraph::~CallGraph() {} +CallGraph::~CallGraph() = default; bool CallGraph::includeInGraph(const Decl *D) { assert(D); @@ -164,8 +179,8 @@ void CallGraph::print(raw_ostream &OS) const { // We are going to print the graph in reverse post order, partially, to make // sure the output is deterministic. - llvm::ReversePostOrderTraversal RPOT(this); - for (llvm::ReversePostOrderTraversal::rpo_iterator + llvm::ReversePostOrderTraversal RPOT(this); + for (llvm::ReversePostOrderTraversal::rpo_iterator I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { const CallGraphNode *N = *I; @@ -209,8 +224,7 @@ namespace llvm { template <> struct DOTGraphTraits : public DefaultDOTGraphTraits { - - DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} static std::string getNodeLabel(const CallGraphNode *Node, const CallGraph *CG) { @@ -222,6 +236,6 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { else return "< >"; } - }; -} + +} // namespace llvm