File indexing completed on 2026-05-10 08:37:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H
0016 #define LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H
0017
0018 #include "clang/AST/AST.h"
0019 #include "clang/AST/RecursiveASTVisitor.h"
0020 #include "clang/Lex/Lexer.h"
0021
0022 namespace clang {
0023 namespace tooling {
0024
0025
0026
0027 template <typename T>
0028 class RecursiveSymbolVisitor
0029 : public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> {
0030 using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>;
0031
0032 public:
0033 RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts)
0034 : SM(SM), LangOpts(LangOpts) {}
0035
0036 bool visitSymbolOccurrence(const NamedDecl *ND,
0037 ArrayRef<SourceRange> NameRanges) {
0038 return true;
0039 }
0040
0041
0042
0043 bool VisitNamedDecl(const NamedDecl *D) {
0044 return isa<CXXConversionDecl>(D) ? true : visit(D, D->getLocation());
0045 }
0046
0047 bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
0048 for (const auto *Initializer : CD->inits()) {
0049
0050 if (!Initializer->isWritten())
0051 continue;
0052 if (const FieldDecl *FD = Initializer->getMember()) {
0053 if (!visit(FD, Initializer->getSourceLocation(),
0054 Lexer::getLocForEndOfToken(Initializer->getSourceLocation(),
0055 0, SM, LangOpts)))
0056 return false;
0057 }
0058 }
0059 return true;
0060 }
0061
0062
0063
0064 bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
0065 return visit(Expr->getFoundDecl(), Expr->getLocation());
0066 }
0067
0068 bool VisitMemberExpr(const MemberExpr *Expr) {
0069 return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
0070 }
0071
0072 bool VisitOffsetOfExpr(const OffsetOfExpr *S) {
0073 for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
0074 const OffsetOfNode &Component = S->getComponent(I);
0075 if (Component.getKind() == OffsetOfNode::Field) {
0076 if (!visit(Component.getField(), Component.getEndLoc()))
0077 return false;
0078 }
0079
0080 }
0081 return true;
0082 }
0083
0084
0085
0086 bool VisitTypeLoc(const TypeLoc Loc) {
0087 const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
0088 const SourceLocation TypeEndLoc =
0089 Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts);
0090 if (const auto *TemplateTypeParm =
0091 dyn_cast<TemplateTypeParmType>(Loc.getType())) {
0092 if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc))
0093 return false;
0094 }
0095 if (const auto *TemplateSpecType =
0096 dyn_cast<TemplateSpecializationType>(Loc.getType())) {
0097 if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
0098 TypeBeginLoc, TypeEndLoc))
0099 return false;
0100 }
0101 if (const Type *TP = Loc.getTypePtr()) {
0102 if (TP->getTypeClass() == clang::Type::Record)
0103 return visit(TP->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc);
0104 }
0105 return true;
0106 }
0107
0108 bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
0109 const SourceLocation TypeEndLoc =
0110 Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts);
0111 return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc);
0112 }
0113
0114 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
0115
0116
0117 if (NNS) {
0118 const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace();
0119 if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc()))
0120 return false;
0121 }
0122 return BaseType::TraverseNestedNameSpecifierLoc(NNS);
0123 }
0124
0125 bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
0126 for (const DesignatedInitExpr::Designator &D : E->designators()) {
0127 if (D.isFieldDesignator()) {
0128 if (const FieldDecl *Decl = D.getFieldDecl()) {
0129 if (!visit(Decl, D.getFieldLoc(), D.getFieldLoc()))
0130 return false;
0131 }
0132 }
0133 }
0134 return true;
0135 }
0136
0137 private:
0138 const SourceManager &SM;
0139 const LangOptions &LangOpts;
0140
0141 bool visit(const NamedDecl *ND, SourceLocation BeginLoc,
0142 SourceLocation EndLoc) {
0143 return static_cast<T *>(this)->visitSymbolOccurrence(
0144 ND, SourceRange(BeginLoc, EndLoc));
0145 }
0146 bool visit(const NamedDecl *ND, SourceLocation Loc) {
0147 return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts));
0148 }
0149 };
0150
0151 }
0152 }
0153
0154 #endif