Cope with extraneous "template" keyword when providing an out-of-line
definition of a member template (or a member thereof). Fixes PR5566. llvm-svn: 89512
This commit is contained in:
parent
5305dc0be1
commit
ade9bcd72e
|
@ -1685,10 +1685,14 @@ public:
|
|||
/// \param ObjectType if this dependent template name occurs in the
|
||||
/// context of a member access expression, the type of the object being
|
||||
/// accessed.
|
||||
///
|
||||
/// \param EnteringContext whether we are entering the context of this
|
||||
/// template.
|
||||
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
TypeTy *ObjectType) {
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext) {
|
||||
return TemplateTy();
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
TPA.Commit();
|
||||
TemplateTy Template
|
||||
= Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
|
||||
ObjectType);
|
||||
ObjectType, EnteringContext);
|
||||
if (!Template)
|
||||
break;
|
||||
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
|
||||
|
@ -774,7 +774,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
|||
TemplateName.setIdentifier(Name, NameLoc);
|
||||
if (ObjectType) {
|
||||
Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
|
||||
TemplateName, ObjectType);
|
||||
TemplateName, ObjectType,
|
||||
EnteringContext);
|
||||
TNK = TNK_Dependent_template_name;
|
||||
if (!Template.get())
|
||||
return true;
|
||||
|
|
|
@ -851,7 +851,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
|
|||
if (isEndOfTemplateArgument(Tok)) {
|
||||
TemplateTy Template
|
||||
= Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
|
||||
/*ObjectType=*/0);
|
||||
/*ObjectType=*/0,
|
||||
/*EnteringContext=*/false);
|
||||
if (Template.get())
|
||||
return ParsedTemplateArgument(SS, Template, Name.StartLocation);
|
||||
}
|
||||
|
|
|
@ -2293,7 +2293,8 @@ public:
|
|||
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
TypeTy *ObjectType);
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext);
|
||||
|
||||
bool CheckClassTemplatePartialSpecializationArgs(
|
||||
TemplateParameterList *TemplateParams,
|
||||
|
|
|
@ -1381,10 +1381,11 @@ Sema::TemplateTy
|
|||
Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
TypeTy *ObjectType) {
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext) {
|
||||
if ((ObjectType &&
|
||||
computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
|
||||
(SS.isSet() && computeDeclContext(SS, false))) {
|
||||
(SS.isSet() && computeDeclContext(SS, EnteringContext))) {
|
||||
// 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
|
||||
|
@ -1403,7 +1404,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
|||
// rules, even in C++03 mode, retroactively applying the DR.
|
||||
TemplateTy Template;
|
||||
TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
|
||||
false, Template);
|
||||
EnteringContext, Template);
|
||||
if (TNK == TNK_Non_template) {
|
||||
Diag(Name.getSourceRange().getBegin(),
|
||||
diag::err_template_kw_refers_to_non_template)
|
||||
|
|
|
@ -5349,7 +5349,8 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
|
|||
/*FIXME:*/getDerived().getBaseLocation(),
|
||||
SS,
|
||||
Name,
|
||||
ObjectType.getAsOpaquePtr())
|
||||
ObjectType.getAsOpaquePtr(),
|
||||
/*EnteringContext=*/false)
|
||||
.template getAsVal<TemplateName>();
|
||||
}
|
||||
|
||||
|
@ -5369,7 +5370,8 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
|
|||
/*FIXME:*/getDerived().getBaseLocation(),
|
||||
SS,
|
||||
Name,
|
||||
ObjectType.getAsOpaquePtr())
|
||||
ObjectType.getAsOpaquePtr(),
|
||||
/*EnteringContext=*/false)
|
||||
.template getAsVal<TemplateName>();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
template<typename T, int N>
|
||||
struct A;
|
||||
|
||||
|
|
|
@ -66,3 +66,14 @@ X0<T, U>::operator T*() const {
|
|||
|
||||
namespace N { template <class X> class A {void a();}; }
|
||||
namespace N { template <class X> void A<X>::a() {} }
|
||||
|
||||
// PR5566
|
||||
template<typename T>
|
||||
struct X1 {
|
||||
template<typename U>
|
||||
struct B { void f(); };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
void X1<T>::template B<U>::f() { }
|
||||
|
|
Loading…
Reference in New Issue