SemaExprObjC.cpp
SemaInherit.cpp
SemaInit.cpp
+ SemaLookup.cpp
SemaNamedCast.cpp
SemaOverload.cpp
SemaStmt.cpp
return *this;
}
+ uintptr_t getAsOpaqueValue() const { return Ptr; }
+
+ static iterator getFromOpaqueValue(uintptr_t P) {
+ iterator Result(0);
+ Result.Ptr = P;
+ return Result;
+ }
+
private:
void PreIncIter();
};
#include "IdentifierResolver.h"
#include "CXXFieldCollector.h"
#include "SemaOverload.h"
+#include "clang/AST/DeclBase.h"
#include "clang/Parse/Action.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallVector.h"
Scope *getNonFieldDeclScope(Scope *S);
- /// More parsing and symbol table subroutines.
- Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
- const DeclContext *LookupCtx = 0,
- bool enableLazyBuiltinCreation = true,
- bool LookInParent = true,
- bool NamespaceNameOnly = false);
-
- Decl *LookupNamespaceName(DeclarationName Name, Scope *S,
- const DeclContext *LookupCtx) {
- return LookupDecl(Name, Decl::IDNS_Tag | Decl::IDNS_Ordinary, S,
- LookupCtx,
- /* enableLazyBuiltinCreation */ false,
- /* LookInParent */ true,
- /* NamespaceNameOnly */ true);
- }
+ /// \name Name lookup
+ ///
+ /// These routines provide name lookup that is used during semantic
+ /// analysis to resolve the various kinds of names (identifiers,
+ /// overloaded operator names, constructor names, etc.) into zero or
+ /// more declarations within a particular scope. The major entry
+ /// points are LookupName, which performs unqualified name lookup,
+ /// and LookupQualifiedName, which performs qualified name lookup.
+ ///
+ /// All name lookup is performed based on some specific criteria,
+ /// which specify what names will be visible to name lookup and how
+ /// far name lookup should work. These criteria are important both
+ /// for capturing language semantics (certain lookups will ignore
+ /// certain names, for example) and for performance, since name
+ /// lookup is often a bottleneck in the compilation of C++. Name
+ /// lookup criteria is specified via the LookupCriteria class.
+ ///
+ /// The results of name lookup can vary based on the kind of name
+ /// lookup performed, the current language, and the translation
+ /// unit. In C, for example, name lookup will either return nothing
+ /// (no entity found) or a single declaration. In C++, name lookup
+ /// can additionally refer to a set of overloaded functions or
+ /// result in an ambiguity. All of the possible results of name
+ /// lookup are captured by the LookupResult class, which provides
+ /// the ability to distinguish among them.
+ //@{
+
+ /// @brief Describes the criteria by which name lookup will
+ /// determine whether a given name will be found.
+ ///
+ /// The LookupCriteria class captures the information required to
+ /// direct name lookup to find the appropriate kind of name. It
+ /// includes information about which kinds of names to consider
+ /// (ordinary names, tag names, class/struct/union member names,
+ /// namespace names, etc.) and where to look for those
+ /// names. LookupCriteria is used throughout semantic analysis to
+ /// specify how to search for a name, e.g., with the LookupName and
+ /// LookupQualifiedName functions.
+ struct LookupCriteria {
+ /// NameKind - The kinds of names that we are looking for.
+ enum NameKind {
+ /// Ordinary - Ordinary name lookup, which finds ordinary names
+ /// (functions, variables, typedefs, etc.) in C and most kinds
+ /// of names (functions, variables, members, types, etc.) in
+ /// C++.
+ Ordinary,
+ /// Tag - Tag name lookup, which finds the names of enums,
+ /// classes, structs, and unions.
+ Tag,
+ /// Member - Member name lookup, which finds the names of
+ /// class/struct/union members.
+ Member,
+ /// NestedNameSpecifier - Look up of a name that precedes the
+ /// '::' scope resolution operator in C++. This lookup
+ /// completely ignores operator, function, and enumerator names
+ /// (C++ [basic.lookup.qual]p1).
+ NestedNameSpecifier,
+ /// Namespace - Look up a namespace name within a C++
+ /// using directive or namespace alias definition, ignoring
+ /// non-namespace names (C++ [basic.lookup.udir]p1).
+ Namespace
+ } Kind;
+
+ /// AllowLazyBuiltinCreation - If true, permits name lookup to
+ /// lazily build declarations for built-in names, e.g.,
+ /// __builtin_expect.
+ bool AllowLazyBuiltinCreation;
+
+ /// RedeclarationOnly - If true, the lookup will only
+ /// consider entities within the scope where the lookup
+ /// began. Entities that might otherwise meet the lookup criteria
+ /// but are not within the original lookup scope will be ignored.
+ bool RedeclarationOnly;
+
+ /// IDNS - Bitwise OR of the appropriate Decl::IDNS_* flags that
+ /// describe the namespaces where we should look for names. This
+ /// field is determined by the kind of name we're searching for.
+ unsigned IDNS;
+
+ LookupCriteria(NameKind K, bool RedeclarationOnly, bool CPlusPlus);
+
+ bool isLookupResult(Decl *D) const;
+ };
+
+ /// @brief Represents the results of name lookup.
+ ///
+ /// An instance of the LookupResult class captures the results of a
+ /// single name lookup, which can return no result (nothing found),
+ /// a single declaration, a set of overloaded functions, or an
+ /// ambiguity. Use the getKind() method to determine which of these
+ /// results occurred for a given lookup.
+ ///
+ /// Any non-ambiguous lookup can be converted into a single
+ /// (possibly NULL) @c Decl* via a conversion function or the
+ /// getAsDecl() method. This conversion permits the common-case
+ /// usage in C and Objective-C where name lookup will always return
+ /// a single declaration.
+ class LookupResult {
+ /// The kind of entity that is actually stored within the
+ /// LookupResult object.
+ mutable enum {
+ /// First is a single declaration (a Decl*), which may be NULL.
+ SingleDecl,
+ /// [First, Last) is an iterator range represented as opaque
+ /// pointers used to reconstruct IdentifierResolver::iterators.
+ OverloadedDeclFromIdResolver,
+ /// [First, Last) is an iterator range represented as opaque
+ /// pointers used to reconstruct DeclContext::lookup_iterators.
+ OverloadedDeclFromDeclContext,
+ /// FIXME: Cope with ambiguous name lookup.
+ AmbiguousLookup
+ } StoredKind;
+
+ /// The first lookup result, whose contents depend on the kind of
+ /// lookup result. This may be a Decl* (if StoredKind ==
+ /// SingleDecl), the opaque pointer from an
+ /// IdentifierResolver::iterator (if StoredKind ==
+ /// OverloadedDeclFromIdResolver), or a
+ /// DeclContext::lookup_iterator (if StoredKind ==
+ /// OverloadedDeclFromDeclContext).
+ mutable uintptr_t First;
+
+ /// The last lookup result, whose contents depend on the kind of
+ /// lookup result. This may be unused (if StoredKind ==
+ /// SingleDecl) or it may have the same type as First (for
+ /// overloaded function declarations).
+ mutable uintptr_t Last;
+
+ /// Context - The context in which we will build any
+ /// OverloadedFunctionDecl nodes needed by the conversion to
+ /// Decl*.
+ ASTContext *Context;
+
+ public:
+ /// @brief The kind of entity found by name lookup.
+ enum LookupKind {
+ /// @brief No entity found met the criteria.
+ NotFound = 0,
+ /// @brief Name lookup found a single declaration that met the
+ /// criteria.
+ Found,
+ /// @brief Name lookup found a set of overloaded functions that
+ /// met the criteria.
+ FoundOverloaded,
+ /// @brief Name lookup resulted in an ambiguity, e.g., because
+ /// the name was found in two different base classes.
+ Ambiguous
+ };
+
+ LookupResult(ASTContext &Context, Decl *D)
+ : StoredKind(SingleDecl), First(reinterpret_cast<uintptr_t>(D)),
+ Last(0), Context(&Context) { }
+
+ LookupResult(ASTContext &Context,
+ IdentifierResolver::iterator F, IdentifierResolver::iterator L)
+ : StoredKind(OverloadedDeclFromIdResolver),
+ First(F.getAsOpaqueValue()), Last(L.getAsOpaqueValue()),
+ Context(&Context) { }
+
+ LookupResult(ASTContext &Context,
+ DeclContext::lookup_iterator F, DeclContext::lookup_iterator L)
+ : StoredKind(OverloadedDeclFromDeclContext),
+ First(reinterpret_cast<uintptr_t>(F)),
+ Last(reinterpret_cast<uintptr_t>(L)),
+ Context(&Context) { }
+
+ LookupKind getKind() const;
+
+ /// @brief Determine whether name look found something.
+ operator bool() const { return getKind() != NotFound; }
+
+ /// @brief Allows conversion of a lookup result into a
+ /// declaration, with the same behavior as getAsDecl.
+ operator Decl*() const { return getAsDecl(); }
+
+ Decl* getAsDecl() const;
+ };
+
+ LookupResult LookupName(Scope *S, DeclarationName Name,
+ LookupCriteria Criteria);
+ LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
+ LookupCriteria Criteria);
+ LookupResult LookupParsedName(Scope *S, const CXXScopeSpec &SS,
+ DeclarationName Name, LookupCriteria Criteria);
+
+ LookupResult LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
+ const DeclContext *LookupCtx = 0,
+ bool enableLazyBuiltinCreation = true,
+ bool LookInParent = true,
+ bool NamespaceNameOnly = false);
+ //@}
+
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S);
ScopedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
Scope *S);
+
+ // More parsing and symbol table subroutines.
+
// Decl attributes - this routine is the top level dispatcher.
void ProcessDeclAttributes(Decl *D, const Declarator &PD);
void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList);
using namespace clang;\r
\r
\r
-namespace {\r
- Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,\r
- DeclarationName Name, bool &IdIsUndeclared,\r
- ASTContext &Context) {\r
- if (LookupCtx && !LookInParentCtx) {\r
- IdIsUndeclared = true;\r
- DeclContext::lookup_const_iterator I, E;\r
- for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) {\r
- IdIsUndeclared = false;\r
- if (((*I)->isInIdentifierNamespace(Decl::IDNS_Tag)) || \r
- isa<TypedefDecl>(*I))\r
- return *I;\r
- }\r
-\r
- return 0;\r
- }\r
-\r
- // FIXME: Decouple this from the IdentifierResolver so that we can\r
- // deal with lookups into the semantic parent contexts that aren't\r
- // lexical parent contexts.\r
-\r
- IdentifierResolver::iterator\r
- I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),\r
- E = IdentifierResolver::end();\r
-\r
- if (I == E) {\r
- IdIsUndeclared = true;\r
- return 0;\r
- }\r
- IdIsUndeclared = false;\r
-\r
- // C++ 3.4.3p1 :\r
- // During the lookup for a name preceding the :: scope resolution operator,\r
- // object, function, and enumerator names are ignored. If the name found is\r
- // not a class-name or namespace-name, the program is ill-formed.\r
-\r
- for (; I != E; ++I) {\r
- if (isa<TypedefDecl>(*I)) {\r
- break;\r
- }\r
- if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag))\r
- break; \r
- }\r
-\r
- return (I != E ? *I : 0);\r
- }\r
-} // anonymous namespace\r
-\r
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the\r
/// global scope ('::').\r
Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,\r
SourceLocation IdLoc,\r
SourceLocation CCLoc,\r
IdentifierInfo &II) {\r
- DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());\r
- Decl *SD;\r
- bool IdIsUndeclared;\r
-\r
- if (DC)\r
- SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared,\r
- Context);\r
- else\r
- SD = LookupNestedName(CurContext, true/*LookInParent*/, &II, \r
- IdIsUndeclared, Context);\r
+ Decl *SD = LookupParsedName(S, SS, &II,\r
+ LookupCriteria(LookupCriteria::NestedNameSpecifier, \r
+ /*RedeclarationOnly=*/false, \r
+ /*CPlusPlus=*/true));\r
\r
if (SD) {\r
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {\r
return cast<DeclContext>(SD);\r
}\r
\r
+ // FIXME: C++0x scoped enums\r
+\r
// Fall through to produce an error: we found something that isn't\r
// a class or a namespace.\r
}\r
\r
+ // If we didn't find anything during our lookup, try again with\r
+ // ordinary name lookup, which can help us produce better error\r
+ // messages.\r
+ if (!SD)\r
+ SD = LookupParsedName(S, SS, &II,\r
+ LookupCriteria(LookupCriteria::Ordinary,\r
+ /*RedeclarationOnly=*/false, \r
+ /*CPlusPlus=*/true));\r
unsigned DiagID;\r
- if (!IdIsUndeclared)\r
+ if (SD)\r
DiagID = diag::err_expected_class_or_namespace;\r
- else if (DC)\r
+ else if (SS.isSet())\r
DiagID = diag::err_typecheck_no_member;\r
else\r
DiagID = diag::err_undeclared_var_use;\r
\r
- if (DC)\r
+ if (SS.isSet())\r
Diag(IdLoc, DiagID) << &II << SS.getRange();\r
else\r
Diag(IdLoc, DiagID) << &II;\r
return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
}
-/// MaybeConstructOverloadSet - Name lookup has determined that the
-/// elements in [I, IEnd) have the name that we are looking for, and
-/// *I is a match for the namespace. This routine returns an
-/// appropriate Decl for name lookup, which may either be *I or an
-/// OverloadeFunctionDecl that represents the overloaded functions in
-/// [I, IEnd).
-///
-/// The existance of this routine is temporary; LookupDecl should
-/// probably be able to return multiple results, to deal with cases of
-/// ambiguity and overloaded functions without needing to create a
-/// Decl node.
-template<typename DeclIterator>
-static Decl *
-MaybeConstructOverloadSet(ASTContext &Context,
- DeclIterator I, DeclIterator IEnd) {
- assert(I != IEnd && "Iterator range cannot be empty");
- assert(!isa<OverloadedFunctionDecl>(*I) &&
- "Cannot have an overloaded function");
-
- if (isa<FunctionDecl>(*I)) {
- // If we found a function, there might be more functions. If
- // so, collect them into an overload set.
- DeclIterator Last = I;
- OverloadedFunctionDecl *Ovl = 0;
- for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
- if (!Ovl) {
- // FIXME: We leak this overload set. Eventually, we want to
- // stop building the declarations for these overload sets, so
- // there will be nothing to leak.
- Ovl = OverloadedFunctionDecl::Create(Context,
- cast<ScopedDecl>(*I)->getDeclContext(),
- (*I)->getDeclName());
- Ovl->addOverload(cast<FunctionDecl>(*I));
- }
- Ovl->addOverload(cast<FunctionDecl>(*Last));
- }
-
- // If we had more than one function, we built an overload
- // set. Return it.
- if (Ovl)
- return Ovl;
- }
-
- return *I;
-}
-
/// getNonFieldDeclScope - Retrieves the innermost scope, starting
/// from S, where a non-field would be declared. This routine copes
/// with the difference between C and C++ scoping rules in structs and
/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
/// 'When looking up a namespace-name in a using-directive or
/// namespace-alias-definition, only namespace names are considered.'
-Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
- const DeclContext *LookupCtx,
- bool enableLazyBuiltinCreation,
- bool LookInParent,
- bool NamespaceNameOnly) {
- if (!Name) return 0;
- unsigned NS = NSI;
-
- // In C++, ordinary and member lookup will always find all
- // kinds of names.
- if (getLangOptions().CPlusPlus &&
- (NS & (Decl::IDNS_Ordinary | Decl::IDNS_Member)))
- NS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Ordinary;
-
- if (LookupCtx == 0 && !getLangOptions().CPlusPlus) {
- // Unqualified name lookup in C/Objective-C is purely lexical, so
- // search in the declarations attached to the name.
- assert(!LookupCtx && "Can't perform qualified name lookup here");
- assert(!NamespaceNameOnly && "Can't perform namespace name lookup here");
-
- // For the purposes of unqualified name lookup, structs and unions
- // don't have scopes at all. For example:
- //
- // struct X {
- // struct T { int i; } x;
- // };
- //
- // void f() {
- // struct T t; // okay: T is defined lexically within X, but
- // // semantically at global scope
- // };
- //
- // FIXME: Is there a better way to deal with this?
- DeclContext *SearchCtx = CurContext;
- while (isa<RecordDecl>(SearchCtx) || isa<EnumDecl>(SearchCtx))
- SearchCtx = SearchCtx->getParent();
- IdentifierResolver::iterator I
- = IdResolver.begin(Name, SearchCtx, LookInParent);
-
- // Scan up the scope chain looking for a decl that matches this
- // identifier that is in the appropriate namespace. This search
- // should not take long, as shadowing of names is uncommon, and
- // deep shadowing is extremely uncommon.
- for (; I != IdResolver.end(); ++I)
- if ((*I)->isInIdentifierNamespace(NS))
- return *I;
- } else if (LookupCtx) {
- // If we're performing qualified name lookup (e.g., lookup into a
- // struct), find fields as part of ordinary name lookup.
- if (NS & Decl::IDNS_Ordinary)
- NS |= Decl::IDNS_Member;
-
- // Perform qualified name lookup into the LookupCtx.
- // FIXME: Will need to look into base classes and such.
- DeclContext::lookup_const_iterator I, E;
- for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I)
- if ((*I)->isInIdentifierNamespace(NS)) {
- // Ignore non-namespace names if we're only looking for namespaces.
- if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) continue;
-
- return MaybeConstructOverloadSet(Context, I, E);
- }
- } else {
- // Name lookup for ordinary names and tag names in C++ requires
- // looking into scopes that aren't strictly lexical, and
- // therefore we walk through the context as well as walking
- // through the scopes.
- IdentifierResolver::iterator
- I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
- IEnd = IdResolver.end();
- for (; S; S = S->getParent()) {
- // Check whether the IdResolver has anything in this scope.
- // FIXME: The isDeclScope check could be expensive. Can we do better?
- for (; I != IEnd && S->isDeclScope(*I); ++I) {
- if ((*I)->isInIdentifierNamespace(NS)) {
- // Ignore non-namespace names if we're only looking for namespaces.
- if (NamespaceNameOnly && !isa<NamespaceDecl>(*I))
- continue;
-
- // We found something. Look for anything else in our scope
- // with this same name and in an acceptable identifier
- // namespace, so that we can construct an overload set if we
- // need to.
- IdentifierResolver::iterator LastI = I;
- for (++LastI; LastI != IEnd; ++LastI) {
- if (!(*LastI)->isInIdentifierNamespace(NS) ||
- !S->isDeclScope(*LastI))
- break;
- }
- return MaybeConstructOverloadSet(Context, I, LastI);
- }
- }
-
- // If there is an entity associated with this scope, it's a
- // DeclContext. We might need to perform qualified lookup into
- // it.
- DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
- while (Ctx && Ctx->isFunctionOrMethod())
- Ctx = Ctx->getParent();
- while (Ctx && (Ctx->isNamespace() || Ctx->isRecord())) {
- // Look for declarations of this name in this scope.
- DeclContext::lookup_const_iterator I, E;
- for (llvm::tie(I, E) = Ctx->lookup(Name); I != E; ++I) {
- // FIXME: Cache this result in the IdResolver
- if ((*I)->isInIdentifierNamespace(NS)) {
- if (NamespaceNameOnly && !isa<NamespaceDecl>(*I))
- continue;
- return MaybeConstructOverloadSet(Context, I, E);
- }
- }
-
- if (!LookInParent && !Ctx->isTransparentContext())
- return 0;
+///
+/// Note: The use of this routine is deprecated. Please use
+/// LookupName, LookupQualifiedName, or LookupParsedName instead.
+Sema::LookupResult
+Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
+ const DeclContext *LookupCtx,
+ bool enableLazyBuiltinCreation,
+ bool LookInParent,
+ bool NamespaceNameOnly) {
+ LookupCriteria::NameKind Kind;
+ if (NSI == Decl::IDNS_Ordinary) {
+ if (NamespaceNameOnly)
+ Kind = LookupCriteria::Namespace;
+ else
+ Kind = LookupCriteria::Ordinary;
+ } else if (NSI == Decl::IDNS_Tag)
+ Kind = LookupCriteria::Tag;
+ else if (NSI == Decl::IDNS_Member)
+ Kind = LookupCriteria::Member;
+ else
+ assert(false && "Unable to grok LookupDecl NSI argument");
- Ctx = Ctx->getParent();
- }
- }
- }
+ if (LookupCtx)
+ return LookupQualifiedName(const_cast<DeclContext *>(LookupCtx), Name,
+ LookupCriteria(Kind, !LookInParent,
+ getLangOptions().CPlusPlus));
- // If we didn't find a use of this identifier, and if the identifier
- // corresponds to a compiler builtin, create the decl object for the builtin
- // now, injecting it into translation unit scope, and return it.
- if (NS & Decl::IDNS_Ordinary) {
- IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (enableLazyBuiltinCreation && II &&
- (LookupCtx == 0 || isa<TranslationUnitDecl>(LookupCtx))) {
- // If this is a builtin on this (or all) targets, create the decl.
- if (unsigned BuiltinID = II->getBuiltinID())
- return LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S);
- }
- if (getLangOptions().ObjC1 && II) {
- // @interface and @compatibility_alias introduce typedef-like names.
- // Unlike typedef's, they can only be introduced at file-scope (and are
- // therefore not scoped decls). They can, however, be shadowed by
- // other names in IDNS_Ordinary.
- ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
- if (IDI != ObjCInterfaceDecls.end())
- return IDI->second;
- ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
- if (I != ObjCAliasDecls.end())
- return I->second->getClassInterface();
- }
- }
- return 0;
+ // Unqualified lookup
+ return LookupName(S, Name,
+ LookupCriteria(Kind, !LookInParent,
+ getLangOptions().CPlusPlus));
}
void Sema::InitBuiltinVaListType() {
if (!StdNamespace) {
IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std");
DeclContext *Global = Context.getTranslationUnitDecl();
- Decl *Std = LookupDecl(StdIdent, Decl::IDNS_Tag | Decl::IDNS_Ordinary,
+ Decl *Std = LookupDecl(StdIdent, Decl::IDNS_Ordinary,
0, Global, /*enableLazyBuiltinCreation=*/false);
StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
}
DC = static_cast<DeclContext*>(SS.getScopeRep());
// Look-up name inside 'foo::'.
- PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC));
+ PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC)
+ .getAsDecl());
// A tag 'foo::bar' must already exist.
if (PrevDecl == 0) {
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
// Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
- PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S));
+ PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S)
+ .getAsDecl());
if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
// in that declarative region, it is treated as an original-namespace-name.
Decl *PrevDecl =
- LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
+ LookupDecl(II, Decl::IDNS_Ordinary, DeclRegionScope, 0,
/*enableLazyBuiltinCreation=*/false,
/*LookupInParent=*/false);
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
// FIXME: This still requires lot more checks, and AST support.
+
// Lookup namespace name.
- DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());
+ LookupCriteria Criteria(LookupCriteria::Namespace, /*RedeclarationOnly=*/false,
+ /*CPlusPlus=*/true);
+ Decl *NS = 0;
+ if (SS.isSet())
+ NS = LookupQualifiedName(static_cast<DeclContext*>(SS.getScopeRep()),
+ NamespcName, Criteria);
+ else
+ NS = LookupName(S, NamespcName, Criteria);
- if (Decl *NS = LookupNamespaceName(NamespcName, S, DC)) {
+ if (NS) {
assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
} else {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
FieldDecl *MemberDecl
= dyn_cast_or_null<FieldDecl>(LookupDecl(OC.U.IdentInfo,
Decl::IDNS_Ordinary,
- S, RD, false, false));
+ S, RD, false, false).getAsDecl());
if (!MemberDecl)
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
return Diag(OpLoc, diag::err_need_header_before_typeid);
IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
- Decl *TypeInfoDecl = LookupDecl(TypeInfoII,
- Decl::IDNS_Tag | Decl::IDNS_Ordinary,
+ Decl *TypeInfoDecl = LookupDecl(TypeInfoII, Decl::IDNS_Tag,
0, StdNs, /*createBuiltins=*/false);
RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl);
if (!TypeInfoRecordDecl)
--- /dev/null
+//===--------------------- SemaLookup.cpp - Name Lookup ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements name lookup for C, C++, Objective-C, and
+// Objective-C++.
+//
+//===----------------------------------------------------------------------===//
+#include "Sema.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+
+/// MaybeConstructOverloadSet - Name lookup has determined that the
+/// elements in [I, IEnd) have the name that we are looking for, and
+/// *I is a match for the namespace. This routine returns an
+/// appropriate Decl for name lookup, which may either be *I or an
+/// OverloadeFunctionDecl that represents the overloaded functions in
+/// [I, IEnd).
+///
+/// The existance of this routine is temporary; LookupDecl should
+/// probably be able to return multiple results, to deal with cases of
+/// ambiguity and overloaded functions without needing to create a
+/// Decl node.
+template<typename DeclIterator>
+static Decl *
+MaybeConstructOverloadSet(ASTContext &Context,
+ DeclIterator I, DeclIterator IEnd) {
+ assert(I != IEnd && "Iterator range cannot be empty");
+ assert(!isa<OverloadedFunctionDecl>(*I) &&
+ "Cannot have an overloaded function");
+
+ if (isa<FunctionDecl>(*I)) {
+ // If we found a function, there might be more functions. If
+ // so, collect them into an overload set.
+ DeclIterator Last = I;
+ OverloadedFunctionDecl *Ovl = 0;
+ for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
+ if (!Ovl) {
+ // FIXME: We leak this overload set. Eventually, we want to
+ // stop building the declarations for these overload sets, so
+ // there will be nothing to leak.
+ Ovl = OverloadedFunctionDecl::Create(Context,
+ cast<ScopedDecl>(*I)->getDeclContext(),
+ (*I)->getDeclName());
+ Ovl->addOverload(cast<FunctionDecl>(*I));
+ }
+ Ovl->addOverload(cast<FunctionDecl>(*Last));
+ }
+
+ // If we had more than one function, we built an overload
+ // set. Return it.
+ if (Ovl)
+ return Ovl;
+ }
+
+ return *I;
+}
+
+/// @brief Constructs name lookup criteria.
+///
+/// @param K The kind of name that we're searching for.
+///
+/// @param RedeclarationOnly If true, then name lookup will only look
+/// into the current scope for names, not in parent scopes. This
+/// option should be set when we're looking to introduce a new
+/// declaration into scope.
+///
+/// @param CPlusPlus Whether we are performing C++ name lookup or not.
+Sema::LookupCriteria::LookupCriteria(NameKind K, bool RedeclarationOnly,
+ bool CPlusPlus)
+ : Kind(K), AllowLazyBuiltinCreation(K == Ordinary),
+ RedeclarationOnly(RedeclarationOnly) {
+ switch (Kind) {
+ case Ordinary:
+ IDNS = Decl::IDNS_Ordinary;
+ if (CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
+ break;
+
+ case Tag:
+ IDNS = Decl::IDNS_Tag;
+ break;
+
+ case Member:
+ IDNS = Decl::IDNS_Member;
+ if (CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
+ break;
+
+ case NestedNameSpecifier:
+ case Namespace:
+ IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
+ break;
+ }
+}
+
+/// isLookupResult - Determines whether D is a suitable lookup result
+/// according to the lookup criteria.
+bool Sema::LookupCriteria::isLookupResult(Decl *D) const {
+ switch (Kind) {
+ case Ordinary:
+ case Tag:
+ case Member:
+ return D->isInIdentifierNamespace(IDNS);
+
+ case NestedNameSpecifier:
+ return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
+
+ case Namespace:
+ return isa<NamespaceDecl>(D);
+ }
+
+ assert(false && "isLookupResult always returns before this point");
+ return false;
+}
+
+/// @brief Determine the result of name lookup.
+Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const {
+ switch (StoredKind) {
+ case SingleDecl:
+ return (reinterpret_cast<Decl *>(First) != 0)? Found : NotFound;
+
+ case OverloadedDeclFromIdResolver:
+ case OverloadedDeclFromDeclContext:
+ return FoundOverloaded;
+
+ case AmbiguousLookup:
+ return Ambiguous;
+ }
+
+ // We can't get here, but GCC complains nonetheless.
+ return Ambiguous;
+}
+
+/// @brief Converts the result of name lookup into a single (possible
+/// NULL) pointer to a declaration.
+///
+/// The resulting declaration will either be the declaration we found
+/// (if only a single declaration was found), an
+/// OverloadedFunctionDecl (if an overloaded function was found), or
+/// NULL (if no declaration was found). This conversion must not be
+/// used anywhere where name lookup could result in an ambiguity.
+///
+/// The OverloadedFunctionDecl conversion is meant as a stop-gap
+/// solution, since it causes the OverloadedFunctionDecl to be
+/// leaked. FIXME: Eventually, there will be a better way to iterate
+/// over the set of overloaded functions returned by name lookup.
+Decl *Sema::LookupResult::getAsDecl() const {
+ switch (StoredKind) {
+ case SingleDecl:
+ return reinterpret_cast<Decl *>(First);
+
+ case OverloadedDeclFromIdResolver:
+ return MaybeConstructOverloadSet(*Context,
+ IdentifierResolver::iterator::getFromOpaqueValue(First),
+ IdentifierResolver::iterator::getFromOpaqueValue(Last));
+
+ case OverloadedDeclFromDeclContext:
+ return MaybeConstructOverloadSet(*Context,
+ reinterpret_cast<DeclContext::lookup_iterator>(First),
+ reinterpret_cast<DeclContext::lookup_iterator>(Last));
+
+ case AmbiguousLookup:
+ assert(false &&
+ "Name lookup returned an ambiguity that could not be handled");
+ break;
+ }
+
+ return 0;
+}
+
+/// @brief Perform unqualified name lookup starting from a given
+/// scope.
+///
+/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
+/// used to find names within the current scope. For example, 'x' in
+/// @code
+/// int x;
+/// int f() {
+/// return x; // unqualified name look finds 'x' in the global scope
+/// }
+/// @endcode
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// @param S The scope from which unqualified name lookup will
+/// begin. If the lookup criteria permits, name lookup may also search
+/// in the parent scopes.
+///
+/// @param Name The name of the entity that we are searching for.
+///
+/// @param Criteria The criteria that this routine will use to
+/// determine which names are visible and which names will be
+/// found. Note that name lookup will find a name that is visible by
+/// the given criteria, but the entity itself may not be semantically
+/// correct or even the kind of entity expected based on the
+/// lookup. For example, searching for a nested-name-specifier name
+/// might result in an EnumDecl, which is visible but is not permitted
+/// as a nested-name-specifier in C++03.
+///
+/// @returns The result of name lookup, which includes zero or more
+/// declarations and possibly additional information used to diagnose
+/// ambiguities.
+Sema::LookupResult
+Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) {
+ if (!Name) return LookupResult(Context, 0);
+
+ if (!getLangOptions().CPlusPlus) {
+ // Unqualified name lookup in C/Objective-C is purely lexical, so
+ // search in the declarations attached to the name.
+
+ // For the purposes of unqualified name lookup, structs and unions
+ // don't have scopes at all. For example:
+ //
+ // struct X {
+ // struct T { int i; } x;
+ // };
+ //
+ // void f() {
+ // struct T t; // okay: T is defined lexically within X, but
+ // // semantically at global scope
+ // };
+ //
+ // FIXME: Is there a better way to deal with this?
+ DeclContext *SearchCtx = CurContext;
+ while (isa<RecordDecl>(SearchCtx) || isa<EnumDecl>(SearchCtx))
+ SearchCtx = SearchCtx->getParent();
+ IdentifierResolver::iterator I
+ = IdResolver.begin(Name, SearchCtx, !Criteria.RedeclarationOnly);
+
+ // Scan up the scope chain looking for a decl that matches this
+ // identifier that is in the appropriate namespace. This search
+ // should not take long, as shadowing of names is uncommon, and
+ // deep shadowing is extremely uncommon.
+ for (; I != IdResolver.end(); ++I)
+ if (Criteria.isLookupResult(*I))
+ return LookupResult(Context, *I);
+ } else {
+ // Unqualified name lookup in C++ requires looking into scopes
+ // that aren't strictly lexical, and therefore we walk through the
+ // context as well as walking through the scopes.
+
+ // FIXME: does "true" for LookInParentCtx actually make sense?
+ IdentifierResolver::iterator
+ I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
+ IEnd = IdResolver.end();
+ for (; S; S = S->getParent()) {
+ // Check whether the IdResolver has anything in this scope.
+ for (; I != IEnd && S->isDeclScope(*I); ++I) {
+ if (Criteria.isLookupResult(*I)) {
+ // We found something. Look for anything else in our scope
+ // with this same name and in an acceptable identifier
+ // namespace, so that we can construct an overload set if we
+ // need to.
+ IdentifierResolver::iterator LastI = I;
+ for (++LastI; LastI != IEnd; ++LastI) {
+ if (!S->isDeclScope(*LastI))
+ break;
+ }
+ return LookupResult(Context, I, LastI);
+ }
+ }
+
+ // If there is an entity associated with this scope, it's a
+ // DeclContext. We might need to perform qualified lookup into
+ // it.
+ // FIXME: We're performing redundant lookups here, where the
+ // scope stack mirrors the semantic nested of classes and
+ // namespaces. We can save some work by checking the lexical
+ // scope against the semantic scope and avoiding any lookups
+ // when they are the same.
+ // FIXME: In some cases, we know that every name that could be
+ // found by this qualified name lookup will also be on the
+ // identifier chain. For example, inside a class without any
+ // base classes, we never need to perform qualified lookup
+ // because all of the members are on top of the identifier
+ // chain. However, we cannot perform this optimization when the
+ // lexical and semantic scopes don't line up, e.g., in an
+ // out-of-line member definition.
+ DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ while (Ctx && Ctx->isFunctionOrMethod())
+ Ctx = Ctx->getParent();
+ while (Ctx && (Ctx->isNamespace() || Ctx->isRecord())) {
+ // Look for declarations of this name in this scope.
+ if (LookupResult Result = LookupQualifiedName(Ctx, Name, Criteria))
+ return Result;
+
+ if (Criteria.RedeclarationOnly && !Ctx->isTransparentContext())
+ return LookupResult(Context, 0);
+
+ Ctx = Ctx->getParent();
+ }
+ }
+ }
+
+ // If we didn't find a use of this identifier, and if the identifier
+ // corresponds to a compiler builtin, create the decl object for the builtin
+ // now, injecting it into translation unit scope, and return it.
+ if (Criteria.Kind == LookupCriteria::Ordinary) {
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+ if (Criteria.AllowLazyBuiltinCreation && II) {
+ // If this is a builtin on this (or all) targets, create the decl.
+ if (unsigned BuiltinID = II->getBuiltinID())
+ return LookupResult(Context,
+ LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+ S));
+ }
+ if (getLangOptions().ObjC1 && II) {
+ // @interface and @compatibility_alias introduce typedef-like names.
+ // Unlike typedef's, they can only be introduced at file-scope (and are
+ // therefore not scoped decls). They can, however, be shadowed by
+ // other names in IDNS_Ordinary.
+ ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
+ if (IDI != ObjCInterfaceDecls.end())
+ return LookupResult(Context, IDI->second);
+ ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
+ if (I != ObjCAliasDecls.end())
+ return LookupResult(Context, I->second->getClassInterface());
+ }
+ }
+ return LookupResult(Context, 0);
+}
+
+/// @brief Perform qualified name lookup into a given context.
+///
+/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
+/// names when the context of those names is explicit specified, e.g.,
+/// "std::vector" or "x->member".
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// @param LookupCtx The context in which qualified name lookup will
+/// search. If the lookup criteria permits, name lookup may also search
+/// in the parent contexts or (for C++ classes) base classes.
+///
+/// @param Name The name of the entity that we are searching for.
+///
+/// @param Criteria The criteria that this routine will use to
+/// determine which names are visible and which names will be
+/// found. Note that name lookup will find a name that is visible by
+/// the given criteria, but the entity itself may not be semantically
+/// correct or even the kind of entity expected based on the
+/// lookup. For example, searching for a nested-name-specifier name
+/// might result in an EnumDecl, which is visible but is not permitted
+/// as a nested-name-specifier in C++03.
+///
+/// @returns The result of name lookup, which includes zero or more
+/// declarations and possibly additional information used to diagnose
+/// ambiguities.
+Sema::LookupResult
+Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
+ LookupCriteria Criteria) {
+ assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
+
+ if (!Name) return LookupResult(Context, 0);
+
+ // If we're performing qualified name lookup (e.g., lookup into a
+ // struct), find fields as part of ordinary name lookup.
+ if (Criteria.Kind == LookupCriteria::Ordinary)
+ Criteria.IDNS |= Decl::IDNS_Member;
+
+ // Perform qualified name lookup into the LookupCtx.
+ // FIXME: Will need to look into base classes and such.
+ DeclContext::lookup_iterator I, E;
+ for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I)
+ if (Criteria.isLookupResult(*I))
+ return LookupResult(Context, I, E);
+
+ return LookupResult(Context, 0);
+}
+
+/// @brief Performs name lookup for a name that was parsed in the
+/// source code, and may contain a C++ scope specifier.
+///
+/// This routine is a convenience routine meant to be called from
+/// contexts that receive a name and an optional C++ scope specifier
+/// (e.g., "N::M::x"). It will then perform either qualified or
+/// unqualified name lookup (with LookupQualifiedName or LookupName,
+/// respectively) on the given name and return those results.
+///
+/// @param S The scope from which unqualified name lookup will
+/// begin.
+///
+/// @param SS An optional C++ scope-specified, e.g., "::N::M".
+///
+/// @param Name The name of the entity that name lookup will
+/// search for.
+///
+/// @param Criteria The criteria that will determine which entities
+/// are visible to name lookup.
+///
+/// @returns The result of qualified or unqualified name lookup.
+Sema::LookupResult
+Sema::LookupParsedName(Scope *S, const CXXScopeSpec &SS,
+ DeclarationName Name, LookupCriteria Criteria) {
+ if (SS.isSet())
+ return LookupQualifiedName(static_cast<DeclContext *>(SS.getScopeRep()),
+ Name, Criteria);
+
+ return LookupName(S, Name, Criteria);
+}
+
+
using namespace ::A // expected-error{{expected namespace name}}
B ; // expected-error{{expected ';' after namespace name}}
+void test_nslookup() {
+ int B;
+ class C;
+ using namespace B;
+ using namespace C;
+}
+
namespace N {
float& f1(int x) {
N::f1::type& i1 = x;
- // FIXME: currently fails f1::type& i2 = x;
+ f1::type& i2 = x;
}
struct f2 {