From: Douglas Gregor Date: Tue, 19 Jan 2010 16:01:07 +0000 (+0000) Subject: Teach Sema::ActOnDependentTemplateName that a dependent template name X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0707bc504c392c8bd214a463f07b01809a23daa5;p=clang Teach Sema::ActOnDependentTemplateName that a dependent template name in a member access expression referring into the current instantiation need not be resolved at template definition *if* the current instantiation has any dependent base classes. Fixes PR6081. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93877 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3e9deda811..948949b7dc 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2053,7 +2053,6 @@ public: bool isDependentScopeSpecifier(const CXXScopeSpec &SS); CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); bool isUnknownSpecialization(const CXXScopeSpec &SS); - bool isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS); /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the /// global scope ('::'). diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 6006bca4b0..7a0b625206 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -210,28 +210,6 @@ bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { return getCurrentInstantiationOf(NNS) == 0; } -/// \brief Determine whether the given scope specifier refers to a -/// current instantiation that has any dependent base clases. -/// -/// This check is typically used when we've performed lookup into the -/// current instantiation of a template, but that lookup failed. When -/// there are dependent bases present, however, the lookup needs to be -/// delayed until template instantiation time. -bool Sema::isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS) { - if (!SS.isSet()) - return false; - - NestedNameSpecifier *NNS = (NestedNameSpecifier*)SS.getScopeRep(); - if (!NNS->isDependent()) - return false; - - CXXRecordDecl *CurrentInstantiation = getCurrentInstantiationOf(NNS); - if (!CurrentInstantiation) - return false; - - return CurrentInstantiation->hasAnyDependentBases(); -} - /// \brief If the given nested name specifier refers to the current /// instantiation, return the declaration that corresponds to that /// current instantiation (C++0x [temp.dep.type]p1). diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 2fad8325d4..0773a0f1e4 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1586,9 +1586,12 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext) { - if ((ObjectType && - computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) || - (SS.isSet() && computeDeclContext(SS, EnteringContext))) { + DeclContext *LookupCtx = 0; + if (SS.isSet()) + LookupCtx = computeDeclContext(SS, EnteringContext); + if (!LookupCtx && ObjectType) + LookupCtx = computeDeclContext(QualType::getFromOpaquePtr(ObjectType)); + if (LookupCtx) { // C++0x [temp.names]p5: // If a name prefixed by the keyword template is not the name of // a template, the program is ill-formed. [Note: the keyword @@ -1608,8 +1611,9 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, TemplateTy Template; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, EnteringContext, Template); - if (TNK == TNK_Non_template && - isCurrentInstantiationWithDependentBases(SS)) { + if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && + isa(LookupCtx) && + cast(LookupCtx)->hasAnyDependentBases()) { // This is a dependent template. } else if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp index 79b28c2239..80d20b09b8 100644 --- a/test/SemaTemplate/dependent-base-classes.cpp +++ b/test/SemaTemplate/dependent-base-classes.cpp @@ -82,3 +82,31 @@ namespace Ambig { Derived di; // expected-note{{instantiation of}} } + +namespace PR6081 { + template + struct A { }; + + template + class B : public A + { + public: + template< class X > + void f0(const X & k) + { + this->template f1()(k); + } + }; + + template + class C + { + public: + template< class X > + void f0(const X & k) + { + this->template f1()(k); // expected-error{{'f1' following the 'template' keyword does not refer to a template}} \ + // FIXME: expected-error{{unqualified-id}} + } + }; +}