blob: 6366a4c854651aa22efded73100eacf79086e729 [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
John McCallba135432009-11-21 08:51:07 +0000283 template <class DeclClass>
284 DeclClass *getAsSingle() const {
285 if (getResultKind() != Found) return 0;
286 return dyn_cast<DeclClass>(getFoundDecl());
287 }
288
John McCall7d384dd2009-11-18 07:57:50 +0000289 /// \brief Fetch the unique decl found by this lookup. Asserts
290 /// that one was found.
291 ///
292 /// This is intended for users who have examined the result kind
293 /// and are certain that there is only one result.
294 NamedDecl *getFoundDecl() const {
295 assert(getResultKind() == Found
296 && "getFoundDecl called on non-unique result");
297 return Decls[0]->getUnderlyingDecl();
298 }
299
John McCall68263142009-11-18 22:49:29 +0000300 /// Fetches a representative decl. Useful for lazy diagnostics.
301 NamedDecl *getRepresentativeDecl() const {
302 assert(!Decls.empty() && "cannot get representative of empty set");
303 return Decls[0];
304 }
305
John McCall7d384dd2009-11-18 07:57:50 +0000306 /// \brief Asks if the result is a single tag decl.
307 bool isSingleTagDecl() const {
308 return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
309 }
310
311 /// \brief Make these results show that the name was found in
312 /// base classes of different types.
313 ///
314 /// The given paths object is copied and invalidated.
315 void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
316
317 /// \brief Make these results show that the name was found in
318 /// distinct base classes of the same type.
319 ///
320 /// The given paths object is copied and invalidated.
321 void setAmbiguousBaseSubobjects(CXXBasePaths &P);
322
323 /// \brief Make these results show that the name was found in
324 /// different contexts and a tag decl was hidden by an ordinary
325 /// decl in a different context.
326 void setAmbiguousQualifiedTagHiding() {
327 setAmbiguous(AmbiguousTagHiding);
328 }
329
330 /// \brief Clears out any current state.
331 void clear() {
332 ResultKind = NotFound;
333 Decls.clear();
334 if (Paths) deletePaths(Paths);
335 Paths = NULL;
336 }
337
338 /// \brief Clears out any current state and re-initializes for a
339 /// different kind of lookup.
340 void clear(Sema::LookupNameKind Kind) {
341 clear();
342 LookupKind = Kind;
343 }
344
345 void print(llvm::raw_ostream &);
346
347 /// Suppress the diagnostics that would normally fire because of this
348 /// lookup. This happens during (e.g.) redeclaration lookups.
349 void suppressDiagnostics() {
350 Diagnose = false;
351 }
352
353 /// Sets a 'context' source range.
354 void setContextRange(SourceRange SR) {
355 NameContextRange = SR;
356 }
357
358 /// Gets the source range of the context of this name; for C++
359 /// qualified lookups, this is the source range of the scope
360 /// specifier.
361 SourceRange getContextRange() const {
362 return NameContextRange;
363 }
364
365 /// Gets the location of the identifier. This isn't always defined:
366 /// sometimes we're doing lookups on synthesized names.
367 SourceLocation getNameLoc() const {
368 return NameLoc;
369 }
370
John McCall68263142009-11-18 22:49:29 +0000371 /// A class for iterating through a result set and possibly
372 /// filtering out results. The results returned are possibly
373 /// sugared.
374 class Filter {
375 LookupResult &Results;
376 unsigned I;
377 bool ErasedAny;
378#ifndef NDEBUG
379 bool CalledDone;
380#endif
381
382 friend class LookupResult;
383 Filter(LookupResult &Results)
384 : Results(Results), I(0), ErasedAny(false)
385#ifndef NDEBUG
386 , CalledDone(false)
387#endif
388 {}
389
390 public:
391#ifndef NDEBUG
392 ~Filter() {
393 assert(CalledDone &&
394 "LookupResult::Filter destroyed without done() call");
395 }
396#endif
397
398 bool hasNext() const {
399 return I != Results.Decls.size();
400 }
401
402 NamedDecl *next() {
403 assert(I < Results.Decls.size() && "next() called on empty filter");
404 return Results.Decls[I++];
405 }
406
407 /// Erase the last element returned from this iterator.
408 void erase() {
409 Results.Decls[--I] = Results.Decls.back();
410 Results.Decls.pop_back();
411 ErasedAny = true;
412 }
413
414 void done() {
415#ifndef NDEBUG
416 assert(!CalledDone && "done() called twice");
417 CalledDone = true;
418#endif
419
420 if (ErasedAny)
421 Results.resolveKindAfterFilter();
422 }
423 };
424
425 /// Create a filter for this result set.
426 Filter makeFilter() {
427 return Filter(*this);
428 }
429
John McCall7d384dd2009-11-18 07:57:50 +0000430private:
431 void diagnose() {
432 if (isAmbiguous())
433 SemaRef.DiagnoseAmbiguousLookup(*this);
434 }
435
436 void setAmbiguous(AmbiguityKind AK) {
437 ResultKind = Ambiguous;
438 Ambiguity = AK;
439 }
440
441 void addDeclsFromBasePaths(const CXXBasePaths &P);
442
443 // Sanity checks.
444 void sanity() const {
445 assert(ResultKind != NotFound || Decls.size() == 0);
446 assert(ResultKind != Found || Decls.size() == 1);
447 assert(ResultKind == NotFound || ResultKind == Found ||
448 ResultKind == FoundUnresolvedValue ||
449 (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
450 || Decls.size() > 1);
451 assert((Paths != NULL) == (ResultKind == Ambiguous &&
452 (Ambiguity == AmbiguousBaseSubobjectTypes ||
453 Ambiguity == AmbiguousBaseSubobjects)));
454 }
455
456 static void deletePaths(CXXBasePaths *);
457
458 // Results.
459 LookupResultKind ResultKind;
460 AmbiguityKind Ambiguity; // ill-defined unless ambiguous
461 DeclsTy Decls;
462 CXXBasePaths *Paths;
463
464 // Parameters.
465 Sema &SemaRef;
466 DeclarationName Name;
467 SourceLocation NameLoc;
468 SourceRange NameContextRange;
469 Sema::LookupNameKind LookupKind;
470 unsigned IDNS; // ill-defined until set by lookup
471 bool Redecl;
472
473 /// \brief True if tag declarations should be hidden if non-tags
474 /// are present
475 bool HideTags;
476
477 bool Diagnose;
478};
479
480}
481
482#endif