blob: 10cc818b8baa294c8f1d297734697b6934fcb0c6 [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.
29///
30/// Any non-ambiguous lookup can be converted into a single
31/// (possibly NULL) @c NamedDecl* via the getAsSingleDecl() method.
32/// This permits the common-case usage in C and Objective-C where
33/// name lookup will always return a single declaration. Use of
34/// this is largely deprecated; callers should handle the possibility
35/// of multiple declarations.
36class LookupResult {
37public:
38 enum LookupResultKind {
39 /// @brief No entity found met the criteria.
40 NotFound = 0,
41
42 /// @brief Name lookup found a single declaration that met the
43 /// criteria. getAsDecl will return this declaration.
44 Found,
45
46 /// @brief Name lookup found a set of overloaded functions that
47 /// met the criteria. getAsDecl will turn this set of overloaded
48 /// functions into an OverloadedFunctionDecl.
49 FoundOverloaded,
50
51 /// @brief Name lookup found an unresolvable value declaration
52 /// and cannot yet complete. This only happens in C++ dependent
53 /// contexts with dependent using declarations.
54 FoundUnresolvedValue,
55
56 /// @brief Name lookup results in an ambiguity; use
57 /// getAmbiguityKind to figure out what kind of ambiguity
58 /// we have.
59 Ambiguous
60 };
61
62 enum AmbiguityKind {
63 /// Name lookup results in an ambiguity because multiple
64 /// entities that meet the lookup criteria were found in
65 /// subobjects of different types. For example:
66 /// @code
67 /// struct A { void f(int); }
68 /// struct B { void f(double); }
69 /// struct C : A, B { };
70 /// void test(C c) {
71 /// c.f(0); // error: A::f and B::f come from subobjects of different
72 /// // types. overload resolution is not performed.
73 /// }
74 /// @endcode
75 AmbiguousBaseSubobjectTypes,
76
77 /// Name lookup results in an ambiguity because multiple
78 /// nonstatic entities that meet the lookup criteria were found
79 /// in different subobjects of the same type. For example:
80 /// @code
81 /// struct A { int x; };
82 /// struct B : A { };
83 /// struct C : A { };
84 /// struct D : B, C { };
85 /// int test(D d) {
86 /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
87 /// }
88 /// @endcode
89 AmbiguousBaseSubobjects,
90
91 /// Name lookup results in an ambiguity because multiple definitions
92 /// of entity that meet the lookup criteria were found in different
93 /// declaration contexts.
94 /// @code
95 /// namespace A {
96 /// int i;
97 /// namespace B { int i; }
98 /// int test() {
99 /// using namespace B;
100 /// return i; // error 'i' is found in namespace A and A::B
101 /// }
102 /// }
103 /// @endcode
104 AmbiguousReference,
105
106 /// Name lookup results in an ambiguity because an entity with a
107 /// tag name was hidden by an entity with an ordinary name from
108 /// a different context.
109 /// @code
110 /// namespace A { struct Foo {}; }
111 /// namespace B { void Foo(); }
112 /// namespace C {
113 /// using namespace A;
114 /// using namespace B;
115 /// }
116 /// void test() {
117 /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
118 /// // different namespace
119 /// }
120 /// @endcode
121 AmbiguousTagHiding
122 };
123
124 /// A little identifier for flagging temporary lookup results.
125 enum TemporaryToken {
126 Temporary
127 };
128
129 typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
130 typedef DeclsTy::const_iterator iterator;
131
132 LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
133 Sema::LookupNameKind LookupKind,
134 Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
135 : ResultKind(NotFound),
136 Paths(0),
137 SemaRef(SemaRef),
138 Name(Name),
139 NameLoc(NameLoc),
140 LookupKind(LookupKind),
141 IDNS(0),
142 Redecl(Redecl != Sema::NotForRedeclaration),
143 HideTags(true),
144 Diagnose(Redecl == Sema::NotForRedeclaration)
145 {}
146
147 /// Creates a temporary lookup result, initializing its core data
148 /// using the information from another result. Diagnostics are always
149 /// disabled.
150 LookupResult(TemporaryToken _, const LookupResult &Other)
151 : ResultKind(NotFound),
152 Paths(0),
153 SemaRef(Other.SemaRef),
154 Name(Other.Name),
155 NameLoc(Other.NameLoc),
156 LookupKind(Other.LookupKind),
157 IDNS(Other.IDNS),
158 Redecl(Other.Redecl),
159 HideTags(Other.HideTags),
160 Diagnose(false)
161 {}
162
163 ~LookupResult() {
164 if (Diagnose) diagnose();
165 if (Paths) deletePaths(Paths);
166 }
167
168 /// Gets the name to look up.
169 DeclarationName getLookupName() const {
170 return Name;
171 }
172
173 /// Gets the kind of lookup to perform.
174 Sema::LookupNameKind getLookupKind() const {
175 return LookupKind;
176 }
177
178 /// True if this lookup is just looking for an existing declaration.
179 bool isForRedeclaration() const {
180 return Redecl;
181 }
182
183 /// Sets whether tag declarations should be hidden by non-tag
184 /// declarations during resolution. The default is true.
185 void setHideTags(bool Hide) {
186 HideTags = Hide;
187 }
188
189 /// The identifier namespace of this lookup. This information is
190 /// private to the lookup routines.
191 unsigned getIdentifierNamespace() const {
192 assert(IDNS);
193 return IDNS;
194 }
195
196 void setIdentifierNamespace(unsigned NS) {
197 IDNS = NS;
198 }
199
200 bool isAmbiguous() const {
201 return getResultKind() == Ambiguous;
202 }
203
John McCall68263142009-11-18 22:49:29 +0000204 /// Determines if this names a single result which is not an
205 /// unresolved value using decl. If so, it is safe to call
206 /// getFoundDecl().
207 bool isSingleResult() const {
208 return getResultKind() == Found;
209 }
210
John McCall7d384dd2009-11-18 07:57:50 +0000211 LookupResultKind getResultKind() const {
212 sanity();
213 return ResultKind;
214 }
215
216 AmbiguityKind getAmbiguityKind() const {
217 assert(isAmbiguous());
218 return Ambiguity;
219 }
220
221 iterator begin() const { return Decls.begin(); }
222 iterator end() const { return Decls.end(); }
223
224 /// \brief Return true if no decls were found
225 bool empty() const { return Decls.empty(); }
226
227 /// \brief Return the base paths structure that's associated with
228 /// these results, or null if none is.
229 CXXBasePaths *getBasePaths() const {
230 return Paths;
231 }
232
233 /// \brief Add a declaration to these results.
234 void addDecl(NamedDecl *D) {
235 Decls.push_back(D);
236 ResultKind = Found;
237 }
238
239 /// \brief Add all the declarations from another set of lookup
240 /// results.
241 void addAllDecls(const LookupResult &Other) {
242 Decls.append(Other.begin(), Other.end());
243 ResultKind = Found;
244 }
245
246 /// \brief Hides a set of declarations.
247 template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) {
248 unsigned I = 0, N = Decls.size();
249 while (I < N) {
250 if (Set.count(Decls[I]))
251 Decls[I] = Decls[--N];
252 else
253 I++;
254 }
255 Decls.set_size(N);
256 }
257
John McCall68263142009-11-18 22:49:29 +0000258 /// \brief Resolves the result kind of the lookup, possibly hiding
259 /// decls.
John McCall7d384dd2009-11-18 07:57:50 +0000260 ///
261 /// This should be called in any environment where lookup might
262 /// generate multiple lookup results.
263 void resolveKind();
264
John McCall68263142009-11-18 22:49:29 +0000265 /// \brief Re-resolves the result kind of the lookup after a set of
266 /// removals has been performed.
267 void resolveKindAfterFilter() {
268 if (Decls.empty())
269 ResultKind = NotFound;
270 else {
271 ResultKind = Found;
272 resolveKind();
273 }
274 }
275
John McCall7d384dd2009-11-18 07:57:50 +0000276 /// \brief Fetch this as an unambiguous single declaration
277 /// (possibly an overloaded one).
278 ///
279 /// This is deprecated; users should be written to handle
280 /// ambiguous and overloaded lookups.
281 NamedDecl *getAsSingleDecl(ASTContext &Context) const;
282
283 /// \brief Fetch the unique decl found by this lookup. Asserts
284 /// that one was found.
285 ///
286 /// This is intended for users who have examined the result kind
287 /// and are certain that there is only one result.
288 NamedDecl *getFoundDecl() const {
289 assert(getResultKind() == Found
290 && "getFoundDecl called on non-unique result");
291 return Decls[0]->getUnderlyingDecl();
292 }
293
John McCall68263142009-11-18 22:49:29 +0000294 /// Fetches a representative decl. Useful for lazy diagnostics.
295 NamedDecl *getRepresentativeDecl() const {
296 assert(!Decls.empty() && "cannot get representative of empty set");
297 return Decls[0];
298 }
299
John McCall7d384dd2009-11-18 07:57:50 +0000300 /// \brief Asks if the result is a single tag decl.
301 bool isSingleTagDecl() const {
302 return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
303 }
304
305 /// \brief Make these results show that the name was found in
306 /// base classes of different types.
307 ///
308 /// The given paths object is copied and invalidated.
309 void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
310
311 /// \brief Make these results show that the name was found in
312 /// distinct base classes of the same type.
313 ///
314 /// The given paths object is copied and invalidated.
315 void setAmbiguousBaseSubobjects(CXXBasePaths &P);
316
317 /// \brief Make these results show that the name was found in
318 /// different contexts and a tag decl was hidden by an ordinary
319 /// decl in a different context.
320 void setAmbiguousQualifiedTagHiding() {
321 setAmbiguous(AmbiguousTagHiding);
322 }
323
324 /// \brief Clears out any current state.
325 void clear() {
326 ResultKind = NotFound;
327 Decls.clear();
328 if (Paths) deletePaths(Paths);
329 Paths = NULL;
330 }
331
332 /// \brief Clears out any current state and re-initializes for a
333 /// different kind of lookup.
334 void clear(Sema::LookupNameKind Kind) {
335 clear();
336 LookupKind = Kind;
337 }
338
339 void print(llvm::raw_ostream &);
340
341 /// Suppress the diagnostics that would normally fire because of this
342 /// lookup. This happens during (e.g.) redeclaration lookups.
343 void suppressDiagnostics() {
344 Diagnose = false;
345 }
346
347 /// Sets a 'context' source range.
348 void setContextRange(SourceRange SR) {
349 NameContextRange = SR;
350 }
351
352 /// Gets the source range of the context of this name; for C++
353 /// qualified lookups, this is the source range of the scope
354 /// specifier.
355 SourceRange getContextRange() const {
356 return NameContextRange;
357 }
358
359 /// Gets the location of the identifier. This isn't always defined:
360 /// sometimes we're doing lookups on synthesized names.
361 SourceLocation getNameLoc() const {
362 return NameLoc;
363 }
364
John McCall68263142009-11-18 22:49:29 +0000365 /// A class for iterating through a result set and possibly
366 /// filtering out results. The results returned are possibly
367 /// sugared.
368 class Filter {
369 LookupResult &Results;
370 unsigned I;
371 bool ErasedAny;
372#ifndef NDEBUG
373 bool CalledDone;
374#endif
375
376 friend class LookupResult;
377 Filter(LookupResult &Results)
378 : Results(Results), I(0), ErasedAny(false)
379#ifndef NDEBUG
380 , CalledDone(false)
381#endif
382 {}
383
384 public:
385#ifndef NDEBUG
386 ~Filter() {
387 assert(CalledDone &&
388 "LookupResult::Filter destroyed without done() call");
389 }
390#endif
391
392 bool hasNext() const {
393 return I != Results.Decls.size();
394 }
395
396 NamedDecl *next() {
397 assert(I < Results.Decls.size() && "next() called on empty filter");
398 return Results.Decls[I++];
399 }
400
401 /// Erase the last element returned from this iterator.
402 void erase() {
403 Results.Decls[--I] = Results.Decls.back();
404 Results.Decls.pop_back();
405 ErasedAny = true;
406 }
407
408 void done() {
409#ifndef NDEBUG
410 assert(!CalledDone && "done() called twice");
411 CalledDone = true;
412#endif
413
414 if (ErasedAny)
415 Results.resolveKindAfterFilter();
416 }
417 };
418
419 /// Create a filter for this result set.
420 Filter makeFilter() {
421 return Filter(*this);
422 }
423
John McCall7d384dd2009-11-18 07:57:50 +0000424private:
425 void diagnose() {
426 if (isAmbiguous())
427 SemaRef.DiagnoseAmbiguousLookup(*this);
428 }
429
430 void setAmbiguous(AmbiguityKind AK) {
431 ResultKind = Ambiguous;
432 Ambiguity = AK;
433 }
434
435 void addDeclsFromBasePaths(const CXXBasePaths &P);
436
437 // Sanity checks.
438 void sanity() const {
439 assert(ResultKind != NotFound || Decls.size() == 0);
440 assert(ResultKind != Found || Decls.size() == 1);
441 assert(ResultKind == NotFound || ResultKind == Found ||
442 ResultKind == FoundUnresolvedValue ||
443 (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
444 || Decls.size() > 1);
445 assert((Paths != NULL) == (ResultKind == Ambiguous &&
446 (Ambiguity == AmbiguousBaseSubobjectTypes ||
447 Ambiguity == AmbiguousBaseSubobjects)));
448 }
449
450 static void deletePaths(CXXBasePaths *);
451
452 // Results.
453 LookupResultKind ResultKind;
454 AmbiguityKind Ambiguity; // ill-defined unless ambiguous
455 DeclsTy Decls;
456 CXXBasePaths *Paths;
457
458 // Parameters.
459 Sema &SemaRef;
460 DeclarationName Name;
461 SourceLocation NameLoc;
462 SourceRange NameContextRange;
463 Sema::LookupNameKind LookupKind;
464 unsigned IDNS; // ill-defined until set by lookup
465 bool Redecl;
466
467 /// \brief True if tag declarations should be hidden if non-tags
468 /// are present
469 bool HideTags;
470
471 bool Diagnose;
472};
473
474}
475
476#endif