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;
}
// 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());
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;
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}}
};
}
};
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}}
+ }
+}