Author: rsmith Date: Mon May 14 13:52:48 2018 New Revision: 332291 URL: http://llvm.org/viewvc/llvm-project?rev=332291&view=rev Log: Fix regression in r332076.
If the name after 'template' is an unresolved using declaration (not containing 'typename'), then we don't yet know if it's a valid template-name, so don't reject it prior to instantiation. Instead, treat it as naming a dependent member of the current instantiation. Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/CXX/drs/dr1xx.cpp cfe/trunk/test/SemaTemplate/dependent-names.cpp Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=332291&r1=332290&r2=332291&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon May 14 13:52:48 2018 @@ -105,6 +105,12 @@ static NamedDecl *isAcceptableTemplateNa return nullptr; } + // 'using Dependent::foo;' can resolve to a template name. + // 'using typename Dependent::foo;' cannot (not even if 'foo' is an + // injected-class-name). + if (isa<UnresolvedUsingValueDecl>(D)) + return D; + return nullptr; } @@ -214,6 +220,10 @@ TemplateNameKind Sema::isTemplateName(Sc // We'll do this lookup again later. R.suppressDiagnostics(); + } else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) { + // We don't yet know whether this is a template-name or not. + MemberOfUnknownSpecialization = true; + return TNK_Non_template; } else { TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl()); @@ -429,7 +439,7 @@ bool Sema::LookupTemplateName(LookupResu if (ExampleLookupResult && TemplateKWLoc.isValid()) { Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template) << Found.getLookupName() << SS.getRange(); - Diag(ExampleLookupResult->getLocation(), + Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(), diag::note_template_kw_refers_to_non_template) << Found.getLookupName(); return true; Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=332291&r1=332290&r2=332291&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr1xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr1xx.cpp Mon May 14 13:52:48 2018 @@ -71,8 +71,7 @@ namespace dr109 { // dr109: yes using T::template f<int>; // expected-error {{'template' keyword not permitted here}} expected-error {{using declaration cannot refer to a template specialization}} // FIXME: We shouldn't suggest using the 'template' keyword in a location where it's not valid. using T::f<int>; // expected-error {{use 'template' keyword}} expected-error {{using declaration cannot refer to a template specialization}} - // FIXME: The first 'using' above introduces 'f' as a non-template member of 'B', leading to bad recovery: - void g() { this->f<int>(123); } // expected-error {{expected '('}} + void g() { this->f<int>(123); } // expected-error {{use 'template' keyword}} }; } Modified: cfe/trunk/test/SemaTemplate/dependent-names.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-names.cpp?rev=332291&r1=332290&r2=332291&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/dependent-names.cpp (original) +++ cfe/trunk/test/SemaTemplate/dependent-names.cpp Mon May 14 13:52:48 2018 @@ -427,3 +427,23 @@ namespace DependentTemplateIdWithNoArgs }; void g() { f<X>(); } } + +namespace DependentUnresolvedUsingTemplate { + template<typename T> + struct X : T { + using T::foo; + void f() { this->template foo(); } // expected-error {{does not refer to a template}} + void g() { this->template foo<>(); } // expected-error {{does not refer to a template}} + void h() { this->template foo<int>(); } // expected-error {{does not refer to a template}} + }; + struct A { template<typename = int> int foo(); }; + struct B { int foo(); }; // expected-note 3{{non-template here}} + void test(X<A> xa, X<B> xb) { + xa.f(); + xa.g(); + xa.h(); + xb.f(); // expected-note {{instantiation of}} + xb.g(); // expected-note {{instantiation of}} + xb.h(); // expected-note {{instantiation of}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits