]> granicus.if.org Git - clang/commitdiff
Give more accurate descriptions of what kind of template we found in diagnostics.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 14 Jan 2017 02:19:59 +0000 (02:19 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 14 Jan 2017 02:19:59 +0000 (02:19 +0000)
We were previouly assuming that every type template was a class template, which
is not true any more.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291988 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
test/SemaTemplate/alias-templates.cpp

index 0d0f68713d7d64adadbebaa7844ea4a8df91f336..13093bc4d1c26ee3f9764022b12e6da21bfd39cc 100644 (file)
@@ -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">;
index 6ac02be697bc6fb2bfb97ba247820844d84dd866..ae70b75336a52906b22b528b501388a58d4e3c9d 100644 (file)
@@ -1689,6 +1689,18 @@ public:
                bool IsAddressOfOperand,
                std::unique_ptr<CorrectionCandidateCallback> 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,
index fe1775e1eb5b0fde95a9acc187e485c969f1bd8a..2cc03c65ad04c7535466d0ffbeeb4e4fb3425faa 100644 (file)
@@ -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<ClassTemplateDecl>(TD))
+    return TemplateNameKindForDiagnostics::ClassTemplate;
+  if (isa<FunctionTemplateDecl>(TD))
+    return TemplateNameKindForDiagnostics::FunctionTemplate;
+  if (isa<VarTemplateDecl>(TD))
+    return TemplateNameKindForDiagnostics::VarTemplate;
+  if (isa<TypeAliasTemplateDecl>(TD))
+    return TemplateNameKindForDiagnostics::AliasTemplate;
+  if (isa<TemplateTemplateParmDecl>(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.
index 8ad5b5951ea34c30c1df8c9c85cf4969a0d7bdd1..1c19f67cb0fc2d9b10b76fc7695a4a6641d8057a 100644 (file)
@@ -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<ClassTemplateDecl>(Template)? 0 :
-        isa<FunctionTemplateDecl>(Template)? 1 :
-        isa<TemplateTemplateParmDecl>(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<ClassTemplateDecl>(Template)? 0 :
-              isa<FunctionTemplateDecl>(Template)? 1 :
-              isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+          << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
           << Template;
         Diag(Template->getLocation(), diag::note_template_decl_here)
           << Params->getSourceRange();
index 7eb5e3744d189f1958a1c749f5452bdbfef11539..425d527e5212dafb2c514398655192cc59e8bf35 100644 (file)
@@ -9,7 +9,7 @@ T pi = T(3.1415926535897932385); // expected-note {{template is declared here}}
 template int pi<int>;
 
 #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
 
index d70e86817849f82519301098697f0cf1d16ecbf9..3b7548d169b0de00085920b8281954f48b55d98e 100644 (file)
@@ -254,3 +254,14 @@ namespace PR31514 {
 
   tuple_size<const int> t;
 }
+
+namespace an_alias_template_is_not_a_class_template {
+  template<typename T> 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<template<typename> 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'}}
+  }
+}