Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- Lookup.h - Classes for name lookup -----------------------*- C++ -*-===// |
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 | // This file defines the LookupResult class, which is integral to |
||
10 | // Sema's name-lookup subsystem. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_SEMA_LOOKUP_H |
||
15 | #define LLVM_CLANG_SEMA_LOOKUP_H |
||
16 | |||
17 | #include "clang/AST/Decl.h" |
||
18 | #include "clang/AST/DeclBase.h" |
||
19 | #include "clang/AST/DeclCXX.h" |
||
20 | #include "clang/AST/DeclarationName.h" |
||
21 | #include "clang/AST/Type.h" |
||
22 | #include "clang/AST/UnresolvedSet.h" |
||
23 | #include "clang/Basic/LLVM.h" |
||
24 | #include "clang/Basic/LangOptions.h" |
||
25 | #include "clang/Basic/SourceLocation.h" |
||
26 | #include "clang/Basic/Specifiers.h" |
||
27 | #include "clang/Sema/Sema.h" |
||
28 | #include "llvm/ADT/MapVector.h" |
||
29 | #include "llvm/ADT/STLExtras.h" |
||
30 | #include "llvm/Support/Casting.h" |
||
31 | #include <cassert> |
||
32 | #include <optional> |
||
33 | #include <utility> |
||
34 | |||
35 | namespace clang { |
||
36 | |||
37 | class CXXBasePaths; |
||
38 | |||
39 | /// Represents the results of name lookup. |
||
40 | /// |
||
41 | /// An instance of the LookupResult class captures the results of a |
||
42 | /// single name lookup, which can return no result (nothing found), |
||
43 | /// a single declaration, a set of overloaded functions, or an |
||
44 | /// ambiguity. Use the getKind() method to determine which of these |
||
45 | /// results occurred for a given lookup. |
||
46 | class LookupResult { |
||
47 | public: |
||
48 | enum LookupResultKind { |
||
49 | /// No entity found met the criteria. |
||
50 | NotFound = 0, |
||
51 | |||
52 | /// No entity found met the criteria within the current |
||
53 | /// instantiation,, but there were dependent base classes of the |
||
54 | /// current instantiation that could not be searched. |
||
55 | NotFoundInCurrentInstantiation, |
||
56 | |||
57 | /// Name lookup found a single declaration that met the |
||
58 | /// criteria. getFoundDecl() will return this declaration. |
||
59 | Found, |
||
60 | |||
61 | /// Name lookup found a set of overloaded functions that |
||
62 | /// met the criteria. |
||
63 | FoundOverloaded, |
||
64 | |||
65 | /// Name lookup found an unresolvable value declaration |
||
66 | /// and cannot yet complete. This only happens in C++ dependent |
||
67 | /// contexts with dependent using declarations. |
||
68 | FoundUnresolvedValue, |
||
69 | |||
70 | /// Name lookup results in an ambiguity; use |
||
71 | /// getAmbiguityKind to figure out what kind of ambiguity |
||
72 | /// we have. |
||
73 | Ambiguous |
||
74 | }; |
||
75 | |||
76 | enum AmbiguityKind { |
||
77 | /// Name lookup results in an ambiguity because multiple |
||
78 | /// entities that meet the lookup criteria were found in |
||
79 | /// subobjects of different types. For example: |
||
80 | /// @code |
||
81 | /// struct A { void f(int); } |
||
82 | /// struct B { void f(double); } |
||
83 | /// struct C : A, B { }; |
||
84 | /// void test(C c) { |
||
85 | /// c.f(0); // error: A::f and B::f come from subobjects of different |
||
86 | /// // types. overload resolution is not performed. |
||
87 | /// } |
||
88 | /// @endcode |
||
89 | AmbiguousBaseSubobjectTypes, |
||
90 | |||
91 | /// Name lookup results in an ambiguity because multiple |
||
92 | /// nonstatic entities that meet the lookup criteria were found |
||
93 | /// in different subobjects of the same type. For example: |
||
94 | /// @code |
||
95 | /// struct A { int x; }; |
||
96 | /// struct B : A { }; |
||
97 | /// struct C : A { }; |
||
98 | /// struct D : B, C { }; |
||
99 | /// int test(D d) { |
||
100 | /// return d.x; // error: 'x' is found in two A subobjects (of B and C) |
||
101 | /// } |
||
102 | /// @endcode |
||
103 | AmbiguousBaseSubobjects, |
||
104 | |||
105 | /// Name lookup results in an ambiguity because multiple definitions |
||
106 | /// of entity that meet the lookup criteria were found in different |
||
107 | /// declaration contexts. |
||
108 | /// @code |
||
109 | /// namespace A { |
||
110 | /// int i; |
||
111 | /// namespace B { int i; } |
||
112 | /// int test() { |
||
113 | /// using namespace B; |
||
114 | /// return i; // error 'i' is found in namespace A and A::B |
||
115 | /// } |
||
116 | /// } |
||
117 | /// @endcode |
||
118 | AmbiguousReference, |
||
119 | |||
120 | /// Name lookup results in an ambiguity because an entity with a |
||
121 | /// tag name was hidden by an entity with an ordinary name from |
||
122 | /// a different context. |
||
123 | /// @code |
||
124 | /// namespace A { struct Foo {}; } |
||
125 | /// namespace B { void Foo(); } |
||
126 | /// namespace C { |
||
127 | /// using namespace A; |
||
128 | /// using namespace B; |
||
129 | /// } |
||
130 | /// void test() { |
||
131 | /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a |
||
132 | /// // different namespace |
||
133 | /// } |
||
134 | /// @endcode |
||
135 | AmbiguousTagHiding |
||
136 | }; |
||
137 | |||
138 | /// A little identifier for flagging temporary lookup results. |
||
139 | enum TemporaryToken { |
||
140 | Temporary |
||
141 | }; |
||
142 | |||
143 | using iterator = UnresolvedSetImpl::iterator; |
||
144 | |||
145 | LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo, |
||
146 | Sema::LookupNameKind LookupKind, |
||
147 | Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) |
||
148 | : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind), |
||
149 | Redecl(Redecl != Sema::NotForRedeclaration), |
||
150 | ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), |
||
151 | Diagnose(Redecl == Sema::NotForRedeclaration) { |
||
152 | configure(); |
||
153 | } |
||
154 | |||
155 | // TODO: consider whether this constructor should be restricted to take |
||
156 | // as input a const IdentifierInfo* (instead of Name), |
||
157 | // forcing other cases towards the constructor taking a DNInfo. |
||
158 | LookupResult(Sema &SemaRef, DeclarationName Name, |
||
159 | SourceLocation NameLoc, Sema::LookupNameKind LookupKind, |
||
160 | Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) |
||
161 | : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind), |
||
162 | Redecl(Redecl != Sema::NotForRedeclaration), |
||
163 | ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), |
||
164 | Diagnose(Redecl == Sema::NotForRedeclaration) { |
||
165 | configure(); |
||
166 | } |
||
167 | |||
168 | /// Creates a temporary lookup result, initializing its core data |
||
169 | /// using the information from another result. Diagnostics are always |
||
170 | /// disabled. |
||
171 | LookupResult(TemporaryToken _, const LookupResult &Other) |
||
172 | : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo), |
||
173 | LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl), |
||
174 | ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags), |
||
175 | AllowHidden(Other.AllowHidden), |
||
176 | TemplateNameLookup(Other.TemplateNameLookup) {} |
||
177 | |||
178 | // FIXME: Remove these deleted methods once the default build includes |
||
179 | // -Wdeprecated. |
||
180 | LookupResult(const LookupResult &) = delete; |
||
181 | LookupResult &operator=(const LookupResult &) = delete; |
||
182 | |||
183 | LookupResult(LookupResult &&Other) |
||
184 | : ResultKind(std::move(Other.ResultKind)), |
||
185 | Ambiguity(std::move(Other.Ambiguity)), Decls(std::move(Other.Decls)), |
||
186 | Paths(std::move(Other.Paths)), |
||
187 | NamingClass(std::move(Other.NamingClass)), |
||
188 | BaseObjectType(std::move(Other.BaseObjectType)), |
||
189 | SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)), |
||
190 | NameContextRange(std::move(Other.NameContextRange)), |
||
191 | LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)), |
||
192 | Redecl(std::move(Other.Redecl)), |
||
193 | ExternalRedecl(std::move(Other.ExternalRedecl)), |
||
194 | HideTags(std::move(Other.HideTags)), |
||
195 | Diagnose(std::move(Other.Diagnose)), |
||
196 | AllowHidden(std::move(Other.AllowHidden)), |
||
197 | Shadowed(std::move(Other.Shadowed)), |
||
198 | TemplateNameLookup(std::move(Other.TemplateNameLookup)) { |
||
199 | Other.Paths = nullptr; |
||
200 | Other.Diagnose = false; |
||
201 | } |
||
202 | |||
203 | LookupResult &operator=(LookupResult &&Other) { |
||
204 | ResultKind = std::move(Other.ResultKind); |
||
205 | Ambiguity = std::move(Other.Ambiguity); |
||
206 | Decls = std::move(Other.Decls); |
||
207 | Paths = std::move(Other.Paths); |
||
208 | NamingClass = std::move(Other.NamingClass); |
||
209 | BaseObjectType = std::move(Other.BaseObjectType); |
||
210 | SemaPtr = std::move(Other.SemaPtr); |
||
211 | NameInfo = std::move(Other.NameInfo); |
||
212 | NameContextRange = std::move(Other.NameContextRange); |
||
213 | LookupKind = std::move(Other.LookupKind); |
||
214 | IDNS = std::move(Other.IDNS); |
||
215 | Redecl = std::move(Other.Redecl); |
||
216 | ExternalRedecl = std::move(Other.ExternalRedecl); |
||
217 | HideTags = std::move(Other.HideTags); |
||
218 | Diagnose = std::move(Other.Diagnose); |
||
219 | AllowHidden = std::move(Other.AllowHidden); |
||
220 | Shadowed = std::move(Other.Shadowed); |
||
221 | TemplateNameLookup = std::move(Other.TemplateNameLookup); |
||
222 | Other.Paths = nullptr; |
||
223 | Other.Diagnose = false; |
||
224 | return *this; |
||
225 | } |
||
226 | |||
227 | ~LookupResult() { |
||
228 | if (Diagnose) diagnose(); |
||
229 | if (Paths) deletePaths(Paths); |
||
230 | } |
||
231 | |||
232 | /// Gets the name info to look up. |
||
233 | const DeclarationNameInfo &getLookupNameInfo() const { |
||
234 | return NameInfo; |
||
235 | } |
||
236 | |||
237 | /// Sets the name info to look up. |
||
238 | void setLookupNameInfo(const DeclarationNameInfo &NameInfo) { |
||
239 | this->NameInfo = NameInfo; |
||
240 | } |
||
241 | |||
242 | /// Gets the name to look up. |
||
243 | DeclarationName getLookupName() const { |
||
244 | return NameInfo.getName(); |
||
245 | } |
||
246 | |||
247 | /// Sets the name to look up. |
||
248 | void setLookupName(DeclarationName Name) { |
||
249 | NameInfo.setName(Name); |
||
250 | } |
||
251 | |||
252 | /// Gets the kind of lookup to perform. |
||
253 | Sema::LookupNameKind getLookupKind() const { |
||
254 | return LookupKind; |
||
255 | } |
||
256 | |||
257 | /// True if this lookup is just looking for an existing declaration. |
||
258 | bool isForRedeclaration() const { |
||
259 | return Redecl; |
||
260 | } |
||
261 | |||
262 | /// True if this lookup is just looking for an existing declaration to link |
||
263 | /// against a declaration with external linkage. |
||
264 | bool isForExternalRedeclaration() const { |
||
265 | return ExternalRedecl; |
||
266 | } |
||
267 | |||
268 | Sema::RedeclarationKind redeclarationKind() const { |
||
269 | return ExternalRedecl ? Sema::ForExternalRedeclaration : |
||
270 | Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration; |
||
271 | } |
||
272 | |||
273 | /// Specify whether hidden declarations are visible, e.g., |
||
274 | /// for recovery reasons. |
||
275 | void setAllowHidden(bool AH) { |
||
276 | AllowHidden = AH; |
||
277 | } |
||
278 | |||
279 | /// Determine whether this lookup is permitted to see hidden |
||
280 | /// declarations, such as those in modules that have not yet been imported. |
||
281 | bool isHiddenDeclarationVisible(NamedDecl *ND) const { |
||
282 | return AllowHidden || |
||
283 | (isForExternalRedeclaration() && ND->isExternallyDeclarable()); |
||
284 | } |
||
285 | |||
286 | /// Sets whether tag declarations should be hidden by non-tag |
||
287 | /// declarations during resolution. The default is true. |
||
288 | void setHideTags(bool Hide) { |
||
289 | HideTags = Hide; |
||
290 | } |
||
291 | |||
292 | /// Sets whether this is a template-name lookup. For template-name lookups, |
||
293 | /// injected-class-names are treated as naming a template rather than a |
||
294 | /// template specialization. |
||
295 | void setTemplateNameLookup(bool TemplateName) { |
||
296 | TemplateNameLookup = TemplateName; |
||
297 | } |
||
298 | |||
299 | bool isTemplateNameLookup() const { return TemplateNameLookup; } |
||
300 | |||
301 | bool isAmbiguous() const { |
||
302 | return getResultKind() == Ambiguous; |
||
303 | } |
||
304 | |||
305 | /// Determines if this names a single result which is not an |
||
306 | /// unresolved value using decl. If so, it is safe to call |
||
307 | /// getFoundDecl(). |
||
308 | bool isSingleResult() const { |
||
309 | return getResultKind() == Found; |
||
310 | } |
||
311 | |||
312 | /// Determines if the results are overloaded. |
||
313 | bool isOverloadedResult() const { |
||
314 | return getResultKind() == FoundOverloaded; |
||
315 | } |
||
316 | |||
317 | bool isUnresolvableResult() const { |
||
318 | return getResultKind() == FoundUnresolvedValue; |
||
319 | } |
||
320 | |||
321 | LookupResultKind getResultKind() const { |
||
322 | assert(checkDebugAssumptions()); |
||
323 | return ResultKind; |
||
324 | } |
||
325 | |||
326 | AmbiguityKind getAmbiguityKind() const { |
||
327 | assert(isAmbiguous()); |
||
328 | return Ambiguity; |
||
329 | } |
||
330 | |||
331 | const UnresolvedSetImpl &asUnresolvedSet() const { |
||
332 | return Decls; |
||
333 | } |
||
334 | |||
335 | iterator begin() const { return iterator(Decls.begin()); } |
||
336 | iterator end() const { return iterator(Decls.end()); } |
||
337 | |||
338 | /// Return true if no decls were found |
||
339 | bool empty() const { return Decls.empty(); } |
||
340 | |||
341 | /// Return the base paths structure that's associated with |
||
342 | /// these results, or null if none is. |
||
343 | CXXBasePaths *getBasePaths() const { |
||
344 | return Paths; |
||
345 | } |
||
346 | |||
347 | /// Determine whether the given declaration is visible to the |
||
348 | /// program. |
||
349 | static bool isVisible(Sema &SemaRef, NamedDecl *D); |
||
350 | |||
351 | static bool isReachable(Sema &SemaRef, NamedDecl *D); |
||
352 | |||
353 | static bool isAcceptable(Sema &SemaRef, NamedDecl *D, |
||
354 | Sema::AcceptableKind Kind) { |
||
355 | return Kind == Sema::AcceptableKind::Visible ? isVisible(SemaRef, D) |
||
356 | : isReachable(SemaRef, D); |
||
357 | } |
||
358 | |||
359 | /// Determine whether this lookup is permitted to see the declaration. |
||
360 | /// Note that a reachable but not visible declaration inhabiting a namespace |
||
361 | /// is not allowed to be seen during name lookup. |
||
362 | /// |
||
363 | /// For example: |
||
364 | /// ``` |
||
365 | /// // m.cppm |
||
366 | /// export module m; |
||
367 | /// struct reachable { int v; } |
||
368 | /// export auto func() { return reachable{43}; } |
||
369 | /// // Use.cpp |
||
370 | /// import m; |
||
371 | /// auto Use() { |
||
372 | /// // Not valid. We couldn't see reachable here. |
||
373 | /// // So isAvailableForLookup would return false when we look |
||
374 | /// up 'reachable' here. |
||
375 | /// // return reachable(43).v; |
||
376 | /// // Valid. The field name 'v' is allowed during name lookup. |
||
377 | /// // So isAvailableForLookup would return true when we look up 'v' here. |
||
378 | /// return func().v; |
||
379 | /// } |
||
380 | /// ``` |
||
381 | static bool isAvailableForLookup(Sema &SemaRef, NamedDecl *ND); |
||
382 | |||
383 | /// Retrieve the accepted (re)declaration of the given declaration, |
||
384 | /// if there is one. |
||
385 | NamedDecl *getAcceptableDecl(NamedDecl *D) const { |
||
386 | if (!D->isInIdentifierNamespace(IDNS)) |
||
387 | return nullptr; |
||
388 | |||
389 | if (isAvailableForLookup(getSema(), D) || isHiddenDeclarationVisible(D)) |
||
390 | return D; |
||
391 | |||
392 | return getAcceptableDeclSlow(D); |
||
393 | } |
||
394 | |||
395 | private: |
||
396 | static bool isAcceptableSlow(Sema &SemaRef, NamedDecl *D, |
||
397 | Sema::AcceptableKind Kind); |
||
398 | static bool isReachableSlow(Sema &SemaRef, NamedDecl *D); |
||
399 | NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const; |
||
400 | |||
401 | public: |
||
402 | /// Returns the identifier namespace mask for this lookup. |
||
403 | unsigned getIdentifierNamespace() const { |
||
404 | return IDNS; |
||
405 | } |
||
406 | |||
407 | /// Returns whether these results arose from performing a |
||
408 | /// lookup into a class. |
||
409 | bool isClassLookup() const { |
||
410 | return NamingClass != nullptr; |
||
411 | } |
||
412 | |||
413 | /// Returns the 'naming class' for this lookup, i.e. the |
||
414 | /// class which was looked into to find these results. |
||
415 | /// |
||
416 | /// C++0x [class.access.base]p5: |
||
417 | /// The access to a member is affected by the class in which the |
||
418 | /// member is named. This naming class is the class in which the |
||
419 | /// member name was looked up and found. [Note: this class can be |
||
420 | /// explicit, e.g., when a qualified-id is used, or implicit, |
||
421 | /// e.g., when a class member access operator (5.2.5) is used |
||
422 | /// (including cases where an implicit "this->" is added). If both |
||
423 | /// a class member access operator and a qualified-id are used to |
||
424 | /// name the member (as in p->T::m), the class naming the member |
||
425 | /// is the class named by the nested-name-specifier of the |
||
426 | /// qualified-id (that is, T). -- end note ] |
||
427 | /// |
||
428 | /// This is set by the lookup routines when they find results in a class. |
||
429 | CXXRecordDecl *getNamingClass() const { |
||
430 | return NamingClass; |
||
431 | } |
||
432 | |||
433 | /// Sets the 'naming class' for this lookup. |
||
434 | void setNamingClass(CXXRecordDecl *Record) { |
||
435 | NamingClass = Record; |
||
436 | } |
||
437 | |||
438 | /// Returns the base object type associated with this lookup; |
||
439 | /// important for [class.protected]. Most lookups do not have an |
||
440 | /// associated base object. |
||
441 | QualType getBaseObjectType() const { |
||
442 | return BaseObjectType; |
||
443 | } |
||
444 | |||
445 | /// Sets the base object type for this lookup. |
||
446 | void setBaseObjectType(QualType T) { |
||
447 | BaseObjectType = T; |
||
448 | } |
||
449 | |||
450 | /// Add a declaration to these results with its natural access. |
||
451 | /// Does not test the acceptance criteria. |
||
452 | void addDecl(NamedDecl *D) { |
||
453 | addDecl(D, D->getAccess()); |
||
454 | } |
||
455 | |||
456 | /// Add a declaration to these results with the given access. |
||
457 | /// Does not test the acceptance criteria. |
||
458 | void addDecl(NamedDecl *D, AccessSpecifier AS) { |
||
459 | Decls.addDecl(D, AS); |
||
460 | ResultKind = Found; |
||
461 | } |
||
462 | |||
463 | /// Add all the declarations from another set of lookup |
||
464 | /// results. |
||
465 | void addAllDecls(const LookupResult &Other) { |
||
466 | Decls.append(Other.Decls.begin(), Other.Decls.end()); |
||
467 | ResultKind = Found; |
||
468 | } |
||
469 | |||
470 | /// Determine whether no result was found because we could not |
||
471 | /// search into dependent base classes of the current instantiation. |
||
472 | bool wasNotFoundInCurrentInstantiation() const { |
||
473 | return ResultKind == NotFoundInCurrentInstantiation; |
||
474 | } |
||
475 | |||
476 | /// Note that while no result was found in the current instantiation, |
||
477 | /// there were dependent base classes that could not be searched. |
||
478 | void setNotFoundInCurrentInstantiation() { |
||
479 | assert(ResultKind == NotFound && Decls.empty()); |
||
480 | ResultKind = NotFoundInCurrentInstantiation; |
||
481 | } |
||
482 | |||
483 | /// Determine whether the lookup result was shadowed by some other |
||
484 | /// declaration that lookup ignored. |
||
485 | bool isShadowed() const { return Shadowed; } |
||
486 | |||
487 | /// Note that we found and ignored a declaration while performing |
||
488 | /// lookup. |
||
489 | void setShadowed() { Shadowed = true; } |
||
490 | |||
491 | /// Resolves the result kind of the lookup, possibly hiding |
||
492 | /// decls. |
||
493 | /// |
||
494 | /// This should be called in any environment where lookup might |
||
495 | /// generate multiple lookup results. |
||
496 | void resolveKind(); |
||
497 | |||
498 | /// Re-resolves the result kind of the lookup after a set of |
||
499 | /// removals has been performed. |
||
500 | void resolveKindAfterFilter() { |
||
501 | if (Decls.empty()) { |
||
502 | if (ResultKind != NotFoundInCurrentInstantiation) |
||
503 | ResultKind = NotFound; |
||
504 | |||
505 | if (Paths) { |
||
506 | deletePaths(Paths); |
||
507 | Paths = nullptr; |
||
508 | } |
||
509 | } else { |
||
510 | std::optional<AmbiguityKind> SavedAK; |
||
511 | bool WasAmbiguous = false; |
||
512 | if (ResultKind == Ambiguous) { |
||
513 | SavedAK = Ambiguity; |
||
514 | WasAmbiguous = true; |
||
515 | } |
||
516 | ResultKind = Found; |
||
517 | resolveKind(); |
||
518 | |||
519 | // If we didn't make the lookup unambiguous, restore the old |
||
520 | // ambiguity kind. |
||
521 | if (ResultKind == Ambiguous) { |
||
522 | (void)WasAmbiguous; |
||
523 | assert(WasAmbiguous); |
||
524 | Ambiguity = *SavedAK; |
||
525 | } else if (Paths) { |
||
526 | deletePaths(Paths); |
||
527 | Paths = nullptr; |
||
528 | } |
||
529 | } |
||
530 | } |
||
531 | |||
532 | template <class DeclClass> |
||
533 | DeclClass *getAsSingle() const { |
||
534 | if (getResultKind() != Found) return nullptr; |
||
535 | return dyn_cast<DeclClass>(getFoundDecl()); |
||
536 | } |
||
537 | |||
538 | /// Fetch the unique decl found by this lookup. Asserts |
||
539 | /// that one was found. |
||
540 | /// |
||
541 | /// This is intended for users who have examined the result kind |
||
542 | /// and are certain that there is only one result. |
||
543 | NamedDecl *getFoundDecl() const { |
||
544 | assert(getResultKind() == Found |
||
545 | && "getFoundDecl called on non-unique result"); |
||
546 | return (*begin())->getUnderlyingDecl(); |
||
547 | } |
||
548 | |||
549 | /// Fetches a representative decl. Useful for lazy diagnostics. |
||
550 | NamedDecl *getRepresentativeDecl() const { |
||
551 | assert(!Decls.empty() && "cannot get representative of empty set"); |
||
552 | return *begin(); |
||
553 | } |
||
554 | |||
555 | /// Asks if the result is a single tag decl. |
||
556 | bool isSingleTagDecl() const { |
||
557 | return getResultKind() == Found && isa<TagDecl>(getFoundDecl()); |
||
558 | } |
||
559 | |||
560 | /// Make these results show that the name was found in |
||
561 | /// base classes of different types. |
||
562 | /// |
||
563 | /// The given paths object is copied and invalidated. |
||
564 | void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P); |
||
565 | |||
566 | /// Make these results show that the name was found in |
||
567 | /// distinct base classes of the same type. |
||
568 | /// |
||
569 | /// The given paths object is copied and invalidated. |
||
570 | void setAmbiguousBaseSubobjects(CXXBasePaths &P); |
||
571 | |||
572 | /// Make these results show that the name was found in |
||
573 | /// different contexts and a tag decl was hidden by an ordinary |
||
574 | /// decl in a different context. |
||
575 | void setAmbiguousQualifiedTagHiding() { |
||
576 | setAmbiguous(AmbiguousTagHiding); |
||
577 | } |
||
578 | |||
579 | /// Clears out any current state. |
||
580 | LLVM_ATTRIBUTE_REINITIALIZES void clear() { |
||
581 | ResultKind = NotFound; |
||
582 | Decls.clear(); |
||
583 | if (Paths) deletePaths(Paths); |
||
584 | Paths = nullptr; |
||
585 | NamingClass = nullptr; |
||
586 | Shadowed = false; |
||
587 | } |
||
588 | |||
589 | /// Clears out any current state and re-initializes for a |
||
590 | /// different kind of lookup. |
||
591 | void clear(Sema::LookupNameKind Kind) { |
||
592 | clear(); |
||
593 | LookupKind = Kind; |
||
594 | configure(); |
||
595 | } |
||
596 | |||
597 | /// Change this lookup's redeclaration kind. |
||
598 | void setRedeclarationKind(Sema::RedeclarationKind RK) { |
||
599 | Redecl = (RK != Sema::NotForRedeclaration); |
||
600 | ExternalRedecl = (RK == Sema::ForExternalRedeclaration); |
||
601 | configure(); |
||
602 | } |
||
603 | |||
604 | void dump(); |
||
605 | void print(raw_ostream &); |
||
606 | |||
607 | /// Suppress the diagnostics that would normally fire because of this |
||
608 | /// lookup. This happens during (e.g.) redeclaration lookups. |
||
609 | void suppressDiagnostics() { |
||
610 | Diagnose = false; |
||
611 | } |
||
612 | |||
613 | /// Determines whether this lookup is suppressing diagnostics. |
||
614 | bool isSuppressingDiagnostics() const { |
||
615 | return !Diagnose; |
||
616 | } |
||
617 | |||
618 | /// Sets a 'context' source range. |
||
619 | void setContextRange(SourceRange SR) { |
||
620 | NameContextRange = SR; |
||
621 | } |
||
622 | |||
623 | /// Gets the source range of the context of this name; for C++ |
||
624 | /// qualified lookups, this is the source range of the scope |
||
625 | /// specifier. |
||
626 | SourceRange getContextRange() const { |
||
627 | return NameContextRange; |
||
628 | } |
||
629 | |||
630 | /// Gets the location of the identifier. This isn't always defined: |
||
631 | /// sometimes we're doing lookups on synthesized names. |
||
632 | SourceLocation getNameLoc() const { |
||
633 | return NameInfo.getLoc(); |
||
634 | } |
||
635 | |||
636 | /// Get the Sema object that this lookup result is searching |
||
637 | /// with. |
||
638 | Sema &getSema() const { return *SemaPtr; } |
||
639 | |||
640 | /// A class for iterating through a result set and possibly |
||
641 | /// filtering out results. The results returned are possibly |
||
642 | /// sugared. |
||
643 | class Filter { |
||
644 | friend class LookupResult; |
||
645 | |||
646 | LookupResult &Results; |
||
647 | LookupResult::iterator I; |
||
648 | bool Changed = false; |
||
649 | bool CalledDone = false; |
||
650 | |||
651 | Filter(LookupResult &Results) : Results(Results), I(Results.begin()) {} |
||
652 | |||
653 | public: |
||
654 | Filter(Filter &&F) |
||
655 | : Results(F.Results), I(F.I), Changed(F.Changed), |
||
656 | CalledDone(F.CalledDone) { |
||
657 | F.CalledDone = true; |
||
658 | } |
||
659 | |||
660 | ~Filter() { |
||
661 | assert(CalledDone && |
||
662 | "LookupResult::Filter destroyed without done() call"); |
||
663 | } |
||
664 | |||
665 | bool hasNext() const { |
||
666 | return I != Results.end(); |
||
667 | } |
||
668 | |||
669 | NamedDecl *next() { |
||
670 | assert(I != Results.end() && "next() called on empty filter"); |
||
671 | return *I++; |
||
672 | } |
||
673 | |||
674 | /// Restart the iteration. |
||
675 | void restart() { |
||
676 | I = Results.begin(); |
||
677 | } |
||
678 | |||
679 | /// Erase the last element returned from this iterator. |
||
680 | void erase() { |
||
681 | Results.Decls.erase(--I); |
||
682 | Changed = true; |
||
683 | } |
||
684 | |||
685 | /// Replaces the current entry with the given one, preserving the |
||
686 | /// access bits. |
||
687 | void replace(NamedDecl *D) { |
||
688 | Results.Decls.replace(I-1, D); |
||
689 | Changed = true; |
||
690 | } |
||
691 | |||
692 | /// Replaces the current entry with the given one. |
||
693 | void replace(NamedDecl *D, AccessSpecifier AS) { |
||
694 | Results.Decls.replace(I-1, D, AS); |
||
695 | Changed = true; |
||
696 | } |
||
697 | |||
698 | void done() { |
||
699 | assert(!CalledDone && "done() called twice"); |
||
700 | CalledDone = true; |
||
701 | |||
702 | if (Changed) |
||
703 | Results.resolveKindAfterFilter(); |
||
704 | } |
||
705 | }; |
||
706 | |||
707 | /// Create a filter for this result set. |
||
708 | Filter makeFilter() { |
||
709 | return Filter(*this); |
||
710 | } |
||
711 | |||
712 | void setFindLocalExtern(bool FindLocalExtern) { |
||
713 | if (FindLocalExtern) |
||
714 | IDNS |= Decl::IDNS_LocalExtern; |
||
715 | else |
||
716 | IDNS &= ~Decl::IDNS_LocalExtern; |
||
717 | } |
||
718 | |||
719 | private: |
||
720 | void diagnose() { |
||
721 | if (isAmbiguous()) |
||
722 | getSema().DiagnoseAmbiguousLookup(*this); |
||
723 | else if (isClassLookup() && getSema().getLangOpts().AccessControl) |
||
724 | getSema().CheckLookupAccess(*this); |
||
725 | } |
||
726 | |||
727 | void setAmbiguous(AmbiguityKind AK) { |
||
728 | ResultKind = Ambiguous; |
||
729 | Ambiguity = AK; |
||
730 | } |
||
731 | |||
732 | void addDeclsFromBasePaths(const CXXBasePaths &P); |
||
733 | void configure(); |
||
734 | |||
735 | bool checkDebugAssumptions() const; |
||
736 | |||
737 | bool checkUnresolved() const { |
||
738 | for (iterator I = begin(), E = end(); I != E; ++I) |
||
739 | if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl())) |
||
740 | return true; |
||
741 | return false; |
||
742 | } |
||
743 | |||
744 | static void deletePaths(CXXBasePaths *); |
||
745 | |||
746 | // Results. |
||
747 | LookupResultKind ResultKind = NotFound; |
||
748 | // ill-defined unless ambiguous. Still need to be initialized it will be |
||
749 | // copied/moved. |
||
750 | AmbiguityKind Ambiguity = {}; |
||
751 | UnresolvedSet<8> Decls; |
||
752 | CXXBasePaths *Paths = nullptr; |
||
753 | CXXRecordDecl *NamingClass = nullptr; |
||
754 | QualType BaseObjectType; |
||
755 | |||
756 | // Parameters. |
||
757 | Sema *SemaPtr; |
||
758 | DeclarationNameInfo NameInfo; |
||
759 | SourceRange NameContextRange; |
||
760 | Sema::LookupNameKind LookupKind; |
||
761 | unsigned IDNS = 0; // set by configure() |
||
762 | |||
763 | bool Redecl; |
||
764 | bool ExternalRedecl; |
||
765 | |||
766 | /// True if tag declarations should be hidden if non-tags |
||
767 | /// are present |
||
768 | bool HideTags = true; |
||
769 | |||
770 | bool Diagnose = false; |
||
771 | |||
772 | /// True if we should allow hidden declarations to be 'visible'. |
||
773 | bool AllowHidden = false; |
||
774 | |||
775 | /// True if the found declarations were shadowed by some other |
||
776 | /// declaration that we skipped. This only happens when \c LookupKind |
||
777 | /// is \c LookupRedeclarationWithLinkage. |
||
778 | bool Shadowed = false; |
||
779 | |||
780 | /// True if we're looking up a template-name. |
||
781 | bool TemplateNameLookup = false; |
||
782 | }; |
||
783 | |||
784 | /// Consumes visible declarations found when searching for |
||
785 | /// all visible names within a given scope or context. |
||
786 | /// |
||
787 | /// This abstract class is meant to be subclassed by clients of \c |
||
788 | /// Sema::LookupVisibleDecls(), each of which should override the \c |
||
789 | /// FoundDecl() function to process declarations as they are found. |
||
790 | class VisibleDeclConsumer { |
||
791 | public: |
||
792 | /// Destroys the visible declaration consumer. |
||
793 | virtual ~VisibleDeclConsumer(); |
||
794 | |||
795 | /// Determine whether hidden declarations (from unimported |
||
796 | /// modules) should be given to this consumer. By default, they |
||
797 | /// are not included. |
||
798 | virtual bool includeHiddenDecls() const; |
||
799 | |||
800 | /// Invoked each time \p Sema::LookupVisibleDecls() finds a |
||
801 | /// declaration visible from the current scope or context. |
||
802 | /// |
||
803 | /// \param ND the declaration found. |
||
804 | /// |
||
805 | /// \param Hiding a declaration that hides the declaration \p ND, |
||
806 | /// or NULL if no such declaration exists. |
||
807 | /// |
||
808 | /// \param Ctx the original context from which the lookup started. |
||
809 | /// |
||
810 | /// \param InBaseClass whether this declaration was found in base |
||
811 | /// class of the context we searched. |
||
812 | virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, |
||
813 | bool InBaseClass) = 0; |
||
814 | |||
815 | /// Callback to inform the client that Sema entered into a new context |
||
816 | /// to find a visible declaration. |
||
817 | // |
||
818 | /// \param Ctx the context which Sema entered. |
||
819 | virtual void EnteredContext(DeclContext *Ctx) {} |
||
820 | }; |
||
821 | |||
822 | /// A class for storing results from argument-dependent lookup. |
||
823 | class ADLResult { |
||
824 | private: |
||
825 | /// A map from canonical decls to the 'most recent' decl. |
||
826 | llvm::MapVector<NamedDecl*, NamedDecl*> Decls; |
||
827 | |||
828 | struct select_second { |
||
829 | NamedDecl *operator()(std::pair<NamedDecl*, NamedDecl*> P) const { |
||
830 | return P.second; |
||
831 | } |
||
832 | }; |
||
833 | |||
834 | public: |
||
835 | /// Adds a new ADL candidate to this map. |
||
836 | void insert(NamedDecl *D); |
||
837 | |||
838 | /// Removes any data associated with a given decl. |
||
839 | void erase(NamedDecl *D) { |
||
840 | Decls.erase(cast<NamedDecl>(D->getCanonicalDecl())); |
||
841 | } |
||
842 | |||
843 | using iterator = |
||
844 | llvm::mapped_iterator<decltype(Decls)::iterator, select_second>; |
||
845 | |||
846 | iterator begin() { return iterator(Decls.begin(), select_second()); } |
||
847 | iterator end() { return iterator(Decls.end(), select_second()); } |
||
848 | }; |
||
849 | |||
850 | } // namespace clang |
||
851 | |||
852 | #endif // LLVM_CLANG_SEMA_LOOKUP_H |