]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Tooling / Refactoring / RecursiveSymbolVisitor.h
1 //===--- RecursiveSymbolVisitor.h - Clang refactoring library -------------===//
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 /// \file
11 /// A wrapper class around \c RecursiveASTVisitor that visits each
12 /// occurrences of a named symbol.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H
17 #define LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H
18
19 #include "clang/AST/AST.h"
20 #include "clang/AST/RecursiveASTVisitor.h"
21 #include "clang/Lex/Lexer.h"
22
23 namespace clang {
24 namespace tooling {
25
26 /// Traverses the AST and visits the occurrence of each named symbol in the
27 /// given nodes.
28 template <typename T>
29 class RecursiveSymbolVisitor
30     : public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> {
31   using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>;
32
33 public:
34   RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts)
35       : SM(SM), LangOpts(LangOpts) {}
36
37   bool visitSymbolOccurrence(const NamedDecl *ND,
38                              ArrayRef<SourceRange> NameRanges) {
39     return true;
40   }
41
42   // Declaration visitors:
43
44   bool VisitNamedDecl(const NamedDecl *D) {
45     return isa<CXXConversionDecl>(D) ? true : visit(D, D->getLocation());
46   }
47
48   bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
49     for (const auto *Initializer : CD->inits()) {
50       // Ignore implicit initializers.
51       if (!Initializer->isWritten())
52         continue;
53       if (const FieldDecl *FD = Initializer->getMember()) {
54         if (!visit(FD, Initializer->getSourceLocation(),
55                    Lexer::getLocForEndOfToken(Initializer->getSourceLocation(),
56                                               0, SM, LangOpts)))
57           return false;
58       }
59     }
60     return true;
61   }
62
63   // Expression visitors:
64
65   bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
66     return visit(Expr->getFoundDecl(), Expr->getLocation());
67   }
68
69   bool VisitMemberExpr(const MemberExpr *Expr) {
70     return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
71   }
72
73   bool VisitOffsetOfExpr(const OffsetOfExpr *S) {
74     for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
75       const OffsetOfNode &Component = S->getComponent(I);
76       if (Component.getKind() == OffsetOfNode::Field) {
77         if (!visit(Component.getField(), Component.getLocEnd()))
78           return false;
79       }
80       // FIXME: Try to resolve dependent field references.
81     }
82     return true;
83   }
84
85   // Other visitors:
86
87   bool VisitTypeLoc(const TypeLoc Loc) {
88     const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
89     const SourceLocation TypeEndLoc =
90         Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts);
91     if (const auto *TemplateTypeParm =
92             dyn_cast<TemplateTypeParmType>(Loc.getType())) {
93       if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc))
94         return false;
95     }
96     if (const auto *TemplateSpecType =
97             dyn_cast<TemplateSpecializationType>(Loc.getType())) {
98       if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
99                  TypeBeginLoc, TypeEndLoc))
100         return false;
101     }
102     return visit(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc);
103   }
104
105   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
106     // The base visitor will visit NNSL prefixes, so we should only look at
107     // the current NNS.
108     if (NNS) {
109       const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace();
110       if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc()))
111         return false;
112     }
113     return BaseType::TraverseNestedNameSpecifierLoc(NNS);
114   }
115
116 private:
117   const SourceManager &SM;
118   const LangOptions &LangOpts;
119
120   bool visit(const NamedDecl *ND, SourceLocation BeginLoc,
121              SourceLocation EndLoc) {
122     return static_cast<T *>(this)->visitSymbolOccurrence(
123         ND, SourceRange(BeginLoc, EndLoc));
124   }
125   bool visit(const NamedDecl *ND, SourceLocation Loc) {
126     return visit(ND, Loc,
127                  Loc.getLocWithOffset(ND->getNameAsString().length() - 1));
128   }
129 };
130
131 } // end namespace tooling
132 } // end namespace clang
133
134 #endif // LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H