From patchwork Mon Jan 21 20:09:43 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 214250 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id E92E42C007C for ; Tue, 22 Jan 2013 07:10:08 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1359403810; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:From:To:Cc:Subject:References:Date:In-Reply-To: Message-ID:User-Agent:MIME-Version:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=OwI/G9oDk0NLOPCvPCyDnXjil58=; b=d+zyipunfqLTtuWKi8WOrBE8GYFH1e2wnFUzWm8PU++0P6SimeSprXh+i0rTg9 6G3Yb+yDzafSdzMZbdZa7911oZ8DTOvli3OfhMucM0O7SmSOVuKCdWkbQUyYvDLA YBXA1RGe7cfSSQ+zfOWJcj4usuxdtFidLZuRVmY6cjnd4= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:From:To:Cc:Subject:References:X-URL:Date:In-Reply-To:Message-ID:User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=rof9U1mX9vUyjHztUfzGh/1k/Dp3vor27Ztp7/0XprdXuig7mc9tyEwzYYXCXl u3LTcRuu8rFq33oY4f1Ko7ETUNqVNDYAhRSKVGJs4B/sYb5v0o8sb6KL8AXuppo3 XOOfc9yF/XpKYKHJGRYGEDBczTojkPw3MT8AwPdedcFlc=; Received: (qmail 15876 invoked by alias); 21 Jan 2013 20:09:59 -0000 Received: (qmail 15860 invoked by uid 22791); 21 Jan 2013 20:09:58 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 21 Jan 2013 20:09:46 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r0LK9k3h029150 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 21 Jan 2013 15:09:46 -0500 Received: from localhost (ovpn-116-86.ams2.redhat.com [10.36.116.86]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r0LK9ib4015980 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 21 Jan 2013 15:09:45 -0500 Received: from localhost.localdomain (paname [127.0.0.1]) by localhost (Postfix) with ESMTP id E575841A31; Mon, 21 Jan 2013 21:09:43 +0100 (CET) Received: (from dodji@localhost) by localhost.localdomain (8.14.6/8.14.6/Submit) id r0LK9hcW015421; Mon, 21 Jan 2013 21:09:43 +0100 From: Dodji Seketeli To: Jason Merrill Cc: GCC Patches Subject: Re: [PATCH] PR c++/53609 - Wrong argument deduction for pack expansion in argument pack References: <50A6C0B0.8070407@redhat.com> <87vccjclke.fsf@redhat.com> <50BF6FCC.90907@redhat.com> <87ip8cb3d1.fsf@redhat.com> <50C66442.9010903@redhat.com> <87hansa8hz.fsf@redhat.com> <50C76202.8040909@redhat.com> <87txrs8fdu.fsf@redhat.com> <50C7A511.5080803@redhat.com> <87k3sn8lvl.fsf@redhat.com> <50CF6C5B.5070107@redhat.com> <87lict52e5.fsf@redhat.com> <50F9FBB4.8040405@redhat.com> X-URL: http://www.redhat.com Date: Mon, 21 Jan 2013 21:09:43 +0100 In-Reply-To: <50F9FBB4.8040405@redhat.com> (Jason Merrill's message of "Fri, 18 Jan 2013 20:49:40 -0500") Message-ID: <877gn6z4ag.fsf@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Jason Merrill writes: > On 12/19/2012 01:21 PM, Dodji Seketeli wrote: >> + tree aps; /* instance of ARGUMENT_PACK_SELECT >> + tree. */ > > Odd comment formatting. Oops, sorry for that. Fixed now. > >> + /* We could not find any argument packs that work, so we'll just >> + return an unsubstituted pack expansion. The caller must be >> + prepared to deal with this. */ > > I still find this comment confusing. I think it would be more correct > to say "we'll just return a substituted pack expansion". > > Also, it seems like the unsubstituted_packs code does what we want, so > you could use that directly rather than change len. Yeah, I got rid of the test + change altogether. > >> + if (unsubstituted_packs || use_pack_expansion_extra) >> { >> - if (real_packs) >> + if (use_pack_expansion_extra) > > It seems like the outer "if" is redundant here. Right, fixed. > >> + /* If the Ith argument pack element is a pack expansion, then >> + the Ith element resulting from the substituting is going to >> + be a pack expansion as well. */ >> + if (has_bare_parameter_packs (t)) >> + t = make_pack_expansion (t); > > Instead of walking through 't' here, I think it would be cheaper to > remember if the pack element was a pack expansion. In which case > maybe we don't need to split out has_bare_parameter_packs. I wonder why I haven't done that to begin with. It's definitely cheaper. >> + if (len > 0) >> { >> + for (i = 0; i < len; ++i) >> { > > The "if" seems redundant here, too. Removed. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ * pt.c (argument_pack_element_is_expansion_p) (make_argument_pack_select, use_pack_expansion_extra_args_p) (gen_elem_of_pack_expansion_instantiation): New static functions. (tsubst): When looking through an ARGUMENT_PACK_SELECT tree node, look through the possibly resulting pack expansion as well. (tsubst_pack_expansion): Use use_pack_expansion_extra_p to generalize when to use the PACK_EXPANSION_EXTRA_ARGS mechanism. Use gen_elem_of_pack_expansion_instantiation to build the instantiation piece-wise. Don't use arg_from_parm_pack_p anymore, as gen_elem_of_pack_expansion_instantiation and the change in tsubst above generalize this particular case. (arg_from_parm_pack_p): Remove this for it's not used by tsubst_pack_expansion anymore. gcc/testsuite/ * g++.dg/cpp0x/variadic139.C: New test. * g++.dg/cpp0x/variadic140.C: Likewise. * g++.dg/cpp0x/variadic141.C: Likewise. --- gcc/cp/pt.c | 359 ++++++++++++++++++------------- gcc/testsuite/g++.dg/cpp0x/variadic139.C | 14 ++ gcc/testsuite/g++.dg/cpp0x/variadic140.C | 22 ++ gcc/testsuite/g++.dg/cpp0x/variadic141.C | 22 ++ 4 files changed, 270 insertions(+), 147 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic139.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic140.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic141.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8ddc143..447e18d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -201,7 +201,6 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree, static tree listify (tree); static tree listify_autos (tree, tree); static tree template_parm_to_arg (tree t); -static bool arg_from_parm_pack_p (tree, tree); static tree current_template_args (void); static tree tsubst_template_parm (tree, tree, tsubst_flags_t); static tree instantiate_alias_template (tree, tree, tsubst_flags_t); @@ -3816,42 +3815,6 @@ template_parm_to_arg (tree t) return t; } -/* This function returns TRUE if PARM_PACK is a template parameter - pack and if ARG_PACK is what template_parm_to_arg returned when - passed PARM_PACK. */ - -static bool -arg_from_parm_pack_p (tree arg_pack, tree parm_pack) -{ - /* For clarity in the comments below let's use the representation - argument_pack' to denote an argument pack and its - elements. - - In the 'if' block below, we want to detect cases where - ARG_PACK is argument_pack. I.e, we want to - check if ARG_PACK is an argument pack which sole element is - the expansion of PARM_PACK. That argument pack is typically - created by template_parm_to_arg when passed a parameter - pack. */ - - if (arg_pack - && TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1 - && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0))) - { - tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0); - tree pattern = PACK_EXPANSION_PATTERN (expansion); - if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack)) - || (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern))) - /* The argument pack that the parameter maps to is just an - expansion of the parameter itself, such as one would - find in the implicit typedef of a class inside the - class itself. Consider this parameter "unsubstituted", - so that we will maintain the outer pack expansion. */ - return true; - } - return false; -} - /* Given a set of template parameters, return them as a set of template arguments. The template parameters are represented as a TREE_VEC, in the form documented in cp-tree.h for template arguments. */ @@ -9148,6 +9111,168 @@ make_fnparm_pack (tree spec_parm) return extract_fnparm_pack (NULL_TREE, &spec_parm); } +/* Return true iff the Ith element of the argument pack ARG_PACK is a + pack expansion. */ + +static bool +argument_pack_element_is_expansion_p (tree arg_pack, int i) +{ + tree vec = ARGUMENT_PACK_ARGS (arg_pack); + if (i >= TREE_VEC_LENGTH (vec)) + return false; + return PACK_EXPANSION_P (TREE_VEC_ELT (vec, i)); +} + + +/* Creates and return an ARGUMENT_PACK_SELECT tree node. */ + +static tree +make_argument_pack_select (tree arg_pack, unsigned index) +{ + tree aps = make_node (ARGUMENT_PACK_SELECT); + + ARGUMENT_PACK_SELECT_FROM_PACK (aps) = arg_pack; + ARGUMENT_PACK_SELECT_INDEX (aps) = index; + + return aps; +} + +/* This is a subroutine of tsubst_pack_expansion. + + It returns TRUE if we need to use the PACK_EXPANSION_EXTRA_ARGS + mechanism to store the (non complete list of) arguments of the + substitution and return a non substituted pack expansion, in order + to wait for when we have enough arguments to really perform the + substitution. */ + +static bool +use_pack_expansion_extra_args_p (tree parm_packs, + int arg_pack_len, + bool has_empty_arg) +{ + if (parm_packs == NULL_TREE) + return false; + + bool has_expansion_arg = false; + for (int i = 0 ; i < arg_pack_len; ++i) + { + bool has_non_expansion_arg = false; + for (tree parm_pack = parm_packs; + parm_pack; + parm_pack = TREE_CHAIN (parm_pack)) + { + tree arg = TREE_VALUE (parm_pack); + + if (argument_pack_element_is_expansion_p (arg, i)) + has_expansion_arg = true; + else + has_non_expansion_arg = true; + } + + /* If one pack has an expansion and another pack has a normal + argument or if one pack has an empty argument another one + hasn't then tsubst_pack_expansion cannot perform the + substitution and need to fall back on the + PACK_EXPANSION_EXTRA mechanism. */ + if ((has_expansion_arg && has_non_expansion_arg) + || (has_empty_arg && (has_expansion_arg || has_non_expansion_arg))) + return true; + } + return false; +} + +/* [temp.variadic]/6 says that: + + The instantiation of a pack expansion [...] + produces a list E1,E2, ..., En, where N is the number of elements + in the pack expansion parameters. + + This subroutine of tsubst_pack_expansion produces one of these Ei. + + PATTERN is the pattern of the pack expansion. PARM_PACKS is a + TREE_LIST in which each TREE_PURPOSE is a parameter pack of + PATTERN, and each TREE_VALUE is its corresponding argument pack. + INDEX is the index 'i' of the element Ei to produce. ARGS, + COMPLAIN, and IN_DECL are the same parameters as for the + tsubst_pack_expansion function. + + The function returns the resulting Ei upon successful completion, + or error_mark_node. + + Note that this function possibly modifies the ARGS parameter, so + it's the responsibility of the caller to restore it. */ + +static tree +gen_elem_of_pack_expansion_instantiation (tree pattern, + tree parm_packs, + unsigned index, + tree args /* This parm gets + modified. */, + tsubst_flags_t complain, + tree in_decl) +{ + tree t; + bool ith_elem_is_expansion = false; + + /* For each parameter pack, change the substitution of the parameter + pack to the ith argument in its argument pack, then expand the + pattern. */ + for (tree pack = parm_packs; pack; pack = TREE_CHAIN (pack)) + { + tree parm = TREE_PURPOSE (pack); + tree arg_pack = TREE_VALUE (pack); + tree aps; /* instance of ARGUMENT_PACK_SELECT. */ + + ith_elem_is_expansion |= + PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), + index)); + /* Select the Ith argument from the pack. */ + if (TREE_CODE (parm) == PARM_DECL) + { + if (index == 0) + { + aps = make_argument_pack_select (arg_pack, index); + mark_used (parm); + register_local_specialization (aps, parm); + } + else + aps = retrieve_local_specialization (parm); + } + else + { + int idx, level; + template_parm_level_and_index (parm, &level, &idx); + + if (index == 0) + { + aps = make_argument_pack_select (arg_pack, index); + /* Update the corresponding argument. */ + TMPL_ARG (args, level, idx) = aps; + } + else + /* Re-use the ARGUMENT_PACK_SELECT. */ + aps = TMPL_ARG (args, level, idx); + } + ARGUMENT_PACK_SELECT_INDEX (aps) = index; + } + + /* Substitute into the PATTERN with the (possibly altered) + arguments. */ + if (!TYPE_P (pattern)) + t = tsubst_expr (pattern, args, complain, in_decl, + /*integral_constant_expression_p=*/false); + else + t = tsubst (pattern, args, complain, in_decl); + + /* If the Ith argument pack element is a pack expansion, then + the Ith element resulting from the substituting is going to + be a pack expansion as well. */ + if (ith_elem_is_expansion) + t = make_pack_expansion (t); + + return t; +} + /* Substitute ARGS into T, which is an pack expansion (i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node @@ -9160,8 +9285,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, tree pattern; tree pack, packs = NULL_TREE; bool unsubstituted_packs = false; - bool real_packs = false; - int missing_level = 0; int i, len = -1; tree result; struct pointer_map_t *saved_local_specializations = NULL; @@ -9240,14 +9363,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, return result; } - if (arg_from_parm_pack_p (arg_pack, parm_pack)) - /* The argument pack that the parameter maps to is just an - expansion of the parameter itself, such as one would find - in the implicit typedef of a class inside the class itself. - Consider this parameter "unsubstituted", so that we will - maintain the outer pack expansion. */ - arg_pack = NULL_TREE; - if (arg_pack) { int my_len = @@ -9275,13 +9390,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, return error_mark_node; } - if (TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1 - && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), - 0))) - /* This isn't a real argument pack yet. */; - else - real_packs = true; - /* Keep track of the parameter packs and their corresponding argument packs. */ packs = tree_cons (parm_pack, arg_pack, packs); @@ -9293,59 +9401,39 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, well as the missing_level counter because function parameter packs don't have a level. */ unsubstituted_packs = true; - if (!missing_level || missing_level > level) - missing_level = level; } } + /* Do we need to use the PACK_EXPANSION_EXTRA_ARGS mechanism? */ + bool use_pack_expansion_extra_args = + use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs); + /* We cannot expand this expansion expression, because we don't have all of the argument packs we need. */ - if (unsubstituted_packs) + if (use_pack_expansion_extra_args) { - if (real_packs) - { - /* We got some full packs, but we can't substitute them in until we - have values for all the packs. So remember these until then. */ - tree save_args; - - t = make_pack_expansion (pattern); + /* We got some full packs, but we can't substitute them in until we + have values for all the packs. So remember these until then. */ - /* The call to add_to_template_args above assumes no overlap - between saved args and new args, so prune away any fake - args, i.e. those that satisfied arg_from_parm_pack_p above. */ - if (missing_level && levels >= missing_level) - { - gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args) - && missing_level > 1); - TREE_VEC_LENGTH (args) = missing_level - 1; - save_args = copy_node (args); - TREE_VEC_LENGTH (args) = levels; - } - else - save_args = args; - - PACK_EXPANSION_EXTRA_ARGS (t) = save_args; - } + t = make_pack_expansion (pattern); + PACK_EXPANSION_EXTRA_ARGS (t) = args; + return t; + } + else if (unsubstituted_packs) + { + /* There were no real arguments, we're just replacing a parameter + pack with another version of itself. Substitute into the + pattern and return a PACK_EXPANSION_*. The caller will need to + deal with that. */ + if (TREE_CODE (t) == EXPR_PACK_EXPANSION) + t = tsubst_expr (pattern, args, complain, in_decl, + /*integral_constant_expression_p=*/false); else - { - /* There were no real arguments, we're just replacing a parameter - pack with another version of itself. Substitute into the - pattern and return a PACK_EXPANSION_*. The caller will need to - deal with that. */ - if (TREE_CODE (t) == EXPR_PACK_EXPANSION) - t = tsubst_expr (pattern, args, complain, in_decl, - /*integral_constant_expression_p=*/false); - else - t = tsubst (pattern, args, complain, in_decl); - t = make_pack_expansion (t); - } + t = tsubst (pattern, args, complain, in_decl); + t = make_pack_expansion (t); return t; } - /* We could not find any argument packs that work. */ - if (len < 0) - return error_mark_node; - if (need_local_specializations) { /* We're in a late-specified return type, so create our own local @@ -9361,55 +9449,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, result = make_tree_vec (len); for (i = 0; i < len; ++i) { - /* For parameter pack, change the substitution of the parameter - pack to the ith argument in its argument pack, then expand - the pattern. */ - for (pack = packs; pack; pack = TREE_CHAIN (pack)) - { - tree parm = TREE_PURPOSE (pack); - tree arg; - - /* Select the Ith argument from the pack. */ - if (TREE_CODE (parm) == PARM_DECL) - { - if (i == 0) - { - arg = make_node (ARGUMENT_PACK_SELECT); - ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack); - mark_used (parm); - register_local_specialization (arg, parm); - } - else - arg = retrieve_local_specialization (parm); - } - else - { - int idx, level; - template_parm_level_and_index (parm, &level, &idx); - - if (i == 0) - { - arg = make_node (ARGUMENT_PACK_SELECT); - ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack); - /* Update the corresponding argument. */ - TMPL_ARG (args, level, idx) = arg; - } - else - /* Re-use the ARGUMENT_PACK_SELECT. */ - arg = TMPL_ARG (args, level, idx); - } - ARGUMENT_PACK_SELECT_INDEX (arg) = i; - } - - /* Substitute into the PATTERN with the altered arguments. */ - if (!TYPE_P (pattern)) - TREE_VEC_ELT (result, i) = - tsubst_expr (pattern, args, complain, in_decl, - /*integral_constant_expression_p=*/false); - else - TREE_VEC_ELT (result, i) = tsubst (pattern, args, complain, in_decl); - - if (TREE_VEC_ELT (result, i) == error_mark_node) + t = gen_elem_of_pack_expansion_instantiation (pattern, packs, + i, + args, complain, + in_decl); + TREE_VEC_ELT (result, i) = t; + if (t == error_mark_node) { result = error_mark_node; break; @@ -9427,6 +9472,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, else { int idx, level; + + if (TREE_VALUE (pack) == NULL_TREE) + continue; + template_parm_level_and_index (parm, &level, &idx); /* Update the corresponding argument. */ @@ -11163,8 +11212,24 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) arg = TMPL_ARG (args, level, idx); if (arg && TREE_CODE (arg) == ARGUMENT_PACK_SELECT) - /* See through ARGUMENT_PACK_SELECT arguments. */ - arg = ARGUMENT_PACK_SELECT_ARG (arg); + { + /* See through ARGUMENT_PACK_SELECT arguments. */ + arg = ARGUMENT_PACK_SELECT_ARG (arg); + /* If the selected argument is an expansion E, that most + likely means we were called from + gen_elem_of_pack_expansion_instantiation during the + substituting of pack an argument pack (which Ith + element is a pack expansion, where I is + ARGUMENT_PACK_SELECT_INDEX) into a pack expansion. + In this case, the Ith element resulting from this + substituting is going to be a pack expansion, which + pattern is the pattern of E. Let's return the + pattern of E, and + gen_elem_of_pack_expansion_instantiation will + build the resulting pack expansion from it. */ + if (PACK_EXPANSION_P (arg)) + arg = PACK_EXPANSION_PATTERN (arg); + } } if (arg == error_mark_node) diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic139.C b/gcc/testsuite/g++.dg/cpp0x/variadic139.C new file mode 100644 index 0000000..a1c64f3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic139.C @@ -0,0 +1,14 @@ +// Origin: PR c++/53609 +// { dg-do compile { target c++11 } } + +template struct List {}; +template struct Z {static const int value = T;}; +template using LZ = List...>; + +template +struct F +{ + using N = LZ; +}; + +F, Z<2> >::N A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic140.C b/gcc/testsuite/g++.dg/cpp0x/variadic140.C new file mode 100644 index 0000000..17ca9e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic140.C @@ -0,0 +1,22 @@ +// Origin: PR c++/53609 +// { dg-do compile { target c++11 } } + +template struct List{ static const bool is_ok = false;}; +template struct Z +{ + static const int value = T; + static const int value_square = T * T; +}; + +template class U> +struct List, U<3>, U<4>, U<9>> { static const bool is_ok = true;}; + +template using LZ = List...>; + +template +struct F +{ + using N = LZ; +}; + +static_assert (F, Z<3>>::N::is_ok, ""); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic141.C b/gcc/testsuite/g++.dg/cpp0x/variadic141.C new file mode 100644 index 0000000..6b893a7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic141.C @@ -0,0 +1,22 @@ +// Origin: PR c++/53609 +// { dg-do compile { target c++11 } } + +template struct List{ static const bool is_ok = false;}; +template struct Z +{ + static const int value = T; + static const int value_square = T * T; +}; + +template class U> +struct List, U<3>, U<4>, U<9>> { static const bool is_ok = true;}; + +template using LZ = List...>; + +template +struct F +{ + using N = LZ::value, Z<9>::value>; +}; + +static_assert (F, Z<3>>::N::is_ok, "");