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