From 31bfc9b9dd65ecddff3afa690906d94ef7b773da Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 21 Dec 2016 14:39:04 -0500 Subject: [PATCH] Implement P0522R0, matching of template template arguments. gcc/c-family/ * c.opt (-fnew-ttp-matching): New flag. * c-opts.c (c_common_post_options): Default on if -std=c++1z. gcc/cp/ * pt.c (coerce_template_template_parms): Allow a template argument that's less specialized than the parameter. (unify_bound_ttp_args): Adjust parm's args to apply to arg's template. (coerce_template_args_for_ttp): Split out from lookup_template_class_1. (coerce_ttp_args_for_tta, store_defaulted_ttp) (lookup_defaulted_ttp, add_defaults_to_ttp): New. (process_partial_specialization): Set DECL_CONTEXT of template template-parameters. (coerce_template_parms): Only inform when complain. (expand_template_argument_pack): Handle error_mark_node. (convert_template_argument, template_args_equal, unify): Handle any_targ_node. * cp-tree.h (enum cp_tree_index): Add CPTI_ANY_TARG. (any_targ_node): New. * decl.c (cxx_init_decl_processing): Set it. * name-lookup.c (consider_binding_level): Ignore names with embedded spaces. From-SVN: r243871 --- gcc/c-family/ChangeLog | 5 + gcc/c-family/c-opts.c | 4 + gcc/c-family/c.opt | 4 + gcc/cp/ChangeLog | 21 ++ gcc/cp/cp-tree.h | 5 + gcc/cp/decl.c | 3 + gcc/cp/name-lookup.c | 6 +- gcc/cp/pt.c | 292 ++++++++++++++++---- gcc/doc/invoke.texi | 9 + gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C | 2 +- gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C | 24 ++ gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C | 17 ++ gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C | 10 + gcc/testsuite/g++.dg/cpp0x/variadic79.C | 1 + gcc/testsuite/g++.dg/cpp0x/variadic79a.C | 7 + gcc/testsuite/g++.dg/cpp0x/variadic85.C | 1 + gcc/testsuite/g++.dg/cpp0x/variadic85a.C | 10 + gcc/testsuite/g++.dg/cpp1z/ttp1.C | 19 ++ gcc/testsuite/g++.dg/template/ttp16.C | 2 + gcc/testsuite/g++.dg/template/ttp16a.C | 9 + gcc/testsuite/g++.dg/template/ttp17.C | 2 + gcc/testsuite/g++.dg/template/ttp17a.C | 9 + gcc/testsuite/g++.dg/torture/pr68220.C | 1 + gcc/testsuite/g++.old-deja/g++.pt/ttp49.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C | 9 + libstdc++-v3/ChangeLog | 2 +- 26 files changed, 417 insertions(+), 59 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic79a.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic85a.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/ttp1.C create mode 100644 gcc/testsuite/g++.dg/template/ttp16a.C create mode 100644 gcc/testsuite/g++.dg/template/ttp17a.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d8bd2c383f9..13ba2f314a9 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2016-12-21 Jason Merrill + + * c.opt (-fnew-ttp-matching): New flag. + * c-opts.c (c_common_post_options): Default on if -std=c++1z. + 2016-12-14 Martin Jambor * c-omp.c: Include omp-general.h instead of omp-low.h. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 57717ff41d8..62d2f46f926 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -920,6 +920,10 @@ c_common_post_options (const char **pfilename) if (!global_options_set.x_flag_new_inheriting_ctors) flag_new_inheriting_ctors = abi_version_at_least (11); + /* For GCC 7, only enable DR150 resolution by default if -std=c++1z. */ + if (!global_options_set.x_flag_new_ttp) + flag_new_ttp = (cxx_dialect >= cxx1z); + if (cxx_dialect >= cxx11) { /* If we're allowing C++0x constructs, don't warn about C++98 diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 33c5def7592..a5333a35e41 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1443,6 +1443,10 @@ C++ ObjC++ Joined Ignore Warn(switch %qs is no longer supported) fnew-abi C++ ObjC++ Ignore Warn(switch %qs is no longer supported) +fnew-ttp-matching +C++ ObjC++ Var(flag_new_ttp) +Implement resolution of DR 150 for matching of template template arguments. + fnext-runtime ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime) Generate code for NeXT (Apple Mac OS X) runtime environment. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ffda8e16100..db3582af2bc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,26 @@ 2016-12-21 Jason Merrill + Implement P0522R0, matching of template template arguments. + * pt.c (coerce_template_template_parms): Allow a template argument + that's less specialized than the parameter. + (unify_bound_ttp_args): Adjust parm's args to apply to arg's + template. + (coerce_template_args_for_ttp): Split out from + lookup_template_class_1. + (coerce_ttp_args_for_tta, store_defaulted_ttp) + (lookup_defaulted_ttp, add_defaults_to_ttp): New. + (process_partial_specialization): Set DECL_CONTEXT of + template template-parameters. + (coerce_template_parms): Only inform when complain. + (expand_template_argument_pack): Handle error_mark_node. + (convert_template_argument, template_args_equal, unify): Handle + any_targ_node. + * cp-tree.h (enum cp_tree_index): Add CPTI_ANY_TARG. + (any_targ_node): New. + * decl.c (cxx_init_decl_processing): Set it. + * name-lookup.c (consider_binding_level): Ignore names with embedded + spaces. + PR c++/42329 * pt.c (unify_bound_ttp_args): Split out from unify. (try_class_unification): Handle BOUND_TEMPLATE_TEMPLATE_PARM. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 89bb9b28f01..ef6265e9b4e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1140,6 +1140,8 @@ enum cp_tree_index CPTI_ALIGN_TYPE, + CPTI_ANY_TARG, + CPTI_MAX }; @@ -1245,6 +1247,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES] +/* A node which matches any template argument. */ +#define any_targ_node cp_global_trees[CPTI_ANY_TARG] + /* Node to indicate default access. This must be distinct from the access nodes in tree.h. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 295416051b7..e70b34c9a17 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4161,6 +4161,9 @@ cxx_init_decl_processing (void) global_type_node = make_node (LANG_TYPE); record_unknown_type (global_type_node, "global type"); + any_targ_node = make_node (LANG_TYPE); + record_unknown_type (any_targ_node, "any type"); + /* Now, C++. */ current_lang_name = lang_name_cplusplus; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index d80c0318330..a0cadb8d6e7 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4758,8 +4758,10 @@ consider_binding_level (tree name, best_match &bm, && DECL_ANTICIPATED (d)) continue; - if (DECL_NAME (d)) - bm.consider (DECL_NAME (d)); + if (tree name = DECL_NAME (d)) + /* Ignore internal names with spaces in them. */ + if (!strchr (IDENTIFIER_POINTER (name), ' ')) + bm.consider (DECL_NAME (d)); } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6abb639e081..301eb5271ba 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3836,6 +3836,9 @@ check_for_bare_parameter_packs (tree t) tree expand_template_argument_pack (tree args) { + if (args == error_mark_node) + return error_mark_node; + tree result_args = NULL_TREE; int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0; int num_result_args = -1; @@ -4758,6 +4761,15 @@ process_partial_specialization (tree decl) DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs); DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl; + /* Give template template parms a DECL_CONTEXT of the template + for which they are a parameter. */ + for (i = 0; i < ntparms; ++i) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (inner_parms, i)); + if (TREE_CODE (parm) == TEMPLATE_DECL) + DECL_CONTEXT (parm) = tmpl; + } + if (VAR_P (decl)) /* We didn't register this in check_explicit_specialization so we could wait until the constraints were set. */ @@ -6863,11 +6875,164 @@ coerce_template_template_parm (tree parm, return 1; } +/* Coerce template argument list ARGLIST for use with template + template-parameter TEMPL. */ + +static tree +coerce_template_args_for_ttp (tree templ, tree arglist, + tsubst_flags_t complain) +{ + /* Consider an example where a template template parameter declared as + + template > class TT + + The template parameter level of T and U are one level larger than + of TT. To proper process the default argument of U, say when an + instantiation `TT' is seen, we need to build the full + arguments containing {int} as the innermost level. Outer levels, + available when not appearing as default template argument, can be + obtained from the arguments of the enclosing template. + + Suppose that TT is later substituted with std::vector. The above + instantiation is `TT >' with TT at + level 1, and T at level 2, while the template arguments at level 1 + becomes {std::vector} and the inner level 2 is {int}. */ + + tree outer = DECL_CONTEXT (templ); + if (outer) + { + if (DECL_TEMPLATE_SPECIALIZATION (outer)) + /* We want arguments for the partial specialization, not arguments for + the primary template. */ + outer = template_parms_to_args (DECL_TEMPLATE_PARMS (outer)); + else + outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer))); + } + else if (current_template_parms) + { + /* This is an argument of the current template, so we haven't set + DECL_CONTEXT yet. */ + tree relevant_template_parms; + + /* Parameter levels that are greater than the level of the given + template template parm are irrelevant. */ + relevant_template_parms = current_template_parms; + while (TMPL_PARMS_DEPTH (relevant_template_parms) + != TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ))) + relevant_template_parms = TREE_CHAIN (relevant_template_parms); + + outer = template_parms_to_args (relevant_template_parms); + } + + if (outer) + arglist = add_to_template_args (outer, arglist); + + tree parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ); + return coerce_template_parms (parmlist, arglist, templ, + complain, + /*require_all_args=*/true, + /*use_default_args=*/true); +} + +/* A cache of template template parameters with match-all default + arguments. */ +static GTY((deletable)) hash_map *defaulted_ttp_cache; +static void +store_defaulted_ttp (tree v, tree t) +{ + if (!defaulted_ttp_cache) + defaulted_ttp_cache = hash_map::create_ggc (13); + defaulted_ttp_cache->put (v, t); +} +static tree +lookup_defaulted_ttp (tree v) +{ + if (defaulted_ttp_cache) + if (tree *p = defaulted_ttp_cache->get (v)) + return *p; + return NULL_TREE; +} + +/* T is a bound template template-parameter. Copy its arguments into default + arguments of the template template-parameter's template parameters. */ + +static tree +add_defaults_to_ttp (tree otmpl) +{ + if (tree c = lookup_defaulted_ttp (otmpl)) + return c; + + tree ntmpl = copy_node (otmpl); + + tree ntype = copy_node (TREE_TYPE (otmpl)); + TYPE_STUB_DECL (ntype) = TYPE_NAME (ntype) = ntmpl; + TYPE_MAIN_VARIANT (ntype) = ntype; + TYPE_POINTER_TO (ntype) = TYPE_REFERENCE_TO (ntype) = NULL_TREE; + TYPE_NAME (ntype) = ntmpl; + SET_TYPE_STRUCTURAL_EQUALITY (ntype); + + tree idx = TEMPLATE_TYPE_PARM_INDEX (ntype) + = copy_node (TEMPLATE_TYPE_PARM_INDEX (ntype)); + TEMPLATE_PARM_DECL (idx) = ntmpl; + TREE_TYPE (ntmpl) = TREE_TYPE (idx) = ntype; + + tree oparms = DECL_TEMPLATE_PARMS (otmpl); + tree parms = DECL_TEMPLATE_PARMS (ntmpl) = copy_node (oparms); + TREE_CHAIN (parms) = TREE_CHAIN (oparms); + tree vec = TREE_VALUE (parms) = copy_node (TREE_VALUE (parms)); + for (int i = 0; i < TREE_VEC_LENGTH (vec); ++i) + { + tree o = TREE_VEC_ELT (vec, i); + if (!template_parameter_pack_p (TREE_VALUE (o))) + { + tree n = TREE_VEC_ELT (vec, i) = copy_node (o); + TREE_PURPOSE (n) = any_targ_node; + } + } + + store_defaulted_ttp (otmpl, ntmpl); + return ntmpl; +} + +/* ARG is a bound potential template template-argument, and PARGS is a list + of arguments for the corresponding template template-parameter. Adjust + PARGS as appropriate for application to ARG's template, and if ARG is a + BOUND_TEMPLATE_TEMPLATE_PARM, possibly adjust it to add default template + arguments to the template template parameter. */ + +static tree +coerce_ttp_args_for_tta (tree& arg, tree pargs, tsubst_flags_t complain) +{ + ++processing_template_decl; + tree arg_tmpl = TYPE_TI_TEMPLATE (arg); + if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl)) + { + /* When comparing two template template-parameters in partial ordering, + rewrite the one currently being used as an argument to have default + arguments for all parameters. */ + arg_tmpl = add_defaults_to_ttp (arg_tmpl); + pargs = coerce_template_args_for_ttp (arg_tmpl, pargs, complain); + if (pargs != error_mark_node) + arg = bind_template_template_parm (TREE_TYPE (arg_tmpl), + TYPE_TI_ARGS (arg)); + } + else + { + tree aparms + = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (arg_tmpl)); + pargs = coerce_template_parms (aparms, pargs, arg_tmpl, complain, + /*require_all*/true, + /*use_default*/true); + } + --processing_template_decl; + return pargs; +} + /* Subroutine of unify for the case when PARM is a BOUND_TEMPLATE_TEMPLATE_PARM. */ static int -unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree arg, +unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree& arg, bool explain_p) { tree parmvec = TYPE_TI_ARGS (parm); @@ -6878,10 +7043,27 @@ unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree arg, parmvec = expand_template_argument_pack (parmvec); argvec = expand_template_argument_pack (argvec); - if (unify (tparms, targs, parmvec, argvec, + tree nparmvec = parmvec; + if (flag_new_ttp) + { + /* In keeping with P0522R0, adjust P's template arguments + to apply to A's template; then flatten it again. */ + nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none); + nparmvec = expand_template_argument_pack (nparmvec); + } + + if (unify (tparms, targs, nparmvec, argvec, UNIFY_ALLOW_NONE, explain_p)) return 1; + /* If the P0522 adjustment eliminated a pack expansion, deduce + empty packs. */ + if (flag_new_ttp + && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec) + && unify_pack_expansion (tparms, targs, parmvec, argvec, + DEDUCE_EXACT, /*sub*/true, explain_p)) + return 1; + return 0; } @@ -6914,6 +7096,48 @@ coerce_template_template_parms (tree parm_parms, nparms = TREE_VEC_LENGTH (parm_parms); nargs = TREE_VEC_LENGTH (arg_parms); + if (flag_new_ttp) + { + /* P0522R0: A template template-parameter P is at least as specialized as + a template template-argument A if, given the following rewrite to two + function templates, the function template corresponding to P is at + least as specialized as the function template corresponding to A + according to the partial ordering rules for function templates + ([temp.func.order]). Given an invented class template X with the + template parameter list of A (including default arguments): + + * Each of the two function templates has the same template parameters, + respectively, as P or A. + + * Each function template has a single function parameter whose type is + a specialization of X with template arguments corresponding to the + template parameters from the respective function template where, for + each template parameter PP in the template parameter list of the + function template, a corresponding template argument AA is formed. If + PP declares a parameter pack, then AA is the pack expansion + PP... ([temp.variadic]); otherwise, AA is the id-expression PP. + + If the rewrite produces an invalid type, then P is not at least as + specialized as A. */ + + /* So coerce P's args to apply to A's parms, and then deduce between A's + args and the converted args. If that succeeds, A is at least as + specialized as P, so they match.*/ + tree pargs = template_parms_level_to_args (parm_parms); + ++processing_template_decl; + pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none, + /*require_all*/true, /*use_default*/true); + --processing_template_decl; + if (pargs != error_mark_node) + { + tree targs = make_tree_vec (nargs); + tree aargs = template_parms_level_to_args (arg_parms); + if (!unify (arg_parms, targs, aargs, pargs, UNIFY_ALLOW_NONE, + /*explain*/false)) + return 1; + } + } + /* Determine whether we have a parameter pack at the end of the template template parameter's template parameter list. */ if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node) @@ -7172,6 +7396,9 @@ convert_template_argument (tree parm, if (TREE_CODE (arg) == WILDCARD_DECL) return convert_wildcard_argument (parm, arg); + if (arg == any_targ_node) + return arg; + if (TREE_CODE (arg) == TREE_LIST && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF) { @@ -7822,8 +8049,9 @@ coerce_template_parms (tree parms, in_decl); if (conv == error_mark_node) { - inform (input_location, "so any instantiation with a " - "non-empty parameter pack would be ill-formed"); + if (complain & tf_error) + inform (input_location, "so any instantiation with a " + "non-empty parameter pack would be ill-formed"); ++lost; } else if (TYPE_P (conv) && !TYPE_P (pattern)) @@ -7987,6 +8215,8 @@ template_args_equal (tree ot, tree nt) return 1; if (nt == NULL_TREE || ot == NULL_TREE) return false; + if (nt == any_targ_node || ot == any_targ_node) + return true; if (TREE_CODE (nt) == TREE_VEC) /* For member templates */ @@ -8328,57 +8558,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ)) { - /* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store - template arguments */ - tree parm; - tree arglist2; - tree outer; - - parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ); - - /* Consider an example where a template template parameter declared as - - template > class TT - - The template parameter level of T and U are one level larger than - of TT. To proper process the default argument of U, say when an - instantiation `TT' is seen, we need to build the full - arguments containing {int} as the innermost level. Outer levels, - available when not appearing as default template argument, can be - obtained from the arguments of the enclosing template. - - Suppose that TT is later substituted with std::vector. The above - instantiation is `TT >' with TT at - level 1, and T at level 2, while the template arguments at level 1 - becomes {std::vector} and the inner level 2 is {int}. */ - - outer = DECL_CONTEXT (templ); - if (outer) - outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer))); - else if (current_template_parms) - { - /* This is an argument of the current template, so we haven't set - DECL_CONTEXT yet. */ - tree relevant_template_parms; - - /* Parameter levels that are greater than the level of the given - template template parm are irrelevant. */ - relevant_template_parms = current_template_parms; - while (TMPL_PARMS_DEPTH (relevant_template_parms) - != TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ))) - relevant_template_parms = TREE_CHAIN (relevant_template_parms); - - outer = template_parms_to_args (relevant_template_parms); - } - - if (outer) - arglist = add_to_template_args (outer, arglist); - - arglist2 = coerce_template_parms (parmlist, arglist, templ, - complain, - /*require_all_args=*/true, - /*use_default_args=*/true); + tree arglist2 = coerce_template_args_for_ttp (templ, arglist, complain); if (arglist2 == error_mark_node || (!uses_template_parms (arglist2) && check_instantiated_args (templ, arglist2, complain))) @@ -19950,6 +20131,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, template args from other function args. */ return unify_success (explain_p); + if (parm == any_targ_node || arg == any_targ_node) + return unify_success (explain_p); + /* If PARM uses template parameters, then we can't bail out here, even if ARG == PARM, since we won't record unifications for the template parameters. We might need them if we're trying to diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 5c92fe69335..1096254085f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -201,6 +201,7 @@ in the following sections. -fno-implicit-inline-templates @gol -fno-implement-inlines -fms-extensions @gol -fnew-inheriting-ctors @gol +-fnew-ttp-matching @gol -fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol -fno-optional-diags -fpermissive @gol -fno-pretty-templates @gol @@ -2455,6 +2456,14 @@ inheritance. This is part of C++17 but also considered to be a Defect Report against C++11 and C++14. This flag is enabled by default unless @option{-fabi-version=10} or lower is specified. +@item -fnew-ttp-matching +@opindex fnew-ttp-matching +Enable the P0522 resolution to Core issue 150, template template +parameters and default arguments: this allows a template with default +template arguments as an argument for a template template parameter +with fewer template parameters. This flag is enabled by default for +@option{-std=c++1z}. + @item -fno-nonansi-builtins @opindex fno-nonansi-builtins Disable built-in declarations of functions that are not mandated by diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C index e301e7ac38d..5ec05cd4264 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++11 } } - +// { dg-options -fno-new-ttp-matching } template class A { /* ... */ }; template class B { /* ... */ }; template class C { /* ... */ }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C new file mode 100644 index 00000000000..8887033e722 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C @@ -0,0 +1,24 @@ +// CWG 150: Matching of template template-arguments excludes compatible +// templates +// { dg-options -fnew-ttp-matching } + +template class A { /* ... */ }; +template class B { /* ... */ }; +template class P> class X { /* ... */ }; +X xa; // OK +X xb; // OK since P0522R0 + +#if __cpp_variadic_templates +template class C { /* ... */ }; +template class Q> class Y { /* ... */ }; +X xc; // OK since P0522R0 +Y ya; // OK +Y yb; // OK +Y yc; // OK +#endif + +#if __cpp_template_auto +template class D { /* ... */ }; +template class R> class Z { /* ... */ }; +Z zd; // OK +#endif diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C new file mode 100644 index 00000000000..72cff3874cb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } + +template +struct get_first_arg; + +template class _Template, typename _Tp, + typename... _Types> +struct get_first_arg<_Template<_Tp, _Types...>> +{ using type = _Tp; }; + +template struct A { }; + +template struct same; +template struct same {}; + +same>::type, + int> x; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C new file mode 100644 index 00000000000..43f951a0286 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } + +template struct A { }; +template struct B { }; + +template class C, T... Is> +struct A, C> +{ + using type = C; +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic79.C b/gcc/testsuite/g++.dg/cpp0x/variadic79.C index 389199cc41d..ed5e0284d23 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic79.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic79.C @@ -1,5 +1,6 @@ // PR c++/33213 // { dg-do compile { target c++11 } } +// { dg-options -fno-new-ttp-matching } template class...> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic79a.C b/gcc/testsuite/g++.dg/cpp0x/variadic79a.C new file mode 100644 index 00000000000..67376cc4f23 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic79a.C @@ -0,0 +1,7 @@ +// PR c++/33213 +// { dg-do compile { target c++11 } } +// { dg-options -fnew-ttp-matching } + +template class...> struct A; + +template class... B> struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85.C b/gcc/testsuite/g++.dg/cpp0x/variadic85.C index 708104af907..c1d6ab9092c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic85.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic85.C @@ -1,5 +1,6 @@ // PR c++/32565 // { dg-do compile { target c++11 } } +// { dg-options -fno-new-ttp-matching } template struct A1; template class T> struct A1 > {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85a.C b/gcc/testsuite/g++.dg/cpp0x/variadic85a.C new file mode 100644 index 00000000000..b3cfeee968a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic85a.C @@ -0,0 +1,10 @@ +// PR c++/32565 +// { dg-do compile { target c++11 } } +// { dg-options -fnew-ttp-matching } + +template struct A1; +template class T> struct A1 > {}; +template struct B1 {}; +A1 > a1; +template struct B2 {}; +A1 > a2; diff --git a/gcc/testsuite/g++.dg/cpp1z/ttp1.C b/gcc/testsuite/g++.dg/cpp1z/ttp1.C new file mode 100644 index 00000000000..7577b5e3280 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/ttp1.C @@ -0,0 +1,19 @@ +// CWG 150: Matching of template template-arguments excludes compatible +// templates + +// { dg-options -fnew-ttp-matching } + +template class B { /* ... */ }; +#if __cpp_variadic_templates +template class C { /* ... */ }; +#endif +template class P, class T> void f(P); + +int main() +{ + f(B()); + f(B()); // { dg-error "no match" } +#if __cpp_variadic_templates + f(C()); +#endif +} diff --git a/gcc/testsuite/g++.dg/template/ttp16.C b/gcc/testsuite/g++.dg/template/ttp16.C index c556c7d98a4..510ef652965 100644 --- a/gcc/testsuite/g++.dg/template/ttp16.C +++ b/gcc/testsuite/g++.dg/template/ttp16.C @@ -1,3 +1,5 @@ +// { dg-options -fno-new-ttp-matching } + template