diff options
-rw-r--r-- | lib/Sema/Lookup.h | 25 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 12 | ||||
-rw-r--r-- | test/SemaTemplate/dependent-base-classes.cpp | 19 |
6 files changed, 73 insertions, 33 deletions
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index e761346c67..9064de6aa0 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -32,6 +32,11 @@ public: /// @brief No entity found met the criteria. NotFound = 0, + /// @brief No entity found met the criteria within the current + /// instantiation,, but there were dependent base classes of the + /// current instantiation that could not be searched. + NotFoundInCurrentInstantiation, + /// @brief Name lookup found a single declaration that met the /// criteria. getFoundDecl() will return this declaration. Found, @@ -268,6 +273,19 @@ public: Decls.set_size(N); } + /// \brief Determine whether no result was found because we could not + /// search into dependent base classes of the current instantiation. + bool wasNotFoundInCurrentInstantiation() const { + return ResultKind == NotFoundInCurrentInstantiation; + } + + /// \brief Note that while no result was found in the current instantiation, + /// there were dependent base classes that could not be searched. + void setNotFoundInCurrentInstantiation() { + assert(ResultKind == NotFound && Decls.empty()); + ResultKind = NotFoundInCurrentInstantiation; + } + /// \brief Resolves the result kind of the lookup, possibly hiding /// decls. /// @@ -278,9 +296,10 @@ public: /// \brief Re-resolves the result kind of the lookup after a set of /// removals has been performed. void resolveKindAfterFilter() { - if (Decls.empty()) - ResultKind = NotFound; - else { + if (Decls.empty()) { + if (ResultKind != NotFoundInCurrentInstantiation) + ResultKind = NotFound; + } else { ResultKind = Found; resolveKind(); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 44bf48915e..953a00fa42 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1212,7 +1212,8 @@ public: = NotForRedeclaration); bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false); - bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx); + bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + bool InUnqualifiedLookup = false); bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 79bb1cb54a..8176710e35 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -138,6 +138,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, NamedDecl *IIDecl = 0; switch (Result.getResultKind()) { case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: return 0; @@ -4791,7 +4792,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // and that current instantiation has any dependent base // classes, we might find something at instantiation time: treat // this as a dependent elaborated-type-specifier. - if (isCurrentInstantiationWithDependentBases(SS)) { + if (Previous.wasNotFoundInCurrentInstantiation()) { IsDependent = true; return DeclPtrTy(); } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index c6ab6a6b19..cda245deba 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -623,7 +623,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // 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. - if (LookupQualifiedName(R, Ctx)) + if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true)) return true; } } @@ -927,11 +927,11 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, return Found; } -/// @brief Perform qualified name lookup into a given context. +/// \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". +/// "std::vector" or "x->member", or as part of unqualified name lookup. /// /// Different lookup criteria can find different names. For example, a /// particular scope can have both a struct and a function of the same @@ -939,25 +939,18 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, /// information about lookup criteria, see the documentation for the /// class LookupCriteria. /// -/// @param LookupCtx The context in which qualified name lookup will +/// \param R captures both the lookup criteria and any lookup results found. +/// +/// \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. +/// \param InUnqualifiedLookup true if this is qualified name lookup that +/// occurs as part of unqualified name lookup. /// -/// @returns The result of name lookup, which includes zero or more -/// declarations and possibly additional information used to diagnose -/// ambiguities. -bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) { +/// \returns true if lookup succeeded, false if it failed. +bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + bool InUnqualifiedLookup) { assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); if (!R.getLookupName()) @@ -995,11 +988,22 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) { // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. - if (!isa<CXXRecordDecl>(LookupCtx)) + CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); + if (!LookupRec) return false; + // If we're performing qualified name lookup into a dependent class, + // then we are actually looking into a current instantiation. If we have any + // dependent base classes, then we either have to delay lookup until + // template instantiation time (at which point all bases will be available) + // or we have to fail. + if (!InUnqualifiedLookup && LookupRec->isDependentContext() && + LookupRec->hasAnyDependentBases()) { + R.setNotFoundInCurrentInstantiation(); + return false; + } + // Perform lookup into our base classes. - CXXRecordDecl *LookupRec = cast<CXXRecordDecl>(LookupCtx); CXXBasePaths Paths; Paths.setOrigin(LookupRec); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d2e70cf9ad..2fad8325d4 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4769,16 +4769,12 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, Decl *Referenced = 0; switch (Result.getResultKind()) { case LookupResult::NotFound: - if (CurrentInstantiation && CurrentInstantiation->hasAnyDependentBases()) { - // We performed a lookup in the current instantiation and didn't - // find anything. However, this current instantiation has - // dependent bases, so we might be able to find something at - // instantiation time: just build a TypenameType and move on. - return Context.getTypenameType(NNS, &II); - } - DiagID = diag::err_typename_nested_not_found; break; + + case LookupResult::NotFoundInCurrentInstantiation: + // Okay, it's a member of an unknown instantiation. + return Context.getTypenameType(NNS, &II); case LookupResult::Found: if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp index b9666dba61..79b28c2239 100644 --- a/test/SemaTemplate/dependent-base-classes.cpp +++ b/test/SemaTemplate/dependent-base-classes.cpp @@ -63,3 +63,22 @@ namespace PR6031 { } }; } + +namespace Ambig { + template<typename T> + struct Base1 { + typedef int type; // expected-note{{member found by ambiguous name lookup}} + }; + + struct Base2 { + typedef float type; // expected-note{{member found by ambiguous name lookup}} + }; + + template<typename T> + struct Derived : Base1<T>, Base2 { + typedef typename Derived::type type; // expected-error{{member 'type' found in multiple base classes of different types}} + type *foo(float *fp) { return fp; } + }; + + Derived<int> di; // expected-note{{instantiation of}} +} |