xref: /llvm-project/clang-tools-extra/clang-move/HelperDeclRefGraph.h (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
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