From c52c190c1e790317e6448902fbf08511fb6c1789 Mon Sep 17 00:00:00 2001 From: Karthik Bhat Date: Thu, 8 May 2014 13:16:20 +0000 Subject: [PATCH] Fix PR19169 [Crash on invalid attempting to specialize a template method as a template variable]. A template declaration of a template name can be null in case we have a dependent name or a set of function templates. Hence use dyn_cast_or_null instead of dyn_cast. Also improve the diagnostic emitted in this case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208313 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ lib/Sema/SemaTemplate.cpp | 13 +++++++++++-- test/SemaCXX/cxx1y-variable-templates_top_level.cpp | 10 ++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 27ca1c9346..e33d2c1666 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3314,6 +3314,9 @@ def note_var_prev_partial_spec_here : Note< "previous declaration of variable template partial specialization is here">; def err_var_spec_no_template : Error< "no variable template matches%select{| partial}0 specialization">; +def err_var_spec_no_template_but_method : Error< + "no variable template matches specialization; " + "did you mean to use %0 as function template instead?">; // C++ Function template specializations def err_function_template_spec_no_match : Error< diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index e21d1eef46..8c0261381c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2420,10 +2420,19 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // The template-id must name a variable template. VarTemplateDecl *VarTemplate = - dyn_cast(Name.getAsTemplateDecl()); - if (!VarTemplate) + dyn_cast_or_null(Name.getAsTemplateDecl()); + if (!VarTemplate) { + NamedDecl *FnTemplate; + if (auto *OTS = Name.getAsOverloadedTemplate()) + FnTemplate = *OTS->begin(); + else + FnTemplate = dyn_cast_or_null(Name.getAsTemplateDecl()); + if (FnTemplate) + return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template_but_method) + << FnTemplate->getDeclName(); return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template) << IsPartialSpecialization; + } // Check for unexpanded parameter packs in any of the template arguments. for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index 37d5bf3a00..1ff64b334a 100644 --- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -448,3 +448,13 @@ namespace PR19152 { static_assert(x == 1, ""); #endif } + +namespace PR19169 { + template int* f(); + template void f(); + template<> int f; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}} + + template void g(); + template<> int g; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} +} + -- 2.40.0