def ext_template_outside_of_template : ExtWarn<
"'template' keyword outside of a template">, InGroup<CXX0x>;
+def err_non_type_template_in_nested_name_specifier : Error<
+ "qualified name refers into a specialization of function template '%0'">;
+def err_template_id_not_a_type : Error<
+ "template name refers to non-type template '%0'">;
+def note_template_declared_here : Note<
+ "%select{function template|class template|template template parameter}0 "
+ "%1 declared here">;
+
// C++0x Variadic Templates
def err_template_param_pack_default_arg : Error<
"template parameter pack cannot have a default argument">;
void translateTemplateArguments(const ASTTemplateArgsPtr &In,
TemplateArgumentListInfo &Out);
+ void NoteAllFoundTemplates(TemplateName Name);
+
QualType CheckTemplateIdType(TemplateName Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs);
} else if (SubstTemplateTemplateParmPackStorage *SubstPack
= getAsSubstTemplateTemplateParmPack())
OS << SubstPack->getParameterPack()->getNameAsString();
+ else {
+ OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
+ (*OTS->begin())->printName(OS);
+ }
}
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
return false;
}
- if (TemplateId->Kind == TNK_Type_template ||
- TemplateId->Kind == TNK_Dependent_template_name) {
- // Consume the template-id token.
- ConsumeToken();
-
- assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
- SourceLocation CCLoc = ConsumeToken();
+ // Consume the template-id token.
+ ConsumeToken();
+
+ assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+ SourceLocation CCLoc = ConsumeToken();
- if (!HasScopeSpecifier)
- HasScopeSpecifier = true;
-
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
- TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
-
- if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
- /*FIXME:*/SourceLocation(),
- SS,
- TemplateId->Template,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc,
- CCLoc,
- EnteringContext)) {
- SourceLocation StartLoc
- = SS.getBeginLoc().isValid()? SS.getBeginLoc()
- : TemplateId->TemplateNameLoc;
- SS.SetInvalid(SourceRange(StartLoc, CCLoc));
- }
-
- TemplateId->Destroy();
- continue;
+ if (!HasScopeSpecifier)
+ HasScopeSpecifier = true;
+
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+
+ if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
+ /*FIXME:*/SourceLocation(),
+ SS,
+ TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc,
+ CCLoc,
+ EnteringContext)) {
+ SourceLocation StartLoc
+ = SS.getBeginLoc().isValid()? SS.getBeginLoc()
+ : TemplateId->TemplateNameLoc;
+ SS.SetInvalid(SourceRange(StartLoc, CCLoc));
}
-
- assert(false && "FIXME: Only type template names supported here");
+
+ TemplateId->Destroy();
+ continue;
}
return false;
}
+
+ if (Template.get().getAsOverloadedTemplate() ||
+ isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
+ SourceRange R(TemplateNameLoc, RAngleLoc);
+ if (SS.getRange().isValid())
+ R.setBegin(SS.getRange().getBegin());
+
+ Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
+ << Template.get() << R;
+ NoteAllFoundTemplates(Template.get());
+ return true;
+ }
+
// We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc,
return ParamLists[NumParamLists - 1];
}
+void Sema::NoteAllFoundTemplates(TemplateName Name) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ Diag(Template->getLocation(), diag::note_template_declared_here)
+ << (isa<FunctionTemplateDecl>(Template)? 0
+ : isa<ClassTemplateDecl>(Template)? 1
+ : 2)
+ << Template->getDeclName();
+ return;
+ }
+
+ if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
+ for (OverloadedTemplateStorage::iterator I = OST->begin(),
+ IEnd = OST->end();
+ I != IEnd; ++I)
+ Diag((*I)->getLocation(), diag::note_template_declared_here)
+ << 0 << (*I)->getDeclName();
+
+ return;
+ }
+}
+
+
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
TemplateDecl *Template = Name.getAsTemplateDecl();
- if (!Template) {
- // The template name does not resolve to a template, so we just
- // build a dependent template-id type.
- return Context.getTemplateSpecializationType(Name, TemplateArgs);
+ if (!Template || isa<FunctionTemplateDecl>(Template)) {
+ // We might have a substituted template template parameter pack. If so,
+ // build a template specialization type for it.
+ if (Name.getAsSubstTemplateTemplateParmPack())
+ return Context.getTemplateSpecializationType(Name, TemplateArgs);
+
+ Diag(TemplateLoc, diag::err_template_id_not_a_type)
+ << Name;
+ NoteAllFoundTemplates(Name);
+ return QualType();
}
// Check that the template argument list is well-formed for this
}
};
}
+
+namespace PR9226 {
+ template<typename a>
+ void nt() // expected-note{{function template 'nt' declared here}}
+ { nt<>:: } // expected-error{{qualified name refers into a specialization of function template 'nt'}} \
+ // expected-error{{expected unqualified-id}}
+
+ template<typename T>
+ void f(T*); // expected-note{{function template 'f' declared here}}
+
+ template<typename T>
+ void f(T*, T*); // expected-note{{function template 'f' declared here}}
+
+ void g() {
+ f<int>:: // expected-error{{qualified name refers into a specialization of function template 'f'}}
+ } // expected-error{{expected unqualified-id}}
+
+ struct X {
+ template<typename T> void f(); // expected-note{{function template 'f' declared here}}
+ };
+
+ template<typename T, typename U>
+ struct Y {
+ typedef typename T::template f<U> type; // expected-error{{template name refers to non-type template 'X::f'}}
+ };
+
+ Y<X, int> yxi; // expected-note{{in instantiation of template class 'PR9226::Y<PR9226::X, int>' requested here}}
+}