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