/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- RecursiveSymbolVisitor.h - Clang refactoring library -------------===// |
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 | | /// \file |
10 | | /// A wrapper class around \c RecursiveASTVisitor that visits each |
11 | | /// occurrences of a named symbol. |
12 | | /// |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H |
16 | | #define LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H |
17 | | |
18 | | #include "clang/AST/AST.h" |
19 | | #include "clang/AST/RecursiveASTVisitor.h" |
20 | | #include "clang/Lex/Lexer.h" |
21 | | |
22 | | namespace clang { |
23 | | namespace tooling { |
24 | | |
25 | | /// Traverses the AST and visits the occurrence of each named symbol in the |
26 | | /// given nodes. |
27 | | template <typename T> |
28 | | class RecursiveSymbolVisitor |
29 | | : public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> { |
30 | | using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>; |
31 | | |
32 | | public: |
33 | | RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts) |
34 | 168 | : SM(SM), LangOpts(LangOpts) {} USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::RecursiveSymbolVisitor(clang::SourceManager const&, clang::LangOptions const&) Line | Count | Source | 34 | 84 | : SM(SM), LangOpts(LangOpts) {} |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::RecursiveSymbolVisitor(clang::SourceManager const&, clang::LangOptions const&) Line | Count | Source | 34 | 84 | : SM(SM), LangOpts(LangOpts) {} |
|
35 | | |
36 | | bool visitSymbolOccurrence(const NamedDecl *ND, |
37 | | ArrayRef<SourceRange> NameRanges) { |
38 | | return true; |
39 | | } |
40 | | |
41 | | // Declaration visitors: |
42 | | |
43 | 864 | bool VisitNamedDecl(const NamedDecl *D) { |
44 | 864 | return isa<CXXConversionDecl>(D) ? true3 : visit(D, D->getLocation())861 ; |
45 | 864 | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitNamedDecl(clang::NamedDecl const*) Line | Count | Source | 43 | 183 | bool VisitNamedDecl(const NamedDecl *D) { | 44 | 183 | return isa<CXXConversionDecl>(D) ? true1 : visit(D, D->getLocation())182 ; | 45 | 183 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitNamedDecl(clang::NamedDecl const*) Line | Count | Source | 43 | 681 | bool VisitNamedDecl(const NamedDecl *D) { | 44 | 681 | return isa<CXXConversionDecl>(D) ? true2 : visit(D, D->getLocation())679 ; | 45 | 681 | } |
|
46 | | |
47 | 25 | bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { |
48 | 25 | for (const auto *Initializer : CD->inits()) { |
49 | | // Ignore implicit initializers. |
50 | 20 | if (!Initializer->isWritten()) |
51 | 7 | continue; |
52 | 13 | if (const FieldDecl *FD = Initializer->getMember()) { |
53 | 13 | if (!visit(FD, Initializer->getSourceLocation(), |
54 | 13 | Lexer::getLocForEndOfToken(Initializer->getSourceLocation(), |
55 | 13 | 0, SM, LangOpts))) |
56 | 2 | return false; |
57 | 13 | } |
58 | 13 | } |
59 | 23 | return true; |
60 | 25 | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitCXXConstructorDecl(clang::CXXConstructorDecl const*) Line | Count | Source | 47 | 2 | bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { | 48 | 2 | for (const auto *Initializer : CD->inits()) { | 49 | | // Ignore implicit initializers. | 50 | 2 | if (!Initializer->isWritten()) | 51 | 0 | continue; | 52 | 2 | if (const FieldDecl *FD = Initializer->getMember()) { | 53 | 2 | if (!visit(FD, Initializer->getSourceLocation(), | 54 | 2 | Lexer::getLocForEndOfToken(Initializer->getSourceLocation(), | 55 | 2 | 0, SM, LangOpts))) | 56 | 2 | return false; | 57 | 2 | } | 58 | 2 | } | 59 | 0 | return true; | 60 | 2 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitCXXConstructorDecl(clang::CXXConstructorDecl const*) Line | Count | Source | 47 | 23 | bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { | 48 | 23 | for (const auto *Initializer : CD->inits()) { | 49 | | // Ignore implicit initializers. | 50 | 18 | if (!Initializer->isWritten()) | 51 | 7 | continue; | 52 | 11 | if (const FieldDecl *FD = Initializer->getMember()) { | 53 | 11 | if (!visit(FD, Initializer->getSourceLocation(), | 54 | 11 | Lexer::getLocForEndOfToken(Initializer->getSourceLocation(), | 55 | 11 | 0, SM, LangOpts))) | 56 | 0 | return false; | 57 | 11 | } | 58 | 11 | } | 59 | 23 | return true; | 60 | 23 | } |
|
61 | | |
62 | | // Expression visitors: |
63 | | |
64 | 389 | bool VisitDeclRefExpr(const DeclRefExpr *Expr) { |
65 | 389 | return visit(Expr->getFoundDecl(), Expr->getLocation()); |
66 | 389 | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitDeclRefExpr(clang::DeclRefExpr const*) Line | Count | Source | 64 | 86 | bool VisitDeclRefExpr(const DeclRefExpr *Expr) { | 65 | 86 | return visit(Expr->getFoundDecl(), Expr->getLocation()); | 66 | 86 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitDeclRefExpr(clang::DeclRefExpr const*) Line | Count | Source | 64 | 303 | bool VisitDeclRefExpr(const DeclRefExpr *Expr) { | 65 | 303 | return visit(Expr->getFoundDecl(), Expr->getLocation()); | 66 | 303 | } |
|
67 | | |
68 | 149 | bool VisitMemberExpr(const MemberExpr *Expr) { |
69 | 149 | return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); |
70 | 149 | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitMemberExpr(clang::MemberExpr const*) Line | Count | Source | 68 | 27 | bool VisitMemberExpr(const MemberExpr *Expr) { | 69 | 27 | return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); | 70 | 27 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitMemberExpr(clang::MemberExpr const*) Line | Count | Source | 68 | 122 | bool VisitMemberExpr(const MemberExpr *Expr) { | 69 | 122 | return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); | 70 | 122 | } |
|
71 | | |
72 | 20 | bool VisitOffsetOfExpr(const OffsetOfExpr *S) { |
73 | 60 | for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I40 ) { |
74 | 43 | const OffsetOfNode &Component = S->getComponent(I); |
75 | 43 | if (Component.getKind() == OffsetOfNode::Field) { |
76 | 26 | if (!visit(Component.getField(), Component.getEndLoc())) |
77 | 3 | return false; |
78 | 26 | } |
79 | | // FIXME: Try to resolve dependent field references. |
80 | 43 | } |
81 | 17 | return true; |
82 | 20 | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitOffsetOfExpr(clang::OffsetOfExpr const*) Line | Count | Source | 72 | 5 | bool VisitOffsetOfExpr(const OffsetOfExpr *S) { | 73 | 10 | for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I5 ) { | 74 | 8 | const OffsetOfNode &Component = S->getComponent(I); | 75 | 8 | if (Component.getKind() == OffsetOfNode::Field) { | 76 | 6 | if (!visit(Component.getField(), Component.getEndLoc())) | 77 | 3 | return false; | 78 | 6 | } | 79 | | // FIXME: Try to resolve dependent field references. | 80 | 8 | } | 81 | 2 | return true; | 82 | 5 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitOffsetOfExpr(clang::OffsetOfExpr const*) Line | Count | Source | 72 | 15 | bool VisitOffsetOfExpr(const OffsetOfExpr *S) { | 73 | 50 | for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I35 ) { | 74 | 35 | const OffsetOfNode &Component = S->getComponent(I); | 75 | 35 | if (Component.getKind() == OffsetOfNode::Field) { | 76 | 20 | if (!visit(Component.getField(), Component.getEndLoc())) | 77 | 0 | return false; | 78 | 20 | } | 79 | | // FIXME: Try to resolve dependent field references. | 80 | 35 | } | 81 | 15 | return true; | 82 | 15 | } |
|
83 | | |
84 | | // Other visitors: |
85 | | |
86 | 1.25k | bool VisitTypeLoc(const TypeLoc Loc) { |
87 | 1.25k | const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); |
88 | 1.25k | const SourceLocation TypeEndLoc = |
89 | 1.25k | Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts); |
90 | 1.25k | if (const auto *TemplateTypeParm = |
91 | 1.25k | dyn_cast<TemplateTypeParmType>(Loc.getType())) { |
92 | 82 | if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc)) |
93 | 2 | return false; |
94 | 82 | } |
95 | 1.25k | if (const auto *TemplateSpecType = |
96 | 1.25k | dyn_cast<TemplateSpecializationType>(Loc.getType())) { |
97 | 44 | if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(), |
98 | 44 | TypeBeginLoc, TypeEndLoc)) |
99 | 2 | return false; |
100 | 44 | } |
101 | 1.25k | if (const Type *TP = Loc.getTypePtr()) { |
102 | 1.25k | if (TP->getTypeClass() == clang::Type::Record) |
103 | 331 | return visit(TP->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc); |
104 | 1.25k | } |
105 | 921 | return true; |
106 | 1.25k | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitTypeLoc(clang::TypeLoc) Line | Count | Source | 86 | 245 | bool VisitTypeLoc(const TypeLoc Loc) { | 87 | 245 | const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); | 88 | 245 | const SourceLocation TypeEndLoc = | 89 | 245 | Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts); | 90 | 245 | if (const auto *TemplateTypeParm = | 91 | 245 | dyn_cast<TemplateTypeParmType>(Loc.getType())) { | 92 | 11 | if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc)) | 93 | 2 | return false; | 94 | 11 | } | 95 | 243 | if (const auto *TemplateSpecType = | 96 | 243 | dyn_cast<TemplateSpecializationType>(Loc.getType())) { | 97 | 12 | if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(), | 98 | 12 | TypeBeginLoc, TypeEndLoc)) | 99 | 2 | return false; | 100 | 12 | } | 101 | 241 | if (const Type *TP = Loc.getTypePtr()) { | 102 | 241 | if (TP->getTypeClass() == clang::Type::Record) | 103 | 82 | return visit(TP->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc); | 104 | 241 | } | 105 | 159 | return true; | 106 | 241 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitTypeLoc(clang::TypeLoc) Line | Count | Source | 86 | 1.01k | bool VisitTypeLoc(const TypeLoc Loc) { | 87 | 1.01k | const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); | 88 | 1.01k | const SourceLocation TypeEndLoc = | 89 | 1.01k | Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts); | 90 | 1.01k | if (const auto *TemplateTypeParm = | 91 | 1.01k | dyn_cast<TemplateTypeParmType>(Loc.getType())) { | 92 | 71 | if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc)) | 93 | 0 | return false; | 94 | 71 | } | 95 | 1.01k | if (const auto *TemplateSpecType = | 96 | 1.01k | dyn_cast<TemplateSpecializationType>(Loc.getType())) { | 97 | 32 | if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(), | 98 | 32 | TypeBeginLoc, TypeEndLoc)) | 99 | 0 | return false; | 100 | 32 | } | 101 | 1.01k | if (const Type *TP = Loc.getTypePtr()) { | 102 | 1.01k | if (TP->getTypeClass() == clang::Type::Record) | 103 | 249 | return visit(TP->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc); | 104 | 1.01k | } | 105 | 762 | return true; | 106 | 1.01k | } |
|
107 | | |
108 | 2 | bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { |
109 | 2 | const SourceLocation TypeEndLoc = |
110 | 2 | Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts); |
111 | 2 | return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc); |
112 | 2 | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitTypedefTypeLoc(clang::TypedefTypeLoc) Line | Count | Source | 108 | 1 | bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { | 109 | 1 | const SourceLocation TypeEndLoc = | 110 | 1 | Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts); | 111 | 1 | return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc); | 112 | 1 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitTypedefTypeLoc(clang::TypedefTypeLoc) Line | Count | Source | 108 | 1 | bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { | 109 | 1 | const SourceLocation TypeEndLoc = | 110 | 1 | Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts); | 111 | 1 | return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc); | 112 | 1 | } |
|
113 | | |
114 | 1.27k | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { |
115 | | // The base visitor will visit NNSL prefixes, so we should only look at |
116 | | // the current NNS. |
117 | 1.27k | if (NNS) { |
118 | 45 | const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace(); |
119 | 45 | if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) |
120 | 0 | return false; |
121 | 45 | } |
122 | 1.27k | return BaseType::TraverseNestedNameSpecifierLoc(NNS); |
123 | 1.27k | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc) Line | Count | Source | 114 | 226 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { | 115 | | // The base visitor will visit NNSL prefixes, so we should only look at | 116 | | // the current NNS. | 117 | 226 | if (NNS) { | 118 | 5 | const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace(); | 119 | 5 | if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) | 120 | 0 | return false; | 121 | 5 | } | 122 | 226 | return BaseType::TraverseNestedNameSpecifierLoc(NNS); | 123 | 226 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc) Line | Count | Source | 114 | 1.04k | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { | 115 | | // The base visitor will visit NNSL prefixes, so we should only look at | 116 | | // the current NNS. | 117 | 1.04k | if (NNS) { | 118 | 40 | const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace(); | 119 | 40 | if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) | 120 | 0 | return false; | 121 | 40 | } | 122 | 1.04k | return BaseType::TraverseNestedNameSpecifierLoc(NNS); | 123 | 1.04k | } |
|
124 | | |
125 | 0 | bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { |
126 | 0 | for (const DesignatedInitExpr::Designator &D : E->designators()) { |
127 | 0 | if (D.isFieldDesignator() && D.getField()) { |
128 | 0 | const FieldDecl *Decl = D.getField(); |
129 | 0 | if (!visit(Decl, D.getFieldLoc(), D.getFieldLoc())) |
130 | 0 | return false; |
131 | 0 | } |
132 | 0 | } |
133 | 0 | return true; |
134 | 0 | } Unexecuted instantiation: USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::VisitDesignatedInitExpr(clang::DesignatedInitExpr const*) Unexecuted instantiation: USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::VisitDesignatedInitExpr(clang::DesignatedInitExpr const*) |
135 | | |
136 | | private: |
137 | | const SourceManager &SM; |
138 | | const LangOptions &LangOpts; |
139 | | |
140 | | bool visit(const NamedDecl *ND, SourceLocation BeginLoc, |
141 | 1.94k | SourceLocation EndLoc) { |
142 | 1.94k | return static_cast<T *>(this)->visitSymbolOccurrence( |
143 | 1.94k | ND, SourceRange(BeginLoc, EndLoc)); |
144 | 1.94k | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::visit(clang::NamedDecl const*, clang::SourceLocation, clang::SourceLocation) Line | Count | Source | 141 | 414 | SourceLocation EndLoc) { | 142 | 414 | return static_cast<T *>(this)->visitSymbolOccurrence( | 143 | 414 | ND, SourceRange(BeginLoc, EndLoc)); | 144 | 414 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::visit(clang::NamedDecl const*, clang::SourceLocation, clang::SourceLocation) Line | Count | Source | 141 | 1.52k | SourceLocation EndLoc) { | 142 | 1.52k | return static_cast<T *>(this)->visitSymbolOccurrence( | 143 | 1.52k | ND, SourceRange(BeginLoc, EndLoc)); | 144 | 1.52k | } |
|
145 | 1.42k | bool visit(const NamedDecl *ND, SourceLocation Loc) { |
146 | 1.42k | return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts)); |
147 | 1.42k | } USRFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::NamedDeclOccurrenceFindingVisitor>::visit(clang::NamedDecl const*, clang::SourceLocation) Line | Count | Source | 145 | 301 | bool visit(const NamedDecl *ND, SourceLocation Loc) { | 146 | 301 | return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts)); | 147 | 301 | } |
USRLocFinder.cpp:clang::tooling::RecursiveSymbolVisitor<clang::tooling::(anonymous namespace)::USRLocFindingASTVisitor>::visit(clang::NamedDecl const*, clang::SourceLocation) Line | Count | Source | 145 | 1.12k | bool visit(const NamedDecl *ND, SourceLocation Loc) { | 146 | 1.12k | return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts)); | 147 | 1.12k | } |
|
148 | | }; |
149 | | |
150 | | } // end namespace tooling |
151 | | } // end namespace clang |
152 | | |
153 | | #endif // LLVM_CLANG_TOOLING_REFACTORING_RECURSIVESYMBOLVISITOR_H |