With the infrastructure of the previous patch in place, this patch easily uses TEMPLATE_ID_TYPE to represent unbound specializations of alias templates, thus fixing PR c++/51239.
A new function introduced to fix that bug is also used to address PR c++/51180 by fixing the representation of template specializations where the arguments contain a pack expansion. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ PR c++/51239 PR c++/51180 * cp-tree.h (any_pack_expansion_template_argument_p): Declare new function. * pt.c (any_pack_expansion_template_argument_p): Define it. (coerce_template_parms, lookup_template_class_1): Use it. gcc/testsuite/ PR c++/51239 PR c++/51180 * g++.dg/cpp0x/alias-decl-18.C: New test. * g++.dg/cpp0x/alias-decl-19.C: Likewise. * g++.dg/cpp0x/alias-decl-15.C: This was wrongly expected to fail before. Adjust accordingly. --- gcc/cp/cp-tree.h | 1 + gcc/cp/pt.c | 32 +++++++++++++++++++++++++++- gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C | 8 +++--- gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C | 29 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-19.C | 19 ++++++++++++++++ 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-19.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index fa5bf7f..ef0ef1b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5333,6 +5333,7 @@ extern int processing_template_parmlist; extern bool dependent_type_p (tree); extern bool dependent_scope_p (tree); extern bool any_dependent_template_arguments_p (const_tree); +extern bool any_pack_expansion_template_argument_p (tree); extern bool dependent_template_p (tree); extern bool dependent_template_id_p (tree, tree); extern bool type_dependent_expression_p (tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7d00770..634e7e0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6787,7 +6787,8 @@ coerce_template_parms (tree parms, && require_all_args && (!use_default_args || (TREE_VEC_ELT (parms, nargs) != error_mark_node - && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)))))) + && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)))) + && !any_pack_expansion_template_argument_p (inner_args))) { if (complain & tf_error) { @@ -7484,6 +7485,14 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, } else if (DECL_ALIAS_TEMPLATE_P (gen_tmpl)) { + if (any_pack_expansion_template_argument_p (arglist)) + /* So we don't yet know the number of arguments the + alias template specialization has. Let's build a + representation that keeps the arguments "unapplied" + to the alias template for now, so that we can apply + the them later when they are fully known. */ + return build_template_id_type (gen_tmpl, arglist); + /* The user referred to a specialization of an alias template represented by GEN_TMPL. @@ -19894,6 +19903,27 @@ any_dependent_template_arguments_p (const_tree args) return false; } +/* Return true if ARGS (a TREE_VEC of template arguments) contains + any pack expansion. */ + +bool +any_pack_expansion_template_argument_p (tree args) +{ + int i; + + if (args == NULL_TREE || TREE_CODE (args) != TREE_VEC) + return false; + + for (i = 0; i < TREE_VEC_LENGTH (args); ++i) + { + tree elt = TREE_VEC_ELT (args, i); + if (elt != NULL_TREE && PACK_EXPANSION_P (elt)) + return true; + } + + return false; +} + /* Returns TRUE if the template TMPL is dependent. */ bool diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C index 2bc9b11..19f1a8d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C @@ -1,8 +1,8 @@ // Origin PR c++/51194 // { dg-options "-std=c++0x" } -template<class U, class V> //#1 -struct foo {}; // { dg-error "provided for|foo" } +template<class U, class V> +struct foo {}; template<class U, class V=char> struct P {}; @@ -10,8 +10,8 @@ struct P {}; template<template<class... U> class... TT> struct bar { template<class... Args> - using mem = P<TT<Args...>...>;//#2 { dg-error "wrong number of|arguments" } + using mem = P<TT<Args...>...>; }; -bar<foo>::mem<int, char> b;//#3 { dg-error "invalid type" } +bar<foo>::mem<int, char> b; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C new file mode 100644 index 0000000..311ab58 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C @@ -0,0 +1,29 @@ +// Origin PR c++/51239 +// { dg-options "-std=c++11" } + +struct S {}; + +template<typename T, typename...> +using head = T; + +template<typename... Ts> +using x = head<Ts...>; + +x<int, char> i0; +x<char> i1; +x<unsigned, int, int> i2; +x<S, char>i3; + +void f0(int); +void f1(char); +void f2(unsigned); +void f3(S); + +void +g() +{ + f0(i0); + f1(i1); + f2(i2); + f3(i3); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-19.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-19.C new file mode 100644 index 0000000..ff7b822 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-19.C @@ -0,0 +1,19 @@ +// Origin PR c++/51180 +// { dg-options "-std=c++11" } + +template<class, class> +struct t2 // { dg-error "provided for" } +{ +}; + +template<template<class...> class M> +struct m +{ + template<class... B> + using inner = M<B...>; // { dg-error "wrong number of template arg" } +}; + +m<t2> sta1; // <-- this one is valid +m<t2>::inner<int, int> sta2; // <-- and this one as well +m<t2>::inner<char> sta3;// { dg-error "invalid" } +m<t2>::inner<char, int, int> sta4;// { dg-error "invalid" } -- 1.7.6.4 -- Dodji