forked from OSchip/llvm-project
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. llvm-svn: 332291
This commit is contained in:
parent
f66f7612bf
commit
cbebd6226d
|
@ -105,6 +105,12 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
|
|||
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(Scope *S,
|
|||
|
||||
// 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(LookupResult &Found,
|
|||
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;
|
||||
|
|
|
@ -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}}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue