summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-01-09 02:22:22 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-01-09 02:22:22 +0000
commit83b11aae180d67ba06764a94dca4ec320e65b1f3 (patch)
tree5f8d89c9c6e417b117f2f8303d248dea7405f43b
parent73f7b0273efabfb414d14d2c68cfb70b808ba34a (diff)
downloadbcm5719-llvm-83b11aae180d67ba06764a94dca4ec320e65b1f3.tar.gz
bcm5719-llvm-83b11aae180d67ba06764a94dca4ec320e65b1f3.zip
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. llvm-svn: 198833
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Sema/Sema.h10
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp34
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp3
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp15
-rw-r--r--clang/test/CodeGenCXX/mangle-alias-template.cpp7
-rw-r--r--clang/test/SemaCXX/cxx1y-generic-lambdas.cpp17
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
OpenPOWER on IntegriCloud