From: Richard Smith Date: Thu, 9 Jan 2014 02:22:22 +0000 (+0000) Subject: PR18401: Fix assert by implementing the current proposed direction of core X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e8e2e809406fa7e1b4f6d04d16b85f0f0952374;p=clang PR18401: Fix assert by implementing the current proposed direction of core issue 1430. Don't allow a pack expansion to be used as an argument to an alias template unless the corresponding parameter is a parameter pack. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198833 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1ae6d2f143..bf8c051910 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3414,6 +3414,8 @@ def note_template_declared_here : Note< "%select{function template|class template|variable template" "|type alias template|template template parameter}0 " "%1 declared here">; +def err_alias_template_expansion_into_fixed_list : Error< + "pack expansion used as argument for non-pack parameter of alias template">; def note_parameter_type : Note< "parameter of type %0 is declared here">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 2a900f36e3..270d18dde6 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5298,18 +5298,12 @@ public: /// \param Converted Will receive the converted, canonicalized template /// arguments. /// - /// - /// \param ExpansionIntoFixedList If non-NULL, will be set true to indicate - /// when the template arguments contain a pack expansion that is being - /// expanded into a fixed parameter list. - /// - /// \returns True if an error occurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl &Converted, - bool *ExpansionIntoFixedList = 0); + SmallVectorImpl &Converted); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, const TemplateArgumentLoc &Arg, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index b468e31f09..97137184c2 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1975,17 +1975,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Check that the template argument list is well-formed for this // template. SmallVector Converted; - bool ExpansionIntoFixedList = false; if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, - false, Converted, &ExpansionIntoFixedList)) + false, Converted)) return QualType(); QualType CanonType; bool InstantiationDependent = false; - TypeAliasTemplateDecl *AliasTemplate = 0; - if (!ExpansionIntoFixedList && - (AliasTemplate = dyn_cast(Template))) { + if (TypeAliasTemplateDecl *AliasTemplate = + dyn_cast(Template)) { // Find the canonical type for this type alias template specialization. TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl(); if (Pattern->isInvalidDecl()) @@ -2590,11 +2588,10 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // Check that the template argument list is well-formed for this template. SmallVector Converted; - bool ExpansionIntoFixedList = false; if (CheckTemplateArgumentList( Template, TemplateNameLoc, const_cast(TemplateArgs), false, - Converted, &ExpansionIntoFixedList)) + Converted)) return true; // Find the variable template specialization declaration that @@ -3549,11 +3546,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl &Converted, - bool *ExpansionIntoFixedList) { - if (ExpansionIntoFixedList) - *ExpansionIntoFixedList = false; - + SmallVectorImpl &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc(); @@ -3606,6 +3599,20 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgumentPack.size(), Converted)) return true; + if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() && + isa(Template) && + !(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() && + !getExpandedPackSize(*Param))) { + // Core issue 1430: we have a pack expansion as an argument to an + // alias template, and it's not part of a final parameter pack. This + // can't be canonicalized, so reject it now. + Diag(TemplateArgs[ArgIdx].getLocation(), + diag::err_alias_template_expansion_into_fixed_list) + << TemplateArgs[ArgIdx].getSourceRange(); + Diag((*Param)->getLocation(), diag::note_template_param_here); + return true; + } + // We're now done with this argument. ++ArgIdx; @@ -3652,9 +3659,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgumentPack.data(), ArgumentPack.size())); ArgumentPack.clear(); - } else if (ExpansionIntoFixedList) { - // We have expanded a pack into a fixed list. - *ExpansionIntoFixedList = true; } return false; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8c988f07ed..22f13d7d2f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2480,11 +2480,10 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Check that the template argument list is well-formed for this template. SmallVector Converted; - bool ExpansionIntoFixedList = false; if (SemaRef.CheckTemplateArgumentList( VarTemplate, VarTemplate->getLocStart(), const_cast(VarTemplateArgsInfo), false, - Converted, &ExpansionIntoFixedList)) + Converted)) return 0; // Find the variable template specialization declaration that diff --git a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp index fb727543ef..a466be0a61 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -121,7 +121,16 @@ namespace PartialSpecialization { namespace FixedAliasTemplate { template struct S {}; - template using U = S; - template U &f(U, Ts...); - S &s1 = f({}, 0, 0.0); + template using U = S; // expected-note 2{{template parameter is declared here}} + template U &f(U, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}} + S &s1 = f({}, 0, 0.0); // expected-error {{no matching function}} +} + +namespace PR18401 { + template struct foo { }; + template using bar = foo; // expected-note 2{{template parameter is declared here}} expected-note {{'bar' declared here}} + template using baz = bar; // expected-error {{pack expansion used as argument for non-pack parameter of alias template}} + // FIXME: We should still record the alias template, but mark it as invalid. + template void f(baz); // expected-error {{no template named 'baz'; did you mean 'bar'}} expected-error {{pack expansion used as argument for non-pack}} + void g() { f(foo()); } // expected-error {{no matching function}} } diff --git a/test/CodeGenCXX/mangle-alias-template.cpp b/test/CodeGenCXX/mangle-alias-template.cpp index b6719c5452..1dbb3eb67a 100644 --- a/test/CodeGenCXX/mangle-alias-template.cpp +++ b/test/CodeGenCXX/mangle-alias-template.cpp @@ -11,10 +11,6 @@ template void g(T); template class F> void h(F); -template struct S {}; -template using U = S; -template void h(U, Ts...); - // CHECK-LABEL: define void @_Z1zv( void z() { vector VI; @@ -42,7 +38,4 @@ void z() { Vec> VVI; g(VVI); // CHECK: call void @_Z1gI6vectorIS0_Ii5allocIiEES1_IS3_EEEvT_( - - // CHECK: call void @_Z1hIJidEEv1UIDpT_ES2_ - h({}, 0, 0.0); } diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 2146a374e1..dc8574825d 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -3,6 +3,9 @@ // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING +template struct first_impl { typedef F type; }; +template using first = typename first_impl::type; + namespace simple_explicit_capture { void test() { int i; @@ -497,8 +500,6 @@ int run = fooT('a') + fooT(3.14); template void print(Ts ... ts) { } -template using first = F; - template auto fooV(Ts ... ts) { auto L = [](auto ... a) { auto M = [](decltype(a) ... b) { @@ -568,7 +569,6 @@ int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expe namespace variadic_tests_1 { template void print(Ts ... ts) { } -template using FirstType = F; template F& FirstArg(F& f, Rest...) { return f; } template int fooV(Ts ... ts) { @@ -582,7 +582,7 @@ template int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType{}); + N(first{}); }; M(a...); print("a = ", a..., "\n"); @@ -607,7 +607,7 @@ template int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType{}); + N(first{}); }; M(a...); return M; @@ -627,7 +627,7 @@ template int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType{}); + N(first{}); return N; }; M(a...); @@ -771,7 +771,6 @@ int run = test(); namespace fptr_with_decltype_return_type { -template using FirstType = F; template F& FirstArg(F& f, Rest& ... r) { return f; }; template auto vfun(Ts&& ... ts) { print(ts...); @@ -782,7 +781,7 @@ int test() { auto L = [](auto ... As) { return [](auto b) ->decltype(b) { - vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(FirstType{}); + vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(first{}); return decltype(b){}; }; }; @@ -913,4 +912,4 @@ int run2 = x2.fooG3(); -} //end ns inclass_lambdas_within_nested_classes \ No newline at end of file +} //end ns inclass_lambdas_within_nested_classes