From: Douglas Gregor Date: Thu, 27 Mar 2008 14:31:47 +0000 (+0000) Subject: pt.c (tsubst_copy): Cope with tsubst_pack_expansion returning a pack expansion... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=063cc99c4658d52b33b37f4173d304efa9c68b00;p=gcc.git pt.c (tsubst_copy): Cope with tsubst_pack_expansion returning a pack expansion... 2008-03-27 Douglas Gregor * pt.c (tsubst_copy) : Cope with tsubst_pack_expansion returning a pack expansion, or a TREE_VEC ending in a pack expansion, both of which can occur when substituting into a nested template. (tsubst_copy_and_build) : When we're instantiating the sizeof...(X) form, make tsubst_copy do the work. * parser.c (cp_parser_template_parameter): Deal with unnamed non-type template parameter packs identified by pack expansions in the parameter type. 2008-03-27 Douglas Gregor * g++.dg/cpp0x/variadic91.C: New. From-SVN: r133642 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 447bfc04117..68c17fd3ab6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2008-03-27 Douglas Gregor + + * pt.c (tsubst_copy) : Cope with + tsubst_pack_expansion returning a pack expansion, or a TREE_VEC + ending in a pack expansion, both of which can occur when + substituting into a nested template. + (tsubst_copy_and_build) : When we're + instantiating the sizeof...(X) form, make tsubst_copy do the work. + * parser.c (cp_parser_template_parameter): Deal with unnamed + non-type template parameter packs identified by pack expansions in + the parameter type. + 2008-03-26 Jakub Jelinek PR c++/35546 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8a9c3e29563..87b353e08c0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -9435,29 +9435,41 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, maybe_warn_variadic_templates (); *is_parameter_pack = true; + } + /* We might end up with a pack expansion as the type of the non-type + template parameter, in which case this is a non-type template + parameter pack. */ + else if (parameter_declarator + && parameter_declarator->decl_specifiers.type + && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type)) + { + *is_parameter_pack = true; + parameter_declarator->decl_specifiers.type = + PACK_EXPANSION_PATTERN (parameter_declarator->decl_specifiers.type); + } + if (*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_EQ)) + { /* Parameter packs cannot have default arguments. However, a user may try to do so, so we'll parse them and give an appropriate diagnostic here. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) - { - /* Consume the `='. */ - cp_lexer_consume_token (parser->lexer); - /* Find the name of the parameter pack. */ - id_declarator = parameter_declarator->declarator; - while (id_declarator && id_declarator->kind != cdk_id) - id_declarator = id_declarator->declarator; - - if (id_declarator && id_declarator->kind == cdk_id) - error ("template parameter pack %qD cannot have a default argument", - id_declarator->u.id.unqualified_name); - else - error ("template parameter pack cannot have a default argument"); - - /* Parse the default argument, but throw away the result. */ - cp_parser_default_argument (parser, /*template_parm_p=*/true); - } + /* Consume the `='. */ + cp_lexer_consume_token (parser->lexer); + + /* Find the name of the parameter pack. */ + id_declarator = parameter_declarator->declarator; + while (id_declarator && id_declarator->kind != cdk_id) + id_declarator = id_declarator->declarator; + + if (id_declarator && id_declarator->kind == cdk_id) + error ("template parameter pack %qD cannot have a default argument", + id_declarator->u.id.unqualified_name); + else + error ("template parameter pack cannot have a default argument"); + + /* Parse the default argument, but throw away the result. */ + cp_parser_default_argument (parser, /*template_parm_p=*/true); } parm = grokdeclarator (parameter_declarator->declarator, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6f7efa6e55e..6954a1bee9e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -9916,9 +9916,30 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) /* We only want to compute the number of arguments. */ tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args, complain, in_decl); + int len; + + if (TREE_CODE (expanded) == TREE_VEC) + len = TREE_VEC_LENGTH (expanded); + if (expanded == error_mark_node) return error_mark_node; - return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded)); + else if (PACK_EXPANSION_P (expanded) + || (TREE_CODE (expanded) == TREE_VEC + && len > 0 + && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1)))) + { + if (TREE_CODE (expanded) == TREE_VEC) + expanded = TREE_VEC_ELT (expanded, len - 1); + + if (TYPE_P (expanded)) + return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, + complain & tf_error); + else + return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR, + complain & tf_error); + } + else + return build_int_cst (size_type_node, len); } /* Fall through */ @@ -10918,14 +10939,7 @@ tsubst_copy_and_build (tree t, case SIZEOF_EXPR: if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) - { - /* We only want to compute the number of arguments. */ - tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args, - complain, in_decl); - if (expanded == error_mark_node) - return error_mark_node; - return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded)); - } + return tsubst_copy (t, args, complain, in_decl); /* Fall through */ case ALIGNOF_EXPR: @@ -12920,7 +12934,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) tree parmvec = TYPE_TI_ARGS (parm); tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg)); tree parm_parms - = DECL_INNERMOST_TEMPLATE_PARMS + = DECL_INNERMOST_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm)); int i, len; int parm_variadic_p = 0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2a130ae11d1..42b5dcd80e9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-03-27 Douglas Gregor + + * g++.dg/cpp0x/variadic91.C: New. + 2008-03-27 Zdenek Dvorak * gcc.dg/tree-ssa/loop-32.c: New testcase. diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic91.C b/gcc/testsuite/g++.dg/cpp0x/variadic91.C new file mode 100644 index 00000000000..d78b791fbf4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic91.C @@ -0,0 +1,17 @@ +// { dg-options "-std=c++0x" } +template struct Int2Type { }; + +template +struct Outer { + template + void foo(Int2Type, Int2Type); +}; + + +Outer outer; + +void g4() { + outer.foo(Int2Type<3>(), Int2Type<2>()); +} + +template class X> void f1();