http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53609



--- Comment #3 from Dodji Seketeli <dodji at gcc dot gnu.org> 2013-01-22 
10:05:13 UTC ---

Author: dodji

Date: Tue Jan 22 10:05:05 2013

New Revision: 195367



URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195367

Log:

PR c++/53609 - Wrong variadic template pack expansion in alias template



Consider this example:



     1    template<class...I> struct List {};

     2    template<int T> struct Z {static const int value = T;};

     3    template<int...T> using LZ = List<Z<T>...>;

     4

     5    template<class...U>

     6    struct F

     7    {

     8      using N = LZ<U::value...>; //#1 This should amount to

List<Z<U::value>...>

     9    }

    10

    11    F<Z<1>, Z<2> >::N A; //#2



which G++ fails to compile, with this error message:



test-PR53609-3.cc: In instantiation of 'struct F<Z<1>, Z<2> >':

test-PR53609-3.cc:11:15:   required from here

test-PR53609-3.cc:3:43: error: wrong number of template arguments (2, should be

1)

 template<int...T> using LZ = List<Z<T>...>;

                                           ^

test-PR53609-3.cc:2:24: error: provided for 'template<int T> struct Z'

 template<int T> struct Z {static const int value = T;};



I think this is because in #1, when we substitute the argument pack

{U::value...} into the pack expansion Z<T>..., tsubst_pack_expansion

yields Z<U::value...>, instead of Z<U::value>..., so the instantiation

of LZ amounts to List<Z<U::value...> >, instead of

List<Z<U::value>...>.



The idea of this patch is to make tsubst_pack_expansion support

substituting an argument pack (into a pack expansion) where one of the

arguments (let's call it the Ith argument) is itself a pack expansion

P.  In that case, the Ith element resulting from the substituting

should be a pack expansion P'.



The pattern of P' is then the pattern of P into which the pattern of

the Ith argument of the argument pack has been substituted.



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.



Added:

    trunk/gcc/testsuite/g++.dg/cpp0x/variadic139.C

    trunk/gcc/testsuite/g++.dg/cpp0x/variadic140.C

    trunk/gcc/testsuite/g++.dg/cpp0x/variadic141.C

Modified:

    trunk/gcc/cp/ChangeLog

    trunk/gcc/cp/pt.c

    trunk/gcc/testsuite/ChangeLog

Reply via email to