From 0c062b408b2cc3d73bcd279a075aee8a9c219ff7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 14 Jan 2017 02:19:59 +0000 Subject: [PATCH] Give more accurate descriptions of what kind of template we found in diagnostics. We were previouly assuming that every type template was a class template, which is not true any more. llvm-svn: 291988 --- .../clang/Basic/DiagnosticSemaKinds.td | 8 ++++--- clang/include/clang/Sema/Sema.h | 12 +++++++++++ clang/lib/Sema/SemaDecl.cpp | 21 ++++++++++++++++++- clang/lib/Sema/SemaTemplate.cpp | 10 +++------ .../cxx1y-variable-template-no-body.cpp | 2 +- clang/test/SemaTemplate/alias-templates.cpp | 11 ++++++++++ 6 files changed, 52 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0d0f68713d7d..13093bc4d1c2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3796,11 +3796,13 @@ def err_template_decl_ref : Error< // C++ Template Argument Lists def err_template_missing_args : Error< - "use of class template %0 requires template arguments">; + "use of " + "%select{class template|function template|variable template|alias template|" + "template template parameter|template}0 %1 requires template arguments">; def err_template_arg_list_different_arity : Error< "%select{too few|too many}0 template arguments for " - "%select{class template|function template|template template parameter" - "|template}1 %2">; + "%select{class template|function template|variable template|alias template|" + "template template parameter|template}1 %2">; def note_template_decl_here : Note<"template is declared here">; def err_template_arg_must_be_type : Error< "template argument for template type parameter must be a type">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6ac02be697bc..ae70b75336a5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1689,6 +1689,18 @@ public: bool IsAddressOfOperand, std::unique_ptr CCC = nullptr); + /// Describes the detailed kind of a template name. Used in diagnostics. + enum class TemplateNameKindForDiagnostics { + ClassTemplate, + FunctionTemplate, + VarTemplate, + AliasTemplate, + TemplateTemplateParam, + DependentTemplate + }; + TemplateNameKindForDiagnostics + getTemplateNameKindForDiagnostics(TemplateName Name); + Decl *ActOnDeclarator(Scope *S, Declarator &D); NamedDecl *HandleDeclarator(Scope *S, Declarator &D, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fe1775e1eb5b..2cc03c65ad04 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -656,7 +656,8 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, Name, nullptr, true, TemplateResult, MemberOfUnknownSpecialization) == TNK_Type_template) { TemplateName TplName = TemplateResult.get(); - Diag(IILoc, diag::err_template_missing_args) << TplName; + Diag(IILoc, diag::err_template_missing_args) + << (int)getTemplateNameKindForDiagnostics(TplName) << TplName; if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { Diag(TplDecl->getLocation(), diag::note_template_decl_here) << TplDecl->getTemplateParameters()->getSourceRange(); @@ -1072,6 +1073,24 @@ Corrected: return BuildDeclarationNameExpr(SS, Result, ADL); } +Sema::TemplateNameKindForDiagnostics +Sema::getTemplateNameKindForDiagnostics(TemplateName Name) { + auto *TD = Name.getAsTemplateDecl(); + if (!TD) + return TemplateNameKindForDiagnostics::DependentTemplate; + if (isa(TD)) + return TemplateNameKindForDiagnostics::ClassTemplate; + if (isa(TD)) + return TemplateNameKindForDiagnostics::FunctionTemplate; + if (isa(TD)) + return TemplateNameKindForDiagnostics::VarTemplate; + if (isa(TD)) + return TemplateNameKindForDiagnostics::AliasTemplate; + if (isa(TD)) + return TemplateNameKindForDiagnostics::TemplateTemplateParam; + return TemplateNameKindForDiagnostics::DependentTemplate; +} + // Determines the context to return to after temporarily entering a // context. This depends in an unnecessarily complicated way on the // exact ordering of callbacks from the parser. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8ad5b5951ea3..1c19f67cb0fc 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3326,7 +3326,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, SourceRange SR = AL.getSourceRange(); TemplateName Name = Arg.getAsTemplate(); Diag(SR.getBegin(), diag::err_template_missing_args) - << Name << SR; + << (int)getTemplateNameKindForDiagnostics(Name) << Name << SR; if (TemplateDecl *Decl = Name.getAsTemplateDecl()) Diag(Decl->getLocation(), diag::note_template_decl_here); @@ -3911,9 +3911,7 @@ static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template, TemplateArgs.getRAngleLoc()); S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity) << (NumArgs > NumParams) - << (isa(Template)? 0 : - isa(Template)? 1 : - isa(Template)? 2 : 3) + << (int)S.getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template << Range; S.Diag(Template->getLocation(), diag::note_template_decl_here) << Params->getSourceRange(); @@ -4021,9 +4019,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Not enough arguments for this parameter pack. Diag(TemplateLoc, diag::err_template_arg_list_different_arity) << false - << (isa(Template)? 0 : - isa(Template)? 1 : - isa(Template)? 2 : 3) + << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template; Diag(Template->getLocation(), diag::note_template_decl_here) << Params->getSourceRange(); diff --git a/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp b/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp index 7eb5e3744d18..425d527e5212 100644 --- a/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp +++ b/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp @@ -9,7 +9,7 @@ T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} template int pi; #ifndef FIXING -template float pi<>; // expected-error {{too few template arguments for template 'pi'}} +template float pi<>; // expected-error {{too few template arguments for variable template 'pi'}} template double pi_var0; // expected-error {{explicit instantiation of 'pi_var0' does not refer to a function template, variable template, member function, member class, or static data member}} #endif diff --git a/clang/test/SemaTemplate/alias-templates.cpp b/clang/test/SemaTemplate/alias-templates.cpp index d70e86817849..3b7548d169b0 100644 --- a/clang/test/SemaTemplate/alias-templates.cpp +++ b/clang/test/SemaTemplate/alias-templates.cpp @@ -254,3 +254,14 @@ namespace PR31514 { tuple_size t; } + +namespace an_alias_template_is_not_a_class_template { + template using Foo = int; // expected-note 2{{here}} + Foo x; // expected-error {{use of alias template 'Foo' requires template arguments}} + Foo<> y; // expected-error {{too few template arguments for alias template 'Foo'}} + + template class Bar> void f() { // expected-note 2{{here}} + Bar x; // expected-error {{use of template template parameter 'Bar' requires template arguments}} + Bar<> y; // expected-error {{too few template arguments for template template parameter 'Bar'}} + } +}