diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp | 15 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-alias-template.cpp | 7 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx1y-generic-lambdas.cpp | 17 |
7 files changed, 44 insertions, 44 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1ae6d2f143a..bf8c051910a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2a900f36e3e..270d18dde62 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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<TemplateArgument> &Converted, - bool *ExpansionIntoFixedList = 0); + SmallVectorImpl<TemplateArgument> &Converted); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, const TemplateArgumentLoc &Arg, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b468e31f097..97137184c29 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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<TemplateArgument, 4> 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<TypeAliasTemplateDecl>(Template))) { + if (TypeAliasTemplateDecl *AliasTemplate = + dyn_cast<TypeAliasTemplateDecl>(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<TemplateArgument, 4> Converted; - bool ExpansionIntoFixedList = false; if (CheckTemplateArgumentList( Template, TemplateNameLoc, const_cast<TemplateArgumentListInfo &>(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<TemplateArgument> &Converted, - bool *ExpansionIntoFixedList) { - if (ExpansionIntoFixedList) - *ExpansionIntoFixedList = false; - + SmallVectorImpl<TemplateArgument> &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<TypeAliasTemplateDecl>(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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8c988f07edf..22f13d7d2f7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2480,11 +2480,10 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Check that the template argument list is well-formed for this template. SmallVector<TemplateArgument, 4> Converted; - bool ExpansionIntoFixedList = false; if (SemaRef.CheckTemplateArgumentList( VarTemplate, VarTemplate->getLocStart(), const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false, - Converted, &ExpansionIntoFixedList)) + Converted)) return 0; // Find the variable template specialization declaration that diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp index fb727543efa..a466be0a61d 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -121,7 +121,16 @@ namespace PartialSpecialization { namespace FixedAliasTemplate { template<typename,typename,typename> struct S {}; - template<typename T, typename U> using U = S<T, int, U>; - template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); - S<int, int, double> &s1 = f({}, 0, 0.0); + template<typename T, typename U> using U = S<T, int, U>; // expected-note 2{{template parameter is declared here}} + template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}} + S<int, int, double> &s1 = f({}, 0, 0.0); // expected-error {{no matching function}} +} + +namespace PR18401 { + template<typename... Args> struct foo { }; + template<typename T, typename... Args> using bar = foo<T, Args...>; // expected-note 2{{template parameter is declared here}} expected-note {{'bar' declared here}} + template<typename T, typename... Args> using baz = bar<Args..., T>; // 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<typename...T> void f(baz<T...>); // expected-error {{no template named 'baz'; did you mean 'bar'}} expected-error {{pack expansion used as argument for non-pack}} + void g() { f(foo<int, char, double>()); } // expected-error {{no matching function}} } diff --git a/clang/test/CodeGenCXX/mangle-alias-template.cpp b/clang/test/CodeGenCXX/mangle-alias-template.cpp index b6719c54523..1dbb3eb67ad 100644 --- a/clang/test/CodeGenCXX/mangle-alias-template.cpp +++ b/clang/test/CodeGenCXX/mangle-alias-template.cpp @@ -11,10 +11,6 @@ template<typename T> void g(T); template<template<typename> class F> void h(F<int>); -template<typename,typename,typename> struct S {}; -template<typename T, typename U> using U = S<T, int, U>; -template<typename...Ts> void h(U<Ts...>, Ts...); - // CHECK-LABEL: define void @_Z1zv( void z() { vector<int> VI; @@ -42,7 +38,4 @@ void z() { Vec<Vec<int>> VVI; g(VVI); // CHECK: call void @_Z1gI6vectorIS0_Ii5allocIiEES1_IS3_EEEvT_( - - // CHECK: call void @_Z1hIJidEEv1UIDpT_ES2_ - h({}, 0, 0.0); } diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp index 2146a374e12..dc8574825dd 100644 --- a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/clang/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<class F, class ...Rest> struct first_impl { typedef F type; }; +template<class ...Args> using first = typename first_impl<Args...>::type; + namespace simple_explicit_capture { void test() { int i; @@ -497,8 +500,6 @@ int run = fooT('a') + fooT(3.14); template<class ... Ts> void print(Ts ... ts) { } -template<class F, class ... Rest> using first = F; - template<class ... Ts> 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<class ... Ts> void print(Ts ... ts) { } -template<class F, class ... Rest> using FirstType = F; template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; } template<class ... Ts> int fooV(Ts ... ts) { @@ -582,7 +582,7 @@ template<class ... Ts> int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType<Ts...>{}); + N(first<Ts...>{}); }; M(a...); print("a = ", a..., "\n"); @@ -607,7 +607,7 @@ template<class ... Ts> int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType<Ts...>{}); + N(first<Ts...>{}); }; M(a...); return M; @@ -627,7 +627,7 @@ template<class ... Ts> int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType<Ts...>{}); + N(first<Ts...>{}); return N; }; M(a...); @@ -771,7 +771,6 @@ int run = test(); namespace fptr_with_decltype_return_type { -template<class F, class ... Ts> using FirstType = F; template<class F, class ... Rest> F& FirstArg(F& f, Rest& ... r) { return f; }; template<class ... Ts> 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<decltype(As)...>{}); + vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(first<decltype(As)...>{}); 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 |