1 //===-- UsedHelperDeclFinder.h - AST-based call graph for helper decls ----===// 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H 11 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/Analysis/CallGraph.h" 14 #include "llvm/ADT/DenseSet.h" 15 #include <memory> 16 #include <vector> 17 18 namespace clang { 19 namespace move { 20 21 // A reference graph for finding used/unused helper declarations in a single 22 // translation unit (e.g. old.cc). We don't reuse CallGraph in clang/Analysis 23 // because that CallGraph only supports function declarations. 24 // 25 // Helper declarations include following types: 26 // * function/variable/class definitions in an anonymous namespace. 27 // * static function/variable definitions in a global/named namespace. 28 // 29 // The reference graph is a directed graph. Each node in the graph represents a 30 // helper declaration in old.cc or a non-moved/moved declaration (e.g. class, 31 // function) in old.h, which means each node is associated with a Decl. 32 // 33 // To construct the graph, we use AST matcher to find interesting Decls (usually 34 // a pair of Caller and Callee), and add an edge from the Caller node to the 35 // Callee node. 36 // 37 // Specially, for a class, it might have multiple declarations such methods 38 // and member variables. We only use a single node to present this class, and 39 // this node is associated with the class declaration (CXXRecordDecl). 40 // 41 // The graph has 3 types of edges: 42 // 1. moved_decl => helper_decl 43 // 2. non_moved_decl => helper_decl 44 // 3. helper_decl => helper_decl 45 class HelperDeclRefGraph { 46 public: 47 HelperDeclRefGraph() = default; 48 ~HelperDeclRefGraph() = default; 49 50 // Add a directed edge from the caller node to the callee node. 51 // A new node will be created if the node for Caller/Callee doesn't exist. 52 // 53 // Note that, all class member declarations are represented by a single node 54 // in the graph. The corresponding Decl of this node is the class declaration. 55 void addEdge(const Decl *Caller, const Decl *Callee); 56 CallGraphNode *getNode(const Decl *D) const; 57 58 // Get all reachable nodes in the graph from the given declaration D's node, 59 // including D. 60 llvm::DenseSet<const CallGraphNode *> getReachableNodes(const Decl *D) const; 61 62 // Dump the call graph for debug purpose. 63 void dump() const; 64 65 private: 66 void print(raw_ostream &OS) const; 67 // Lookup a node for the given declaration D. If not found, insert a new 68 // node into the graph. 69 CallGraphNode *getOrInsertNode(Decl *D); 70 71 typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>> 72 DeclMapTy; 73 74 // DeclMap owns all CallGraphNodes. 75 DeclMapTy DeclMap; 76 }; 77 78 // A builder helps to construct a call graph of helper declarations. 79 class HelperDeclRGBuilder : public ast_matchers::MatchFinder::MatchCallback { 80 public: HelperDeclRGBuilder()81 HelperDeclRGBuilder() : RG(new HelperDeclRefGraph) {} 82 void run(const ast_matchers::MatchFinder::MatchResult &Result) override; getGraph()83 const HelperDeclRefGraph *getGraph() const { return RG.get(); } 84 85 // Find out the outmost enclosing class/function declaration of a given D. 86 // For a CXXMethodDecl, get its CXXRecordDecl; For a VarDecl/FunctionDecl, get 87 // its outmost enclosing FunctionDecl or CXXRecordDecl. 88 // Return D if not found. 89 static const Decl *getOutmostClassOrFunDecl(const Decl *D); 90 91 private: 92 std::unique_ptr<HelperDeclRefGraph> RG; 93 }; 94 95 } // namespace move 96 } // namespace clang 97 98 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H 99