Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:11

0001 //===--- RecursiveSymbolVisitor.h - Clang refactoring library -------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// A wrapper class around \c RecursiveASTVisitor that visits each
0011 /// occurrences of a named symbol.
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 /// Traverses the AST and visits the occurrence of each named symbol in the
0026 /// given nodes.
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   // Declaration visitors:
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       // Ignore implicit initializers.
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   // Expression visitors:
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       // FIXME: Try to resolve dependent field references.
0080     }
0081     return true;
0082   }
0083 
0084   // Other visitors:
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     // The base visitor will visit NNSL prefixes, so we should only look at
0116     // the current NNS.
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 } // end namespace tooling
0152 } // end namespace clang
0153 
0154 #endif // LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H