1 //===--- RecursiveSymbolVisitor.h - Clang refactoring library -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief A wrapper class around \c RecursiveASTVisitor that visits each
12 /// occurrences of a named symbol.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H
17 #define LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H
19 #include "clang/AST/AST.h"
20 #include "clang/AST/RecursiveASTVisitor.h"
21 #include "clang/Lex/Lexer.h"
26 /// Traverses the AST and visits the occurrence of each named symbol in the
29 class RecursiveSymbolVisitor
30 : public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> {
31 using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>;
34 RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts)
35 : SM(SM), LangOpts(LangOpts) {}
37 bool visitSymbolOccurrence(const NamedDecl *ND,
38 ArrayRef<SourceRange> NameRanges) {
42 // Declaration visitors:
44 bool VisitNamedDecl(const NamedDecl *D) {
45 return isa<CXXConversionDecl>(D) ? true : visit(D, D->getLocation());
48 bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
49 for (const auto *Initializer : CD->inits()) {
50 // Ignore implicit initializers.
51 if (!Initializer->isWritten())
53 if (const FieldDecl *FD = Initializer->getMember()) {
54 if (!visit(FD, Initializer->getSourceLocation(),
55 Lexer::getLocForEndOfToken(Initializer->getSourceLocation(),
63 // Expression visitors:
65 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
66 return visit(Expr->getFoundDecl(), Expr->getLocation());
69 bool VisitMemberExpr(const MemberExpr *Expr) {
70 return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
75 bool VisitTypeLoc(const TypeLoc Loc) {
76 const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
77 const SourceLocation TypeEndLoc =
78 Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts);
79 if (const auto *TemplateTypeParm =
80 dyn_cast<TemplateTypeParmType>(Loc.getType())) {
81 if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc))
84 if (const auto *TemplateSpecType =
85 dyn_cast<TemplateSpecializationType>(Loc.getType())) {
86 if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
87 TypeBeginLoc, TypeEndLoc))
90 return visit(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc);
93 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
94 // The base visitor will visit NNSL prefixes, so we should only look at
97 const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace();
98 if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc()))
101 return BaseType::TraverseNestedNameSpecifierLoc(NNS);
105 const SourceManager &SM;
106 const LangOptions &LangOpts;
108 bool visit(const NamedDecl *ND, SourceLocation BeginLoc,
109 SourceLocation EndLoc) {
110 return static_cast<T *>(this)->visitSymbolOccurrence(
111 ND, SourceRange(BeginLoc, EndLoc));
113 bool visit(const NamedDecl *ND, SourceLocation Loc) {
114 return visit(ND, Loc,
115 Loc.getLocWithOffset(ND->getNameAsString().length() - 1));
119 } // end namespace tooling
120 } // end namespace clang
122 #endif // LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H