From d6027563413543e1607fdc8752e4c4f238fad350 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sun, 2 Oct 2011 17:45:01 -0400 Subject: [PATCH] re PR c++/35722 ([C++0x] Variadic templates expansion into non-variadic class template) PR c++/35722 Implement N2555 (expanding pack expansion to fixed parm list) * pt.c (coerce_template_parms): Allow expanding a pack expansion to a fixed-length argument list. (unify_pack_expansion): Handle explicit args properly. (unify) [TREE_VEC]: Handle pack expansions here. [TYPE_ARGUMENT_PACK]: Not here. (tsubst_pack_expansion): Don't try to do partial substitution. (pack_deducible_p): New. (fn_type_unification): Use it. (find_parameter_packs_r): Take the TYPE_MAIN_VARIANT of a type parameter. (check_non_deducible_conversion): Split from type_unification_real. (unify_one_argument): Split from type_unification_real... (unify_pack_expansion): ...and here. Drop call_args_p parm. (type_unification_real, unify, more_specialized_fn): Adjust. From-SVN: r179436 --- gcc/cp/ChangeLog | 17 + gcc/cp/pt.c | 606 +++++++++--------- gcc/testsuite/ChangeLog | 5 + .../g++.dg/cpp0x/variadic-explicit1.C | 11 + .../g++.dg/cpp0x/variadic-nondeduce1.C | 12 + gcc/testsuite/g++.dg/cpp0x/variadic105.C | 4 +- gcc/testsuite/g++.dg/cpp0x/variadic117.C | 11 + gcc/testsuite/g++.dg/cpp0x/variadic118.C | 11 + gcc/testsuite/g++.dg/cpp0x/variadic35.C | 3 +- gcc/testsuite/g++.dg/cpp0x/variadic65.C | 7 +- gcc/testsuite/g++.dg/cpp0x/variadic82.C | 4 +- gcc/testsuite/g++.dg/cpp0x/variadic83.C | 4 +- libstdc++-v3/ChangeLog | 5 + libstdc++-v3/testsuite/util/testsuite_tr1.h | 9 +- 14 files changed, 379 insertions(+), 330 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic117.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic118.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a605c9fc32d..9bcec3274e0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,22 @@ 2011-10-02 Jason Merrill + PR c++/35722 + Implement N2555 (expanding pack expansion to fixed parm list) + * pt.c (coerce_template_parms): Allow expanding a pack expansion + to a fixed-length argument list. + (unify_pack_expansion): Handle explicit args properly. + (unify) [TREE_VEC]: Handle pack expansions here. + [TYPE_ARGUMENT_PACK]: Not here. + (tsubst_pack_expansion): Don't try to do partial substitution. + (pack_deducible_p): New. + (fn_type_unification): Use it. + (find_parameter_packs_r): Take the TYPE_MAIN_VARIANT + of a type parameter. + (check_non_deducible_conversion): Split from type_unification_real. + (unify_one_argument): Split from type_unification_real... + (unify_pack_expansion): ...and here. Drop call_args_p parm. + (type_unification_real, unify, more_specialized_fn): Adjust. + * class.c (fixed_type_or_null): Handle NSDMI. * method.c (walk_field_subobs): Disable NSDMI noexcept checking for now. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4d57f94d2b1..015ee377707 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -165,7 +165,7 @@ static int template_decl_level (tree); static int check_cv_quals_for_unify (int, tree, tree); static void template_parm_level_and_index (tree, int*, int*); static int unify_pack_expansion (tree, tree, tree, - tree, int, bool, bool, bool); + tree, unification_kind_t, bool, bool); static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree); static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree); static tree tsubst_template_parms (tree, tree, tsubst_flags_t); @@ -2961,6 +2961,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) break; case TEMPLATE_TYPE_PARM: + t = TYPE_MAIN_VARIANT (t); case TEMPLATE_TEMPLATE_PARM: if (TEMPLATE_TYPE_PARAMETER_PACK (t)) parameter_pack_p = true; @@ -6741,22 +6742,10 @@ coerce_template_parms (tree parms, { if (PACK_EXPANSION_P (arg)) { - if (complain & tf_error) - { - /* FIXME this restriction was removed by N2555; see - bug 35722. */ - /* If ARG is a pack expansion, but PARM is not a - template parameter pack (if it were, we would have - handled it above), we're trying to expand into a - fixed-length argument list. */ - if (TREE_CODE (arg) == EXPR_PACK_EXPANSION) - sorry ("cannot expand %<%E%> into a fixed-length " - "argument list", arg); - else - sorry ("cannot expand %<%T%> into a fixed-length " - "argument list", arg); - } - ++lost; + /* We don't know how many args we have yet, just + use the unconverted ones for now. */ + new_inner_args = args; + break; } } else if (require_all_args) @@ -9116,7 +9105,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, tree pack, packs = NULL_TREE, unsubstituted_packs = NULL_TREE; int i, len = -1; tree result; - int incomplete = 0; htab_t saved_local_specializations = NULL; gcc_assert (PACK_EXPANSION_P (t)); @@ -9189,21 +9177,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, int my_len = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)); - /* It's all-or-nothing with incomplete argument packs. */ - if (incomplete && !ARGUMENT_PACK_INCOMPLETE_P (arg_pack)) - return error_mark_node; - + /* Don't bother trying to do a partial substitution with + incomplete packs; we'll try again after deduction. */ if (ARGUMENT_PACK_INCOMPLETE_P (arg_pack)) - incomplete = 1; + return t; if (len < 0) len = my_len; else if (len != my_len) { - if (incomplete) - /* We got explicit args for some packs but not others; - do nothing now and try again after deduction. */ - return t; if (TREE_CODE (t) == TYPE_PACK_EXPANSION) error ("mismatched argument pack lengths while expanding " "%<%T%>", @@ -9261,8 +9243,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, /* For each argument in each argument pack, substitute into the pattern. */ - result = make_tree_vec (len + incomplete); - for (i = 0; i < len + incomplete; ++i) + 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 @@ -9307,13 +9289,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, else TREE_VEC_ELT (result, i) = tsubst (pattern, args, complain, in_decl); - if (i == len) - /* When we have incomplete argument packs, the last "expanded" - result is itself a pack expansion, which allows us - to deduce more arguments. */ - TREE_VEC_ELT (result, i) = - make_pack_expansion (TREE_VEC_ELT (result, i)); - if (TREE_VEC_ELT (result, i) == error_mark_node) { result = error_mark_node; @@ -14289,6 +14264,40 @@ pop_deduction_access_scope (tree tmpl) pop_deferring_access_checks (); } +/* PARM is a template parameter pack for FN. Returns true iff + PARM is used in a deducible way in the argument list of FN. */ + +static bool +pack_deducible_p (tree parm, tree fn) +{ + tree t = FUNCTION_FIRST_USER_PARMTYPE (fn); + for (; t; t = TREE_CHAIN (t)) + { + tree type = TREE_VALUE (t); + tree packs; + if (!PACK_EXPANSION_P (type)) + continue; + for (packs = PACK_EXPANSION_PARAMETER_PACKS (type); + packs; packs = TREE_CHAIN (packs)) + if (TREE_VALUE (packs) == parm) + { + /* The template parameter pack is used in a function parameter + pack. If this is the end of the parameter list, the + template parameter pack is deducible. */ + if (TREE_CHAIN (t) == void_list_node) + return true; + else + /* Otherwise, not. Well, it could be deduced from + a non-pack parameter, but doing so would end up with + a deduction mismatch, so don't bother. */ + return false; + } + } + /* The template parameter pack isn't used in any function parameter + packs, but it might be used deeper, e.g. tuple. */ + return true; +} + /* The FN is a TEMPLATE_DECL for a function. ARGS is an array with NARGS elements of the arguments that are being used when calling it. TARGS is a vector into which the deduced template arguments @@ -14334,7 +14343,6 @@ fn_type_unification (tree fn, tree parms; tree fntype; int result; - bool incomplete_argument_packs_p = false; gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL); @@ -14386,6 +14394,7 @@ fn_type_unification (tree fn, { tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i)); bool parameter_pack = false; + tree targ = TREE_VEC_ELT (converted_args, i); /* Dig out the actual parm. */ if (TREE_CODE (parm) == TYPE_DECL @@ -14400,16 +14409,15 @@ fn_type_unification (tree fn, parameter_pack = TEMPLATE_PARM_PARAMETER_PACK (parm); } - if (parameter_pack) - { - int level, idx; - tree targ; - template_parm_level_and_index (parm, &level, &idx); + if (!parameter_pack && targ == NULL_TREE) + /* No explicit argument for this template parameter. */ + incomplete = true; + if (parameter_pack && pack_deducible_p (parm, fn)) + { /* Mark the argument pack as "incomplete". We could still deduce more arguments during unification. We remove this mark in type_unification_real. */ - targ = TMPL_ARG (converted_args, level, idx); if (targ) { ARGUMENT_PACK_INCOMPLETE_P(targ) = 1; @@ -14418,18 +14426,10 @@ fn_type_unification (tree fn, } /* We have some incomplete argument packs. */ - incomplete_argument_packs_p = true; + incomplete = true; } } - if (incomplete_argument_packs_p) - /* Any substitution is guaranteed to be incomplete if there - are incomplete argument packs, because we can still deduce - more arguments. */ - incomplete = 1; - else - incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs); - processing_template_decl += incomplete; fntype = deduction_tsubst_fntype (fn, converted_args, (explain_p @@ -14643,6 +14643,134 @@ maybe_adjust_types_for_deduction (unification_kind_t strict, return result; } +/* Subroutine of unify_one_argument. PARM is a function parameter of a + template which does contain any deducible template parameters; check if + ARG is a suitable match for it. STRICT, FLAGS and EXPLAIN_P are as in + unify_one_argument. */ + +static int +check_non_deducible_conversion (tree parm, tree arg, int strict, + int flags, bool explain_p) +{ + tree type; + + if (!TYPE_P (arg)) + type = TREE_TYPE (arg); + else + type = arg; + + if (same_type_p (parm, type)) + return unify_success (explain_p); + + if (strict == DEDUCE_CONV) + { + if (can_convert_arg (type, parm, NULL_TREE, flags)) + return unify_success (explain_p); + } + else if (strict != DEDUCE_EXACT) + { + if (can_convert_arg (parm, type, + TYPE_P (arg) ? NULL_TREE : arg, + flags)) + return unify_success (explain_p); + } + + if (strict == DEDUCE_EXACT) + return unify_type_mismatch (explain_p, parm, arg); + else + return unify_arg_conversion (explain_p, parm, type, arg); +} + +/* Subroutine of type_unification_real and unify_pack_expansion to + handle unification of a single P/A pair. Parameters are as + for those functions. */ + +static int +unify_one_argument (tree tparms, tree targs, tree parm, tree arg, + int subr, unification_kind_t strict, int flags, + bool explain_p) +{ + tree arg_expr = NULL_TREE; + int arg_strict; + + if (arg == error_mark_node || parm == error_mark_node) + return unify_invalid (explain_p); + if (arg == unknown_type_node) + /* We can't deduce anything from this, but we might get all the + template args from other function args. */ + return unify_success (explain_p); + + /* FIXME uses_deducible_template_parms */ + if (TYPE_P (parm) && !uses_template_parms (parm)) + return check_non_deducible_conversion (parm, arg, strict, flags, + explain_p); + + switch (strict) + { + case DEDUCE_CALL: + arg_strict = (UNIFY_ALLOW_OUTER_LEVEL + | UNIFY_ALLOW_MORE_CV_QUAL + | UNIFY_ALLOW_DERIVED); + break; + + case DEDUCE_CONV: + arg_strict = UNIFY_ALLOW_LESS_CV_QUAL; + break; + + case DEDUCE_EXACT: + arg_strict = UNIFY_ALLOW_NONE; + break; + + default: + gcc_unreachable (); + } + + /* We only do these transformations if this is the top-level + parameter_type_list in a call or declaration matching; in other + situations (nested function declarators, template argument lists) we + won't be comparing a type to an expression, and we don't do any type + adjustments. */ + if (!subr) + { + if (!TYPE_P (arg)) + { + gcc_assert (TREE_TYPE (arg) != NULL_TREE); + if (type_unknown_p (arg)) + { + /* [temp.deduct.type] A template-argument can be + deduced from a pointer to function or pointer + to member function argument if the set of + overloaded functions does not contain function + templates and at most one of a set of + overloaded functions provides a unique + match. */ + + if (resolve_overloaded_unification + (tparms, targs, parm, arg, strict, + arg_strict, explain_p)) + return unify_success (explain_p); + return unify_overload_resolution_failure (explain_p, arg); + } + + arg_expr = arg; + arg = unlowered_expr_type (arg); + if (arg == error_mark_node) + return unify_invalid (explain_p); + } + + arg_strict |= + maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr); + } + else + gcc_assert ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL) + == (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)); + + /* For deduction from an init-list we need the actual list. */ + if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr)) + arg = arg_expr; + return unify (tparms, targs, parm, arg, arg_strict, explain_p); +} + /* Most parms like fn_type_unification. If SUBR is 1, we're being called recursively (to unify the @@ -14660,10 +14788,9 @@ type_unification_real (tree tparms, int flags, bool explain_p) { - tree parm, arg, arg_expr; + tree parm, arg; int i; int ntparms = TREE_VEC_LENGTH (tparms); - int sub_strict; int saw_undeduced = 0; tree parms; const tree *args; @@ -14678,25 +14805,6 @@ type_unification_real (tree tparms, in TARGS. */ NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE; - switch (strict) - { - case DEDUCE_CALL: - sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL - | UNIFY_ALLOW_DERIVED); - break; - - case DEDUCE_CONV: - sub_strict = UNIFY_ALLOW_LESS_CV_QUAL; - break; - - case DEDUCE_EXACT: - sub_strict = UNIFY_ALLOW_NONE; - break; - - default: - gcc_unreachable (); - } - again: parms = xparms; args = xargs; @@ -14726,90 +14834,12 @@ type_unification_real (tree tparms, arg = args[ia]; ++ia; - arg_expr = NULL; - if (arg == error_mark_node) - return unify_invalid (explain_p); - if (arg == unknown_type_node) - /* We can't deduce anything from this, but we might get all the - template args from other function args. */ - continue; - - /* Conversions will be performed on a function argument that - corresponds with a function parameter that contains only - non-deducible template parameters and explicitly specified - template parameters. */ - if (!uses_template_parms (parm)) - { - tree type; - - if (!TYPE_P (arg)) - type = TREE_TYPE (arg); - else - type = arg; - - if (same_type_p (parm, type)) - continue; - if (strict == DEDUCE_CONV) - { - if (can_convert_arg (type, parm, NULL_TREE, flags)) - continue; - } - else if (strict != DEDUCE_EXACT) - { - if (can_convert_arg (parm, type, - TYPE_P (arg) ? NULL_TREE : arg, - flags)) - continue; - } - - if (strict == DEDUCE_EXACT) - return unify_type_mismatch (explain_p, parm, arg); - else - return unify_arg_conversion (explain_p, parm, type, arg); - } - - if (!TYPE_P (arg)) - { - gcc_assert (TREE_TYPE (arg) != NULL_TREE); - if (type_unknown_p (arg)) - { - /* [temp.deduct.type] - - A template-argument can be deduced from a pointer to - function or pointer to member function argument if - the set of overloaded functions does not contain - function templates and at most one of a set of - overloaded functions provides a unique match. */ - if (resolve_overloaded_unification - (tparms, targs, parm, arg, strict, sub_strict, explain_p)) - continue; - - return unify_overload_resolution_failure (explain_p, arg); - } - arg_expr = arg; - arg = unlowered_expr_type (arg); - if (arg == error_mark_node) - return unify_invalid (explain_p); - } - - { - int arg_strict = sub_strict; - - if (!subr) - arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, - arg_expr); - - if (arg == init_list_type_node && arg_expr) - arg = arg_expr; - if (unify (tparms, targs, parm, arg, arg_strict, explain_p)) - /* If unification failed, the recursive call will have updated - UI appropriately. */ - return 1; - } + if (unify_one_argument (tparms, targs, parm, arg, subr, strict, + flags, explain_p)) + return 1; } - if (parms && parms != void_list_node && TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION) @@ -14826,7 +14856,7 @@ type_unification_real (tree tparms, /* Copy the parameter into parmvec. */ TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms); if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict, - /*call_args_p=*/true, /*subr=*/subr, explain_p)) + /*subr=*/subr, explain_p)) return 1; /* Advance to the end of the list of parameters. */ @@ -15461,10 +15491,12 @@ template_parm_level_and_index (tree parm, int* level, int* index) unify. CALL_ARGS_P is true iff PACKED_ARGS is actually a function call argument list. We'll need to adjust the arguments to make them types. SUBR tells us if this is from a recursive call to - type_unification_real. */ + type_unification_real, or for comparing two template argument + lists. */ + static int unify_pack_expansion (tree tparms, tree targs, tree packed_parms, - tree packed_args, int strict, bool call_args_p, + tree packed_args, unification_kind_t strict, bool subr, bool explain_p) { tree parm @@ -15495,92 +15527,56 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms, unified and unify each with the pattern. */ for (i = start; i < len; i++) { - tree parm = pattern; + tree parm; + bool any_explicit = false; + tree arg = TREE_VEC_ELT (packed_args, i); - /* For each parameter pack, clear out the deduced value so that - we can deduce it again. */ + /* For each parameter pack, set its TMPL_ARG to either NULL_TREE + or the element of its argument pack at the current index if + this argument was explicitly specified. */ for (pack = packs; pack; pack = TREE_CHAIN (pack)) { int idx, level; + tree arg, pargs; template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx); - TMPL_ARG (targs, level, idx) = NULL_TREE; + arg = NULL_TREE; + if (TREE_VALUE (pack) + && (pargs = ARGUMENT_PACK_EXPLICIT_ARGS (TREE_VALUE (pack))) + && (i < TREE_VEC_LENGTH (pargs))) + { + any_explicit = true; + arg = TREE_VEC_ELT (pargs, i); + } + TMPL_ARG (targs, level, idx) = arg; } + /* If we had explicit template arguments, substitute them into the + pattern before deduction. */ + if (any_explicit) + { + /* Some arguments might still be unspecified or dependent. */ + bool dependent; + ++processing_template_decl; + dependent = any_dependent_template_arguments_p (targs); + if (!dependent) + --processing_template_decl; + parm = tsubst (pattern, targs, + explain_p ? tf_warning_or_error : tf_none, + NULL_TREE); + if (dependent) + --processing_template_decl; + if (parm == error_mark_node) + return 1; + } + else + parm = pattern; + /* Unify the pattern with the current argument. */ - { - tree arg = TREE_VEC_ELT (packed_args, i); - tree arg_expr = NULL_TREE; - int arg_strict = strict; + if (unify_one_argument (tparms, targs, parm, arg, subr, strict, + LOOKUP_IMPLICIT, explain_p)) + return 1; - if (call_args_p) - { - int sub_strict; - - /* This mirrors what we do in type_unification_real. */ - switch (strict) - { - case DEDUCE_CALL: - sub_strict = (UNIFY_ALLOW_OUTER_LEVEL - | UNIFY_ALLOW_MORE_CV_QUAL - | UNIFY_ALLOW_DERIVED); - break; - - case DEDUCE_CONV: - sub_strict = UNIFY_ALLOW_LESS_CV_QUAL; - break; - - case DEDUCE_EXACT: - sub_strict = UNIFY_ALLOW_NONE; - break; - - default: - gcc_unreachable (); - } - - if (!TYPE_P (arg)) - { - gcc_assert (TREE_TYPE (arg) != NULL_TREE); - if (type_unknown_p (arg)) - { - /* [temp.deduct.type] A template-argument can be - deduced from a pointer to function or pointer - to member function argument if the set of - overloaded functions does not contain function - templates and at most one of a set of - overloaded functions provides a unique - match. */ - - if (resolve_overloaded_unification - (tparms, targs, parm, arg, - (unification_kind_t) strict, - sub_strict, explain_p)) - goto unified; - return unify_overload_resolution_failure (explain_p, arg); - } - - arg_expr = arg; - arg = unlowered_expr_type (arg); - if (arg == error_mark_node) - return unify_invalid (explain_p); - } - - arg_strict = sub_strict; - - if (!subr) - arg_strict |= - maybe_adjust_types_for_deduction ((unification_kind_t) strict, - &parm, &arg, arg_expr); - } - - /* For deduction from an init-list we need the actual list. */ - if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr)) - arg = arg_expr; - RECUR_AND_CHECK_FAILURE (tparms, targs, parm, arg, arg_strict, - explain_p); - } - - unified: /* For each parameter pack, collect the deduced value. */ for (pack = packs; pack; pack = TREE_CHAIN (pack)) { @@ -15619,21 +15615,12 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms, if (old_pack && ARGUMENT_PACK_INCOMPLETE_P (old_pack)) { - /* Prepend the explicit arguments onto NEW_ARGS. */ + /* If we had fewer function args than explicit template args, + just use the explicits. */ tree explicit_args = ARGUMENT_PACK_EXPLICIT_ARGS (old_pack); - tree old_args = new_args; - int i, explicit_len = TREE_VEC_LENGTH (explicit_args); - int len = explicit_len + TREE_VEC_LENGTH (old_args); - - /* Copy the explicit arguments. */ - new_args = make_tree_vec (len); - for (i = 0; i < explicit_len; i++) - TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (explicit_args, i); - - /* Copy the deduced arguments. */ - for (; i < len; i++) - TREE_VEC_ELT (new_args, i) = - TREE_VEC_ELT (old_args, i - explicit_len); + int explicit_len = TREE_VEC_LENGTH (explicit_args); + if (len < explicit_len) + new_args = explicit_args; } if (!old_pack) @@ -15961,9 +15948,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, if (parm_variadic_p && unify_pack_expansion (tparms, targs, parmvec, argvec, - UNIFY_ALLOW_NONE, - /*call_args_p=*/false, - /*subr=*/false, explain_p)) + DEDUCE_EXACT, + /*subr=*/true, explain_p)) return 1; } arg = TYPE_TI_TEMPLATE (arg); @@ -16253,17 +16239,55 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, case TREE_VEC: { - int i; + int i, len, argslen; + int parm_variadic_p = 0; + if (TREE_CODE (arg) != TREE_VEC) return unify_template_argument_mismatch (explain_p, parm, arg); - if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg)) - return unify_arity (explain_p, TREE_VEC_LENGTH (arg), - TREE_VEC_LENGTH (parm)); - for (i = 0; i < TREE_VEC_LENGTH (parm); ++i) - RECUR_AND_CHECK_FAILURE (tparms, targs, - TREE_VEC_ELT (parm, i), - TREE_VEC_ELT (arg, i), - UNIFY_ALLOW_NONE, explain_p); + + len = TREE_VEC_LENGTH (parm); + argslen = TREE_VEC_LENGTH (arg); + + /* Check for pack expansions in the parameters. */ + for (i = 0; i < len; ++i) + { + if (PACK_EXPANSION_P (TREE_VEC_ELT (parm, i))) + { + if (i == len - 1) + /* We can unify against something with a trailing + parameter pack. */ + parm_variadic_p = 1; + else + /* [temp.deduct.type]/9: If the template argument list of + P contains a pack expansion that is not the last + template argument, the entire template argument list + is a non-deduced context. */ + return unify_success (explain_p); + } + } + + /* If we don't have enough arguments to satisfy the parameters + (not counting the pack expression at the end), or we have + too many arguments for a parameter list that doesn't end in + a pack expression, we can't unify. */ + if (parm_variadic_p + ? argslen < len - parm_variadic_p + : argslen != len) + return unify_arity (explain_p, TREE_VEC_LENGTH (arg), len); + + /* Unify all of the parameters that precede the (optional) + pack expression. */ + for (i = 0; i < len - parm_variadic_p; ++i) + { + RECUR_AND_CHECK_FAILURE (tparms, targs, + TREE_VEC_ELT (parm, i), + TREE_VEC_ELT (arg, i), + UNIFY_ALLOW_NONE, explain_p); + } + if (parm_variadic_p) + return unify_pack_expansion (tparms, targs, parm, arg, + DEDUCE_EXACT, + /*subr=*/true, explain_p); return unify_success (explain_p); } @@ -16425,58 +16449,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, case TYPE_ARGUMENT_PACK: case NONTYPE_ARGUMENT_PACK: - { - tree packed_parms = ARGUMENT_PACK_ARGS (parm); - tree packed_args = ARGUMENT_PACK_ARGS (arg); - int i, len = TREE_VEC_LENGTH (packed_parms); - int argslen = TREE_VEC_LENGTH (packed_args); - int parm_variadic_p = 0; - - for (i = 0; i < len; ++i) - { - if (PACK_EXPANSION_P (TREE_VEC_ELT (packed_parms, i))) - { - if (i == len - 1) - /* We can unify against something with a trailing - parameter pack. */ - parm_variadic_p = 1; - else - /* Since there is something following the pack - expansion, we cannot unify this template argument - list. */ - return unify_success (explain_p); - } - } - - - /* If we don't have enough arguments to satisfy the parameters - (not counting the pack expression at the end), or we have - too many arguments for a parameter list that doesn't end in - a pack expression, we can't unify. */ - if (argslen < (len - parm_variadic_p)) - return unify_too_few_arguments (explain_p, argslen, len); - if (argslen > len && !parm_variadic_p) - return unify_too_many_arguments (explain_p, argslen, len); - - /* Unify all of the parameters that precede the (optional) - pack expression. */ - for (i = 0; i < len - parm_variadic_p; ++i) - { - RECUR_AND_CHECK_FAILURE (tparms, targs, - TREE_VEC_ELT (packed_parms, i), - TREE_VEC_ELT (packed_args, i), - strict, explain_p); - } - - if (parm_variadic_p) - return unify_pack_expansion (tparms, targs, - packed_parms, packed_args, - strict, /*call_args_p=*/false, - /*subr=*/false, explain_p); - return unify_success (explain_p); - } - - break; + return unify (tparms, targs, ARGUMENT_PACK_ARGS (parm), + ARGUMENT_PACK_ARGS (arg), strict, explain_p); case TYPEOF_TYPE: case DECLTYPE_TYPE: @@ -16785,9 +16759,8 @@ more_specialized_fn (tree pat1, tree pat2, int len) TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta); deduce1 = (unify_pack_expansion (tparms1, targs1, parmvec, - argvec, UNIFY_ALLOW_NONE, - /*call_args_p=*/false, - /*subr=*/0, /*explain_p=*/false) + argvec, DEDUCE_EXACT, + /*subr=*/true, /*explain_p=*/false) == 0); /* We cannot deduce in the other direction, because ARG1 is @@ -16810,9 +16783,8 @@ more_specialized_fn (tree pat1, tree pat2, int len) TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta); deduce2 = (unify_pack_expansion (tparms2, targs2, parmvec, - argvec, UNIFY_ALLOW_NONE, - /*call_args_p=*/false, - /*subr=*/0, /*explain_p=*/false) + argvec, DEDUCE_EXACT, + /*subr=*/true, /*explain_p=*/false) == 0); /* We cannot deduce in the other direction, because ARG2 is diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c4cadf732bf..275b9b34040 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2011-10-02 Jason Merrill + * g++.dg/cpp0x/variadic65.C: Remove xfails. + * g++.dg/cpp0x/variadic82.C: Remove xfails. + * g++.dg/cpp0x/variadic83.C: Remove xfails. + * g++.dg/cpp0x/variadic105.C: Remove xfails. + * g++.dg/cpp0x/nsdmi5.C: New. 2011-10-02 Richard Sandiford diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C new file mode 100644 index 00000000000..a097f43d218 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C @@ -0,0 +1,11 @@ +// { dg-options -std=c++0x } + +template struct A { }; +template void f( A... p); + +void g() { + f( + A(), + A() + ); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C new file mode 100644 index 00000000000..a64d7971c6e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C @@ -0,0 +1,12 @@ +// { dg-options -std=c++0x } + +template +void f(T..., int, T...) { } + +int main() +{ + f(0); + f(0,0,0); + f(0,0,0,0,0); + f(0,0,0); // { dg-error "" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C index 66387b23c47..66d24a7efe3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C @@ -20,6 +20,6 @@ struct call_sum { int main() { // This shouldn't be an error; this is bug 35722. - reverse(1,2); // { dg-bogus "no match" "" { xfail *-*-* } } - // { dg-bogus "sorry, unimplemented" "candidate explanation" { xfail *-*-* } 6 } + reverse(1,2); // { dg-bogus "no match" "" } + // { dg-bogus "sorry, unimplemented" "candidate explanation" { target *-*-* } 6 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic117.C b/gcc/testsuite/g++.dg/cpp0x/variadic117.C new file mode 100644 index 00000000000..22f2fc5ae2d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic117.C @@ -0,0 +1,11 @@ +// { dg-options -std=c++0x } + +template struct A { typedef T type; }; + +template