blob: 9064de6aa019e320fa814862c938050797efd7b3 [file] [log] [blame]
John McCall7d384dd2009-11-18 07:57:50 +00001//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the LookupResult class, which is integral to
11// Sema's name-lookup subsystem.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_SEMA_LOOKUP_H
16#define LLVM_CLANG_SEMA_LOOKUP_H
17
18#include "Sema.h"
19
20namespace clang {
21
22/// @brief Represents the results of name lookup.
23///
24/// An instance of the LookupResult class captures the results of a
25/// single name lookup, which can return no result (nothing found),
26/// a single declaration, a set of overloaded functions, or an
27/// ambiguity. Use the getKind() method to determine which of these
28/// results occurred for a given lookup.
John McCall7d384dd2009-11-18 07:57:50 +000029class LookupResult {
30public:
31 enum LookupResultKind {
32 /// @brief No entity found met the criteria.
33 NotFound = 0,
34
Douglas Gregor7d3f5762010-01-15 01:44:47 +000035 /// @brief No entity found met the criteria within the current
36 /// instantiation,, but there were dependent base classes of the
37 /// current instantiation that could not be searched.
38 NotFoundInCurrentInstantiation,
39
John McCall7d384dd2009-11-18 07:57:50 +000040 /// @brief Name lookup found a single declaration that met the
John McCall51fa86f2009-12-02 08:47:38 +000041 /// criteria. getFoundDecl() will return this declaration.
John McCall7d384dd2009-11-18 07:57:50 +000042 Found,
43
44 /// @brief Name lookup found a set of overloaded functions that
John McCall51fa86f2009-12-02 08:47:38 +000045 /// met the criteria.
John McCall7d384dd2009-11-18 07:57:50 +000046 FoundOverloaded,
47
48 /// @brief Name lookup found an unresolvable value declaration
49 /// and cannot yet complete. This only happens in C++ dependent
50 /// contexts with dependent using declarations.
51 FoundUnresolvedValue,
52
53 /// @brief Name lookup results in an ambiguity; use
54 /// getAmbiguityKind to figure out what kind of ambiguity
55 /// we have.
56 Ambiguous
57 };
58
59 enum AmbiguityKind {
60 /// Name lookup results in an ambiguity because multiple
61 /// entities that meet the lookup criteria were found in
62 /// subobjects of different types. For example:
63 /// @code
64 /// struct A { void f(int); }
65 /// struct B { void f(double); }
66 /// struct C : A, B { };
67 /// void test(C c) {
68 /// c.f(0); // error: A::f and B::f come from subobjects of different
69 /// // types. overload resolution is not performed.
70 /// }
71 /// @endcode
72 AmbiguousBaseSubobjectTypes,
73
74 /// Name lookup results in an ambiguity because multiple
75 /// nonstatic entities that meet the lookup criteria were found
76 /// in different subobjects of the same type. For example:
77 /// @code
78 /// struct A { int x; };
79 /// struct B : A { };
80 /// struct C : A { };
81 /// struct D : B, C { };
82 /// int test(D d) {
83 /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
84 /// }
85 /// @endcode
86 AmbiguousBaseSubobjects,
87
88 /// Name lookup results in an ambiguity because multiple definitions
89 /// of entity that meet the lookup criteria were found in different
90 /// declaration contexts.
91 /// @code
92 /// namespace A {
93 /// int i;
94 /// namespace B { int i; }
95 /// int test() {
96 /// using namespace B;
97 /// return i; // error 'i' is found in namespace A and A::B
98 /// }
99 /// }
100 /// @endcode
101 AmbiguousReference,
102
103 /// Name lookup results in an ambiguity because an entity with a
104 /// tag name was hidden by an entity with an ordinary name from
105 /// a different context.
106 /// @code
107 /// namespace A { struct Foo {}; }
108 /// namespace B { void Foo(); }
109 /// namespace C {
110 /// using namespace A;
111 /// using namespace B;
112 /// }
113 /// void test() {
114 /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
115 /// // different namespace
116 /// }
117 /// @endcode
118 AmbiguousTagHiding
119 };
120
121 /// A little identifier for flagging temporary lookup results.
122 enum TemporaryToken {
123 Temporary
124 };
125
126 typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
127 typedef DeclsTy::const_iterator iterator;
128
John McCall1d7c5282009-12-18 10:40:03 +0000129 typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS);
130
John McCall7d384dd2009-11-18 07:57:50 +0000131 LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
132 Sema::LookupNameKind LookupKind,
133 Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
134 : ResultKind(NotFound),
135 Paths(0),
136 SemaRef(SemaRef),
137 Name(Name),
138 NameLoc(NameLoc),
139 LookupKind(LookupKind),
John McCall1d7c5282009-12-18 10:40:03 +0000140 IsAcceptableFn(0),
John McCall7d384dd2009-11-18 07:57:50 +0000141 IDNS(0),
142 Redecl(Redecl != Sema::NotForRedeclaration),
143 HideTags(true),
144 Diagnose(Redecl == Sema::NotForRedeclaration)
John McCall1d7c5282009-12-18 10:40:03 +0000145 {
146 configure();
147 }
John McCall7d384dd2009-11-18 07:57:50 +0000148
149 /// Creates a temporary lookup result, initializing its core data
150 /// using the information from another result. Diagnostics are always
151 /// disabled.
152 LookupResult(TemporaryToken _, const LookupResult &Other)
153 : ResultKind(NotFound),
154 Paths(0),
155 SemaRef(Other.SemaRef),
156 Name(Other.Name),
157 NameLoc(Other.NameLoc),
158 LookupKind(Other.LookupKind),
John McCall1d7c5282009-12-18 10:40:03 +0000159 IsAcceptableFn(Other.IsAcceptableFn),
John McCall7d384dd2009-11-18 07:57:50 +0000160 IDNS(Other.IDNS),
161 Redecl(Other.Redecl),
162 HideTags(Other.HideTags),
163 Diagnose(false)
164 {}
165
166 ~LookupResult() {
167 if (Diagnose) diagnose();
168 if (Paths) deletePaths(Paths);
169 }
170
171 /// Gets the name to look up.
172 DeclarationName getLookupName() const {
173 return Name;
174 }
175
Douglas Gregor546be3c2009-12-30 17:04:44 +0000176 /// \brief Sets the name to look up.
177 void setLookupName(DeclarationName Name) {
178 this->Name = Name;
179 }
180
John McCall7d384dd2009-11-18 07:57:50 +0000181 /// Gets the kind of lookup to perform.
182 Sema::LookupNameKind getLookupKind() const {
183 return LookupKind;
184 }
185
186 /// True if this lookup is just looking for an existing declaration.
187 bool isForRedeclaration() const {
188 return Redecl;
189 }
190
191 /// Sets whether tag declarations should be hidden by non-tag
192 /// declarations during resolution. The default is true.
193 void setHideTags(bool Hide) {
194 HideTags = Hide;
195 }
196
John McCall7d384dd2009-11-18 07:57:50 +0000197 bool isAmbiguous() const {
198 return getResultKind() == Ambiguous;
199 }
200
John McCall68263142009-11-18 22:49:29 +0000201 /// Determines if this names a single result which is not an
202 /// unresolved value using decl. If so, it is safe to call
203 /// getFoundDecl().
204 bool isSingleResult() const {
205 return getResultKind() == Found;
206 }
207
John McCall7453ed42009-11-22 00:44:51 +0000208 /// Determines if the results are overloaded.
209 bool isOverloadedResult() const {
210 return getResultKind() == FoundOverloaded;
211 }
212
John McCall129e2df2009-11-30 22:42:35 +0000213 bool isUnresolvableResult() const {
214 return getResultKind() == FoundUnresolvedValue;
215 }
216
John McCall7d384dd2009-11-18 07:57:50 +0000217 LookupResultKind getResultKind() const {
218 sanity();
219 return ResultKind;
220 }
221
222 AmbiguityKind getAmbiguityKind() const {
223 assert(isAmbiguous());
224 return Ambiguity;
225 }
226
227 iterator begin() const { return Decls.begin(); }
228 iterator end() const { return Decls.end(); }
229
230 /// \brief Return true if no decls were found
231 bool empty() const { return Decls.empty(); }
232
233 /// \brief Return the base paths structure that's associated with
234 /// these results, or null if none is.
235 CXXBasePaths *getBasePaths() const {
236 return Paths;
237 }
238
John McCall1d7c5282009-12-18 10:40:03 +0000239 /// \brief Tests whether the given declaration is acceptable.
240 bool isAcceptableDecl(NamedDecl *D) const {
241 assert(IsAcceptableFn);
242 return IsAcceptableFn(D, IDNS);
243 }
244
245 /// \brief Returns the identifier namespace mask for this lookup.
246 unsigned getIdentifierNamespace() const {
247 return IDNS;
248 }
249
250 /// \brief Add a declaration to these results. Does not test the
251 /// acceptance criteria.
John McCall7d384dd2009-11-18 07:57:50 +0000252 void addDecl(NamedDecl *D) {
253 Decls.push_back(D);
254 ResultKind = Found;
255 }
256
257 /// \brief Add all the declarations from another set of lookup
258 /// results.
259 void addAllDecls(const LookupResult &Other) {
260 Decls.append(Other.begin(), Other.end());
261 ResultKind = Found;
262 }
263
264 /// \brief Hides a set of declarations.
265 template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) {
266 unsigned I = 0, N = Decls.size();
267 while (I < N) {
268 if (Set.count(Decls[I]))
269 Decls[I] = Decls[--N];
270 else
271 I++;
272 }
273 Decls.set_size(N);
274 }
275
Douglas Gregor7d3f5762010-01-15 01:44:47 +0000276 /// \brief Determine whether no result was found because we could not
277 /// search into dependent base classes of the current instantiation.
278 bool wasNotFoundInCurrentInstantiation() const {
279 return ResultKind == NotFoundInCurrentInstantiation;
280 }
281
282 /// \brief Note that while no result was found in the current instantiation,
283 /// there were dependent base classes that could not be searched.
284 void setNotFoundInCurrentInstantiation() {
285 assert(ResultKind == NotFound && Decls.empty());
286 ResultKind = NotFoundInCurrentInstantiation;
287 }
288
John McCall68263142009-11-18 22:49:29 +0000289 /// \brief Resolves the result kind of the lookup, possibly hiding
290 /// decls.
John McCall7d384dd2009-11-18 07:57:50 +0000291 ///
292 /// This should be called in any environment where lookup might
293 /// generate multiple lookup results.
294 void resolveKind();
295
John McCall68263142009-11-18 22:49:29 +0000296 /// \brief Re-resolves the result kind of the lookup after a set of
297 /// removals has been performed.
298 void resolveKindAfterFilter() {
Douglas Gregor7d3f5762010-01-15 01:44:47 +0000299 if (Decls.empty()) {
300 if (ResultKind != NotFoundInCurrentInstantiation)
301 ResultKind = NotFound;
302 } else {
John McCall68263142009-11-18 22:49:29 +0000303 ResultKind = Found;
304 resolveKind();
305 }
306 }
307
John McCallba135432009-11-21 08:51:07 +0000308 template <class DeclClass>
309 DeclClass *getAsSingle() const {
310 if (getResultKind() != Found) return 0;
311 return dyn_cast<DeclClass>(getFoundDecl());
312 }
313
John McCall7d384dd2009-11-18 07:57:50 +0000314 /// \brief Fetch the unique decl found by this lookup. Asserts
315 /// that one was found.
316 ///
317 /// This is intended for users who have examined the result kind
318 /// and are certain that there is only one result.
319 NamedDecl *getFoundDecl() const {
320 assert(getResultKind() == Found
321 && "getFoundDecl called on non-unique result");
322 return Decls[0]->getUnderlyingDecl();
323 }
324
John McCall68263142009-11-18 22:49:29 +0000325 /// Fetches a representative decl. Useful for lazy diagnostics.
326 NamedDecl *getRepresentativeDecl() const {
327 assert(!Decls.empty() && "cannot get representative of empty set");
328 return Decls[0];
329 }
330
John McCall7d384dd2009-11-18 07:57:50 +0000331 /// \brief Asks if the result is a single tag decl.
332 bool isSingleTagDecl() const {
333 return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
334 }
335
336 /// \brief Make these results show that the name was found in
337 /// base classes of different types.
338 ///
339 /// The given paths object is copied and invalidated.
340 void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
341
342 /// \brief Make these results show that the name was found in
343 /// distinct base classes of the same type.
344 ///
345 /// The given paths object is copied and invalidated.
346 void setAmbiguousBaseSubobjects(CXXBasePaths &P);
347
348 /// \brief Make these results show that the name was found in
349 /// different contexts and a tag decl was hidden by an ordinary
350 /// decl in a different context.
351 void setAmbiguousQualifiedTagHiding() {
352 setAmbiguous(AmbiguousTagHiding);
353 }
354
355 /// \brief Clears out any current state.
356 void clear() {
357 ResultKind = NotFound;
358 Decls.clear();
359 if (Paths) deletePaths(Paths);
360 Paths = NULL;
361 }
362
363 /// \brief Clears out any current state and re-initializes for a
364 /// different kind of lookup.
365 void clear(Sema::LookupNameKind Kind) {
366 clear();
367 LookupKind = Kind;
John McCall1d7c5282009-12-18 10:40:03 +0000368 configure();
John McCall7d384dd2009-11-18 07:57:50 +0000369 }
370
371 void print(llvm::raw_ostream &);
372
373 /// Suppress the diagnostics that would normally fire because of this
374 /// lookup. This happens during (e.g.) redeclaration lookups.
375 void suppressDiagnostics() {
376 Diagnose = false;
377 }
378
379 /// Sets a 'context' source range.
380 void setContextRange(SourceRange SR) {
381 NameContextRange = SR;
382 }
383
384 /// Gets the source range of the context of this name; for C++
385 /// qualified lookups, this is the source range of the scope
386 /// specifier.
387 SourceRange getContextRange() const {
388 return NameContextRange;
389 }
390
391 /// Gets the location of the identifier. This isn't always defined:
392 /// sometimes we're doing lookups on synthesized names.
393 SourceLocation getNameLoc() const {
394 return NameLoc;
395 }
396
Douglas Gregor546be3c2009-12-30 17:04:44 +0000397 /// \brief Get the Sema object that this lookup result is searching
398 /// with.
399 Sema &getSema() const { return SemaRef; }
400
John McCall68263142009-11-18 22:49:29 +0000401 /// A class for iterating through a result set and possibly
402 /// filtering out results. The results returned are possibly
403 /// sugared.
404 class Filter {
405 LookupResult &Results;
406 unsigned I;
John McCallf7a1a742009-11-24 19:00:30 +0000407 bool Changed;
John McCall68263142009-11-18 22:49:29 +0000408#ifndef NDEBUG
409 bool CalledDone;
410#endif
411
412 friend class LookupResult;
413 Filter(LookupResult &Results)
John McCallf7a1a742009-11-24 19:00:30 +0000414 : Results(Results), I(0), Changed(false)
John McCall68263142009-11-18 22:49:29 +0000415#ifndef NDEBUG
416 , CalledDone(false)
417#endif
418 {}
419
420 public:
421#ifndef NDEBUG
422 ~Filter() {
423 assert(CalledDone &&
424 "LookupResult::Filter destroyed without done() call");
425 }
426#endif
427
428 bool hasNext() const {
429 return I != Results.Decls.size();
430 }
431
432 NamedDecl *next() {
433 assert(I < Results.Decls.size() && "next() called on empty filter");
434 return Results.Decls[I++];
435 }
436
437 /// Erase the last element returned from this iterator.
438 void erase() {
439 Results.Decls[--I] = Results.Decls.back();
440 Results.Decls.pop_back();
John McCallf7a1a742009-11-24 19:00:30 +0000441 Changed = true;
442 }
443
444 void replace(NamedDecl *D) {
445 Results.Decls[I-1] = D;
446 Changed = true;
John McCall68263142009-11-18 22:49:29 +0000447 }
448
449 void done() {
450#ifndef NDEBUG
451 assert(!CalledDone && "done() called twice");
452 CalledDone = true;
453#endif
454
John McCallf7a1a742009-11-24 19:00:30 +0000455 if (Changed)
John McCall68263142009-11-18 22:49:29 +0000456 Results.resolveKindAfterFilter();
457 }
458 };
459
460 /// Create a filter for this result set.
461 Filter makeFilter() {
462 return Filter(*this);
463 }
464
John McCall7d384dd2009-11-18 07:57:50 +0000465private:
466 void diagnose() {
467 if (isAmbiguous())
468 SemaRef.DiagnoseAmbiguousLookup(*this);
469 }
470
471 void setAmbiguous(AmbiguityKind AK) {
472 ResultKind = Ambiguous;
473 Ambiguity = AK;
474 }
475
476 void addDeclsFromBasePaths(const CXXBasePaths &P);
John McCall1d7c5282009-12-18 10:40:03 +0000477 void configure();
John McCall7d384dd2009-11-18 07:57:50 +0000478
479 // Sanity checks.
480 void sanity() const {
481 assert(ResultKind != NotFound || Decls.size() == 0);
482 assert(ResultKind != Found || Decls.size() == 1);
John McCall7453ed42009-11-22 00:44:51 +0000483 assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
John McCall97d9e212009-11-22 20:57:36 +0000484 (Decls.size() == 1 &&
485 isa<FunctionTemplateDecl>(Decls[0]->getUnderlyingDecl())));
John McCall7453ed42009-11-22 00:44:51 +0000486 assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
487 assert(ResultKind != Ambiguous || Decls.size() > 1 ||
488 (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects));
John McCall7d384dd2009-11-18 07:57:50 +0000489 assert((Paths != NULL) == (ResultKind == Ambiguous &&
490 (Ambiguity == AmbiguousBaseSubobjectTypes ||
491 Ambiguity == AmbiguousBaseSubobjects)));
492 }
493
John McCall7453ed42009-11-22 00:44:51 +0000494 bool sanityCheckUnresolved() const {
495 for (DeclsTy::const_iterator I = Decls.begin(), E = Decls.end();
496 I != E; ++I)
497 if (isa<UnresolvedUsingValueDecl>(*I))
498 return true;
499 return false;
500 }
501
John McCall7d384dd2009-11-18 07:57:50 +0000502 static void deletePaths(CXXBasePaths *);
503
504 // Results.
505 LookupResultKind ResultKind;
506 AmbiguityKind Ambiguity; // ill-defined unless ambiguous
507 DeclsTy Decls;
508 CXXBasePaths *Paths;
509
510 // Parameters.
511 Sema &SemaRef;
512 DeclarationName Name;
513 SourceLocation NameLoc;
514 SourceRange NameContextRange;
515 Sema::LookupNameKind LookupKind;
John McCall1d7c5282009-12-18 10:40:03 +0000516 ResultFilter IsAcceptableFn; // set by configure()
517 unsigned IDNS; // set by configure()
518
John McCall7d384dd2009-11-18 07:57:50 +0000519 bool Redecl;
520
521 /// \brief True if tag declarations should be hidden if non-tags
522 /// are present
523 bool HideTags;
524
525 bool Diagnose;
526};
527
Douglas Gregor546be3c2009-12-30 17:04:44 +0000528 /// \brief Consumes visible declarations found when searching for
529 /// all visible names within a given scope or context.
530 ///
531 /// This abstract class is meant to be subclassed by clients of \c
532 /// Sema::LookupVisibleDecls(), each of which should override the \c
533 /// FoundDecl() function to process declarations as they are found.
534 class VisibleDeclConsumer {
535 public:
536 /// \brief Destroys the visible declaration consumer.
537 virtual ~VisibleDeclConsumer();
538
539 /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
540 /// declaration visible from the current scope or context.
541 ///
542 /// \param ND the declaration found.
543 ///
544 /// \param Hiding a declaration that hides the declaration \p ND,
545 /// or NULL if no such declaration exists.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000546 ///
547 /// \param InBaseClass whether this declaration was found in base
548 /// class of the context we searched.
549 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
550 bool InBaseClass) = 0;
Douglas Gregor546be3c2009-12-30 17:04:44 +0000551 };
John McCall7d384dd2009-11-18 07:57:50 +0000552}
553
554#endif