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
18namespace clang {
19namespace 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
45class HelperDeclRefGraph {
46public:
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
65private:
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.
79class HelperDeclRGBuilder : public ast_matchers::MatchFinder::MatchCallback {
80public:
81 HelperDeclRGBuilder() : RG(new HelperDeclRefGraph) {}
82 void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
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
91private:
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

source code of clang-tools-extra/clang-move/HelperDeclRefGraph.h