aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-12-21 14:39:04 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-12-21 14:39:04 -0500
commit31bfc9b9dd65ecddff3afa690906d94ef7b773da (patch)
tree6a4c3f49466411d75b33e5d43dd222039ad777dd /gcc
parent3c75aaa3d884ef2cb1dfed57bb3c2a392ece89d5 (diff)
downloadgcc-31bfc9b9dd65ecddff3afa690906d94ef7b773da.zip
gcc-31bfc9b9dd65ecddff3afa690906d94ef7b773da.tar.gz
gcc-31bfc9b9dd65ecddff3afa690906d94ef7b773da.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-opts.c4
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/name-lookup.c6
-rw-r--r--gcc/cp/pt.c292
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic79.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic79a.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic85.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic85a.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/ttp1.C19
-rw-r--r--gcc/testsuite/g++.dg/template/ttp16.C2
-rw-r--r--gcc/testsuite/g++.dg/template/ttp16a.C9
-rw-r--r--gcc/testsuite/g++.dg/template/ttp17.C2
-rw-r--r--gcc/testsuite/g++.dg/template/ttp17a.C9
-rw-r--r--gcc/testsuite/g++.dg/torture/pr68220.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp49.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C9
25 files changed, 416 insertions, 58 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index d8bd2c3..13ba2f3 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2016-12-21 Jason Merrill <jason@redhat.com>
+
+ * 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 <mjambor@suse.cz>
* 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 57717ff..62d2f46 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 33c5def..a5333a3 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 ffda8e1..db3582a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,26 @@
2016-12-21 Jason Merrill <jason@redhat.com>
+ 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 89bb9b2..ef6265e 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 2954160..e70b34c 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 d80c031..a0cadb8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4758,8 +4758,10 @@ consider_binding_level (tree name, best_match <tree, tree> &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 6abb639..301eb52 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 T, class U = std::allocator<T> > 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<int>' 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<int, std::allocator<T> >' 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<tree,tree> *defaulted_ttp_cache;
+static void
+store_defaulted_ttp (tree v, tree t)
+{
+ if (!defaulted_ttp_cache)
+ defaulted_ttp_cache = hash_map<tree,tree>::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 T, class U = std::allocator<T> > 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<int>' 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<int, std::allocator<T> >' 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 5c92fe6..1096254 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 e301e7a..5ec05cd 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 T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
template<class... Types> 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 0000000..8887033
--- /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 T> class A { /* ... */ };
+template<class T, class U = T> class B { /* ... */ };
+template<template<class> class P> class X { /* ... */ };
+X<A> xa; // OK
+X<B> xb; // OK since P0522R0
+
+#if __cpp_variadic_templates
+template <class ... Types> class C { /* ... */ };
+template<template<class ...> class Q> class Y { /* ... */ };
+X<C> xc; // OK since P0522R0
+Y<A> ya; // OK
+Y<B> yb; // OK
+Y<C> yc; // OK
+#endif
+
+#if __cpp_template_auto
+template<auto n> class D { /* ... */ };
+template<template<int> class R> class Z { /* ... */ };
+Z<D> 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 0000000..72cff38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+
+template<typename _Tp>
+struct get_first_arg;
+
+template<template<typename, typename...> class _Template, typename _Tp,
+ typename... _Types>
+struct get_first_arg<_Template<_Tp, _Types...>>
+{ using type = _Tp; };
+
+template<typename T> struct A { };
+
+template<class,class> struct same;
+template<class T> struct same<T,T> {};
+
+same<get_first_arg<A<int>>::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 0000000..43f951a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+
+template <typename, typename> struct A { };
+template <typename T> struct B { };
+
+template <typename T, template <T...> class C, T... Is>
+struct A<B<T>, C<Is...>>
+{
+ using type = C<Is...>;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic79.C b/gcc/testsuite/g++.dg/cpp0x/variadic79.C
index 389199c..ed5e028 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<template<typename> 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 0000000..67376cc
--- /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<template<typename> class...> struct A;
+
+template<template<typename...> class... B> struct A<B...> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85.C b/gcc/testsuite/g++.dg/cpp0x/variadic85.C
index 708104a..c1d6ab9 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<typename...> struct A1;
template<template<int, int...> class T> struct A1<T<0, 1> > {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85a.C b/gcc/testsuite/g++.dg/cpp0x/variadic85a.C
new file mode 100644
index 0000000..b3cfeee
--- /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<typename...> struct A1;
+template<template<int, int...> class T> struct A1<T<0, 1> > {};
+template<int, int, int...> struct B1 {};
+A1<B1<0, 1> > a1;
+template<int...> struct B2 {};
+A1<B2<0, 1> > a2;
diff --git a/gcc/testsuite/g++.dg/cpp1z/ttp1.C b/gcc/testsuite/g++.dg/cpp1z/ttp1.C
new file mode 100644
index 0000000..7577b5e
--- /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 T, class U = T> class B { /* ... */ };
+#if __cpp_variadic_templates
+template <class ... Types> class C { /* ... */ };
+#endif
+template<template<class> class P, class T> void f(P<T>);
+
+int main()
+{
+ f(B<int>());
+ f(B<int,float>()); // { dg-error "no match" }
+#if __cpp_variadic_templates
+ f(C<int>());
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/template/ttp16.C b/gcc/testsuite/g++.dg/template/ttp16.C
index c556c7d..510ef65 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 <template <typename> class C>
void f() {}
diff --git a/gcc/testsuite/g++.dg/template/ttp16a.C b/gcc/testsuite/g++.dg/template/ttp16a.C
new file mode 100644
index 0000000..0ecada1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp16a.C
@@ -0,0 +1,9 @@
+// { dg-options -fnew-ttp-matching }
+
+template <template <typename> class C>
+void f() {}
+
+template <typename T, typename U = int>
+struct S {};
+
+template void f<S>();
diff --git a/gcc/testsuite/g++.dg/template/ttp17.C b/gcc/testsuite/g++.dg/template/ttp17.C
index f1ddeb1..cc9bc6e 100644
--- a/gcc/testsuite/g++.dg/template/ttp17.C
+++ b/gcc/testsuite/g++.dg/template/ttp17.C
@@ -1,3 +1,5 @@
+// { dg-options -fno-new-ttp-matching }
+
template <template <typename> class C>
void f(C<double>) {}
diff --git a/gcc/testsuite/g++.dg/template/ttp17a.C b/gcc/testsuite/g++.dg/template/ttp17a.C
new file mode 100644
index 0000000..3bd0b0c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp17a.C
@@ -0,0 +1,9 @@
+// { dg-options -fnew-ttp-matching }
+
+template <template <typename> class C>
+void f(C<double>) {}
+
+template <typename T, typename U = int>
+struct S {};
+
+template void f(S<double>);
diff --git a/gcc/testsuite/g++.dg/torture/pr68220.C b/gcc/testsuite/g++.dg/torture/pr68220.C
index 3b27653..9522e2f 100644
--- a/gcc/testsuite/g++.dg/torture/pr68220.C
+++ b/gcc/testsuite/g++.dg/torture/pr68220.C
@@ -1,3 +1,4 @@
+// { dg-options -fno-new-ttp-matching }
// { dg-do compile }
namespace mpl {
template <typename, typename = int> struct lambda;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp49.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp49.C
index 8449849..c60a160 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp49.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp49.C
@@ -1,4 +1,4 @@
-// { dg-do assemble }
+// { dg-options -fno-new-ttp-matching }
template <int i> class C {};
template <template <long> class TT> class D {};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C
new file mode 100644
index 0000000..88a1c50
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C
@@ -0,0 +1,9 @@
+// { dg-options -fnew-ttp-matching }
+
+template <int i> class C {};
+template <template <long> class TT> class D {};
+
+int main()
+{
+ D<C> d;
+}