13626516bSHaojian Wu //===-- UsedHelperDeclFinder.h - AST-based call graph for helper decls ----===// 23626516bSHaojian Wu // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63626516bSHaojian Wu // 73626516bSHaojian Wu //===----------------------------------------------------------------------===// 83626516bSHaojian Wu 93626516bSHaojian Wu #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H 103626516bSHaojian Wu #define LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H 113626516bSHaojian Wu 123626516bSHaojian Wu #include "clang/ASTMatchers/ASTMatchFinder.h" 133626516bSHaojian Wu #include "clang/Analysis/CallGraph.h" 143626516bSHaojian Wu #include "llvm/ADT/DenseSet.h" 153626516bSHaojian Wu #include <memory> 163626516bSHaojian Wu #include <vector> 173626516bSHaojian Wu 183626516bSHaojian Wu namespace clang { 193626516bSHaojian Wu namespace move { 203626516bSHaojian Wu 213626516bSHaojian Wu // A reference graph for finding used/unused helper declarations in a single 223626516bSHaojian Wu // translation unit (e.g. old.cc). We don't reuse CallGraph in clang/Analysis 233626516bSHaojian Wu // because that CallGraph only supports function declarations. 243626516bSHaojian Wu // 253626516bSHaojian Wu // Helper declarations include following types: 263626516bSHaojian Wu // * function/variable/class definitions in an anonymous namespace. 273626516bSHaojian Wu // * static function/variable definitions in a global/named namespace. 283626516bSHaojian Wu // 293626516bSHaojian Wu // The reference graph is a directed graph. Each node in the graph represents a 303626516bSHaojian Wu // helper declaration in old.cc or a non-moved/moved declaration (e.g. class, 313626516bSHaojian Wu // function) in old.h, which means each node is associated with a Decl. 323626516bSHaojian Wu // 333626516bSHaojian Wu // To construct the graph, we use AST matcher to find interesting Decls (usually 343626516bSHaojian Wu // a pair of Caller and Callee), and add an edge from the Caller node to the 353626516bSHaojian Wu // Callee node. 363626516bSHaojian Wu // 373626516bSHaojian Wu // Specially, for a class, it might have multiple declarations such methods 383626516bSHaojian Wu // and member variables. We only use a single node to present this class, and 393626516bSHaojian Wu // this node is associated with the class declaration (CXXRecordDecl). 403626516bSHaojian Wu // 413626516bSHaojian Wu // The graph has 3 types of edges: 423626516bSHaojian Wu // 1. moved_decl => helper_decl 433626516bSHaojian Wu // 2. non_moved_decl => helper_decl 443626516bSHaojian Wu // 3. helper_decl => helper_decl 453626516bSHaojian Wu class HelperDeclRefGraph { 463626516bSHaojian Wu public: 473626516bSHaojian Wu HelperDeclRefGraph() = default; 483626516bSHaojian Wu ~HelperDeclRefGraph() = default; 493626516bSHaojian Wu 503626516bSHaojian Wu // Add a directed edge from the caller node to the callee node. 513626516bSHaojian Wu // A new node will be created if the node for Caller/Callee doesn't exist. 523626516bSHaojian Wu // 533626516bSHaojian Wu // Note that, all class member declarations are represented by a single node 543626516bSHaojian Wu // in the graph. The corresponding Decl of this node is the class declaration. 553626516bSHaojian Wu void addEdge(const Decl *Caller, const Decl *Callee); 563626516bSHaojian Wu CallGraphNode *getNode(const Decl *D) const; 573626516bSHaojian Wu 583626516bSHaojian Wu // Get all reachable nodes in the graph from the given declaration D's node, 593626516bSHaojian Wu // including D. 603626516bSHaojian Wu llvm::DenseSet<const CallGraphNode *> getReachableNodes(const Decl *D) const; 613626516bSHaojian Wu 623626516bSHaojian Wu // Dump the call graph for debug purpose. 633626516bSHaojian Wu void dump() const; 643626516bSHaojian Wu 653626516bSHaojian Wu private: 663626516bSHaojian Wu void print(raw_ostream &OS) const; 673626516bSHaojian Wu // Lookup a node for the given declaration D. If not found, insert a new 683626516bSHaojian Wu // node into the graph. 693626516bSHaojian Wu CallGraphNode *getOrInsertNode(Decl *D); 703626516bSHaojian Wu 713626516bSHaojian Wu typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>> 723626516bSHaojian Wu DeclMapTy; 733626516bSHaojian Wu 743626516bSHaojian Wu // DeclMap owns all CallGraphNodes. 753626516bSHaojian Wu DeclMapTy DeclMap; 763626516bSHaojian Wu }; 773626516bSHaojian Wu 783626516bSHaojian Wu // A builder helps to construct a call graph of helper declarations. 793626516bSHaojian Wu class HelperDeclRGBuilder : public ast_matchers::MatchFinder::MatchCallback { 803626516bSHaojian Wu public: HelperDeclRGBuilder()813626516bSHaojian Wu HelperDeclRGBuilder() : RG(new HelperDeclRefGraph) {} 823626516bSHaojian Wu void run(const ast_matchers::MatchFinder::MatchResult &Result) override; getGraph()833626516bSHaojian Wu const HelperDeclRefGraph *getGraph() const { return RG.get(); } 843626516bSHaojian Wu 853626516bSHaojian Wu // Find out the outmost enclosing class/function declaration of a given D. 863626516bSHaojian Wu // For a CXXMethodDecl, get its CXXRecordDecl; For a VarDecl/FunctionDecl, get 873626516bSHaojian Wu // its outmost enclosing FunctionDecl or CXXRecordDecl. 883626516bSHaojian Wu // Return D if not found. 893626516bSHaojian Wu static const Decl *getOutmostClassOrFunDecl(const Decl *D); 903626516bSHaojian Wu 913626516bSHaojian Wu private: 923626516bSHaojian Wu std::unique_ptr<HelperDeclRefGraph> RG; 933626516bSHaojian Wu }; 943626516bSHaojian Wu 953626516bSHaojian Wu } // namespace move 963626516bSHaojian Wu } // namespace clang 973626516bSHaojian Wu 983626516bSHaojian Wu #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_USED_HELPER_DECL_FINDER_H 99