clang: lib/Tooling/Refactoring/Lookup.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
20#include "llvm/ADT/SmallVector.h"
21using namespace clang;
23
24
25
26
27
28
32 auto GetNextNamedNamespace = [](const DeclContext *Context) {
33
34 while (Context && (!isa(Context) ||
35 cast(Context)->isAnonymousNamespace()))
36 Context = Context->getParent();
37 return Context;
38 };
39 for (Context = GetNextNamedNamespace(Context); Context != nullptr;
40 Context = GetNextNamedNamespace(Context->getParent()))
41 Namespaces.push_back(cast(Context));
42 return Namespaces;
43}
44
45
46
47
48static bool
51
52
53
54
55
60
61
62 if (UseNamespaces.size() < FromNamespaces.size())
63 return false;
64 unsigned Diff = UseNamespaces.size() - FromNamespaces.size();
65 auto FromIter = FromNamespaces.begin();
66
67
68
69 auto UseIter = UseNamespaces.begin() + Diff;
70 for (; FromIter != FromNamespaces.end() && UseIter != UseNamespaces.end();
71 ++FromIter, ++UseIter) {
72
73 if (*FromIter == *UseIter)
74 return false;
75
76
77 if (cast(*FromIter)->getDeclName() ==
78 cast(*UseIter)->getDeclName())
79 return true;
80 }
81 assert(FromIter == FromNamespaces.end() && UseIter == UseNamespaces.end());
82 return false;
83}
84
86 StringRef NewName,
87 bool HadLeadingColonColon) {
88 while (true) {
89 while (DeclA && !isa(DeclA))
91
92
93 if (!DeclA)
94 return HadLeadingColonColon ? NewName : NewName.substr(2);
95
96
97
98
99 std::string NS =
100 "::" + cast(DeclA)->getQualifiedNameAsString() + "::";
101 if (NewName.consume_front(NS))
102 return NewName;
103
104
105
106
108 }
109}
110
111
113 while (NNS) {
115 return true;
117 }
118 return false;
119}
120
121
122
123
124
125
126
128 StringRef QName,
131 assert(QName.starts_with("::"));
132 assert(QName.ends_with(Spelling));
133 if (Spelling.starts_with("::"))
134 return std::string(Spelling);
135
136 auto UnspelledSpecifier = QName.drop_back(Spelling.size());
138 UnspelledSpecifier.split(UnspelledScopes, "::", -1,
139 false);
140
144 StringRef TrimmedQName = QName.substr(2);
146 UseLoc = SM.getSpellingLoc(UseLoc);
147
148 auto IsAmbiguousSpelling = [&](const llvm::StringRef CurSpelling) {
149 if (CurSpelling.starts_with("::"))
150 return false;
151
152
153
154 StringRef Head = CurSpelling.split("::").first;
155 for (const auto *NS : EnclosingNamespaces) {
156 auto LookupRes = NS->lookup(DeclarationName(&AST.Idents.get(Head)));
157 if (!LookupRes.empty()) {
158 for (const NamedDecl *Res : LookupRes)
159
160
161
162
163 if (!TrimmedQName.starts_with(Res->getQualifiedNameAsString()) &&
164 SM.isBeforeInTranslationUnit(
165 SM.getSpellingLoc(Res->getLocation()), UseLoc))
166 return true;
167 }
168 }
169 return false;
170 };
171
172
173 std::string Disambiguated = std::string(Spelling);
174 while (IsAmbiguousSpelling(Disambiguated)) {
175 if (UnspelledScopes.empty()) {
176 Disambiguated = "::" + Disambiguated;
177 } else {
178 Disambiguated = (UnspelledScopes.back() + "::" + Disambiguated).str();
179 UnspelledScopes.pop_back();
180 }
181 }
182 return Disambiguated;
183}
184
189 StringRef ReplacementString) {
190 assert(ReplacementString.starts_with("::") &&
191 "Expected fully-qualified name!");
192
193
194
195
196
197
198
199
200
201 const bool class_name_only = !Use;
202 const bool in_global_namespace =
204 const bool is_class_forward_decl =
205 isa(FromDecl) &&
206 !cast(FromDecl)->isCompleteDefinition();
207 if (class_name_only && !in_global_namespace && !is_class_forward_decl &&
209 UseContext)) {
210 auto Pos = ReplacementString.rfind("::");
211 return std::string(Pos != StringRef::npos
212 ? ReplacementString.substr(Pos + 2)
213 : ReplacementString);
214 }
215
216
217
218
221
223 UseLoc);
224}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static llvm::SmallVector< const NamespaceDecl *, 4 > getAllNamedNamespaces(const DeclContext *Context)
static bool usingFromDifferentCanonicalNamespace(const DeclContext *FromContext, const DeclContext *UseContext)
static StringRef getBestNamespaceSubstr(const DeclContext *DeclA, StringRef NewName, bool HadLeadingColonColon)
static std::string disambiguateSpellingInScope(StringRef Spelling, StringRef QName, const DeclContext &UseContext, SourceLocation UseLoc)
static bool isFullyQualified(const NestedNameSpecifier *NNS)
Check if the name specifier begins with a written "::".
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
const NamedDecl * FromDecl
SourceManager & getSourceManager()
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
ASTContext & getParentASTContext() const
DeclContext * getDeclContext()
The name of a declaration.
This represents a decl that may have a name.
Represents a C++ nested name specifier, such as "\::std::vector::".
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
NestedNameSpecifier * getPrefix() const
Return the prefix of this nested name specifier.
@ Global
The global specifier '::'. There is no stored value.
Encodes a location in the source.
The JSON file list parser is used to communicate input to InstallAPI.