+2008-03-27 Douglas Gregor <doug.gregor@gmail.com>
+
+ * pt.c (tsubst_copy) <case SIZEOF_EXPR>: 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) <case SIZEOF_EXPR>: 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 <jakub@redhat.com>
PR c++/35546
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,
/* 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 */
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:
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;
+2008-03-27 Douglas Gregor <doug.gregor@gmail.com>
+
+ * g++.dg/cpp0x/variadic91.C: New.
+
2008-03-27 Zdenek Dvorak <ook@ucw.cz>
* gcc.dg/tree-ssa/loop-32.c: New testcase.
--- /dev/null
+// { dg-options "-std=c++0x" }
+template<int N> struct Int2Type { };
+
+template<typename... T>
+struct Outer {
+ template<typename... U>
+ void foo(Int2Type<sizeof...(T)>, Int2Type<sizeof...(U)>);
+};
+
+
+Outer<short, int, long> outer;
+
+void g4() {
+ outer.foo<float, double>(Int2Type<3>(), Int2Type<2>());
+}
+
+template<typename... T, template<T...> class X> void f1();