blob: 6e72dcef161a8b83483dacbdc8a8466617c102bf [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
204 LookupResultKind getResultKind() const {
205 sanity();
206 return ResultKind;
207 }
208
209 AmbiguityKind getAmbiguityKind() const {
210 assert(isAmbiguous());
211 return Ambiguity;
212 }
213
214 iterator begin() const { return Decls.begin(); }
215 iterator end() const { return Decls.end(); }
216
217 /// \brief Return true if no decls were found
218 bool empty() const { return Decls.empty(); }
219
220 /// \brief Return the base paths structure that's associated with
221 /// these results, or null if none is.
222 CXXBasePaths *getBasePaths() const {
223 return Paths;
224 }
225
226 /// \brief Add a declaration to these results.
227 void addDecl(NamedDecl *D) {
228 Decls.push_back(D);
229 ResultKind = Found;
230 }
231
232 /// \brief Add all the declarations from another set of lookup
233 /// results.
234 void addAllDecls(const LookupResult &Other) {
235 Decls.append(Other.begin(), Other.end());
236 ResultKind = Found;
237 }
238
239 /// \brief Hides a set of declarations.
240 template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) {
241 unsigned I = 0, N = Decls.size();
242 while (I < N) {
243 if (Set.count(Decls[I]))
244 Decls[I] = Decls[--N];
245 else
246 I++;
247 }
248 Decls.set_size(N);
249 }
250
251 /// \brief Resolves the kind of the lookup, possibly hiding decls.
252 ///
253 /// This should be called in any environment where lookup might
254 /// generate multiple lookup results.
255 void resolveKind();
256
257 /// \brief Fetch this as an unambiguous single declaration
258 /// (possibly an overloaded one).
259 ///
260 /// This is deprecated; users should be written to handle
261 /// ambiguous and overloaded lookups.
262 NamedDecl *getAsSingleDecl(ASTContext &Context) const;
263
264 /// \brief Fetch the unique decl found by this lookup. Asserts
265 /// that one was found.
266 ///
267 /// This is intended for users who have examined the result kind
268 /// and are certain that there is only one result.
269 NamedDecl *getFoundDecl() const {
270 assert(getResultKind() == Found
271 && "getFoundDecl called on non-unique result");
272 return Decls[0]->getUnderlyingDecl();
273 }
274
275 /// \brief Asks if the result is a single tag decl.
276 bool isSingleTagDecl() const {
277 return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
278 }
279
280 /// \brief Make these results show that the name was found in
281 /// base classes of different types.
282 ///
283 /// The given paths object is copied and invalidated.
284 void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
285
286 /// \brief Make these results show that the name was found in
287 /// distinct base classes of the same type.
288 ///
289 /// The given paths object is copied and invalidated.
290 void setAmbiguousBaseSubobjects(CXXBasePaths &P);
291
292 /// \brief Make these results show that the name was found in
293 /// different contexts and a tag decl was hidden by an ordinary
294 /// decl in a different context.
295 void setAmbiguousQualifiedTagHiding() {
296 setAmbiguous(AmbiguousTagHiding);
297 }
298
299 /// \brief Clears out any current state.
300 void clear() {
301 ResultKind = NotFound;
302 Decls.clear();
303 if (Paths) deletePaths(Paths);
304 Paths = NULL;
305 }
306
307 /// \brief Clears out any current state and re-initializes for a
308 /// different kind of lookup.
309 void clear(Sema::LookupNameKind Kind) {
310 clear();
311 LookupKind = Kind;
312 }
313
314 void print(llvm::raw_ostream &);
315
316 /// Suppress the diagnostics that would normally fire because of this
317 /// lookup. This happens during (e.g.) redeclaration lookups.
318 void suppressDiagnostics() {
319 Diagnose = false;
320 }
321
322 /// Sets a 'context' source range.
323 void setContextRange(SourceRange SR) {
324 NameContextRange = SR;
325 }
326
327 /// Gets the source range of the context of this name; for C++
328 /// qualified lookups, this is the source range of the scope
329 /// specifier.
330 SourceRange getContextRange() const {
331 return NameContextRange;
332 }
333
334 /// Gets the location of the identifier. This isn't always defined:
335 /// sometimes we're doing lookups on synthesized names.
336 SourceLocation getNameLoc() const {
337 return NameLoc;
338 }
339
340private:
341 void diagnose() {
342 if (isAmbiguous())
343 SemaRef.DiagnoseAmbiguousLookup(*this);
344 }
345
346 void setAmbiguous(AmbiguityKind AK) {
347 ResultKind = Ambiguous;
348 Ambiguity = AK;
349 }
350
351 void addDeclsFromBasePaths(const CXXBasePaths &P);
352
353 // Sanity checks.
354 void sanity() const {
355 assert(ResultKind != NotFound || Decls.size() == 0);
356 assert(ResultKind != Found || Decls.size() == 1);
357 assert(ResultKind == NotFound || ResultKind == Found ||
358 ResultKind == FoundUnresolvedValue ||
359 (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
360 || Decls.size() > 1);
361 assert((Paths != NULL) == (ResultKind == Ambiguous &&
362 (Ambiguity == AmbiguousBaseSubobjectTypes ||
363 Ambiguity == AmbiguousBaseSubobjects)));
364 }
365
366 static void deletePaths(CXXBasePaths *);
367
368 // Results.
369 LookupResultKind ResultKind;
370 AmbiguityKind Ambiguity; // ill-defined unless ambiguous
371 DeclsTy Decls;
372 CXXBasePaths *Paths;
373
374 // Parameters.
375 Sema &SemaRef;
376 DeclarationName Name;
377 SourceLocation NameLoc;
378 SourceRange NameContextRange;
379 Sema::LookupNameKind LookupKind;
380 unsigned IDNS; // ill-defined until set by lookup
381 bool Redecl;
382
383 /// \brief True if tag declarations should be hidden if non-tags
384 /// are present
385 bool HideTags;
386
387 bool Diagnose;
388};
389
390}
391
392#endif