Implement P0522R0, matching of template template arguments.
authorJason Merrill <jason@redhat.com>
Wed, 21 Dec 2016 19:39:04 +0000 (14:39 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 21 Dec 2016 19:39:04 +0000 (14:39 -0500)
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

26 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
gcc/testsuite/g++.dg/cpp0x/variadic-ex14a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ttp4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ttp5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic79.C
gcc/testsuite/g++.dg/cpp0x/variadic79a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic85.C
gcc/testsuite/g++.dg/cpp0x/variadic85a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/ttp1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/ttp16.C
gcc/testsuite/g++.dg/template/ttp16a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/ttp17.C
gcc/testsuite/g++.dg/template/ttp17a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/pr68220.C
gcc/testsuite/g++.old-deja/g++.pt/ttp49.C
gcc/testsuite/g++.old-deja/g++.pt/ttp49a.C [new file with mode: 0644]
libstdc++-v3/ChangeLog

index d8bd2c383f994a4d224c49332f3a86bdaade0ccd..13ba2f314a94aea915212edc1e67500e48ff3474 100644 (file)
@@ -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.
index 57717ff41d883bca9b5f14bf3ebd19653eac90f5..62d2f46f926063527273e4744981c59534e7a72f 100644 (file)
@@ -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
index 33c5def759296d22438560c65c7fc215a5e6ea71..a5333a35e4149e64e89ad03939ed25b6b37ec306 100644 (file)
@@ -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.
index ffda8e161004f94a8666c3432c289cbdb08852ac..db3582af2bccb48253800a84d3680ad8d409cfe1 100644 (file)
@@ -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.
index 89bb9b28f016db8c2217a7c6d655a67dca4f95fc..ef6265e9b4e5e3e426d13eb84717ef662555a9a1 100644 (file)
@@ -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.  */
 
index 295416051b709b5428cf1d58d0631568cfa55fe7..e70b34c9a179cc37186964289fb830f4002aa327 100644 (file)
@@ -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;
 
index d80c0318330a0e67bb31f4c9d297d38c708f5de3..a0cadb8d6e74592d1f960a7c4746cfe11fc56c96 100644 (file)
@@ -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));
     }
 }
 
index 6abb639e0812b4f88d39af0793256ad191eed253..301eb5271bae5779c2e870191b4992f625a06206 100644 (file)
@@ -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
index 5c92fe69335cae0b5657bff37ac79f86cb88a906..1096254085fa08900b56c316f6105a4f9c786401 100644 (file)
@@ -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
index e301e7ac38d3846b60cacb83211e8fd1e40def6f..5ec05cd426412abf0e80e345fbf3f6b79f8556f7 100644 (file)
@@ -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 (file)
index 0000000..8887033
--- /dev/null
@@ -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 (file)
index 0000000..72cff38
--- /dev/null
@@ -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 (file)
index 0000000..43f951a
--- /dev/null
@@ -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...>;
+};
index 389199cc41db315dde97968a151892adf8ce1893..ed5e0284d2316aec8c9117cb2b73b9f0eb25b24a 100644 (file)
@@ -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 (file)
index 0000000..67376cc
--- /dev/null
@@ -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...> {};
index 708104af9072b1dbf1f078929d736b386d4f0c1a..c1d6ab9092c8dd58ad169fa094b47f2fd1cc85e2 100644 (file)
@@ -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 (file)
index 0000000..b3cfeee
--- /dev/null
@@ -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 (file)
index 0000000..7577b5e
--- /dev/null
@@ -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
+}
index c556c7d98a440c50c99c6779dd614986355d5403..510ef6529654e1d64ea4ccaa2f9a743174955bc6 100644 (file)
@@ -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 (file)
index 0000000..0ecada1
--- /dev/null
@@ -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>();
index f1ddeb12ef3be4ae4cd27cb7cdfb14be62c0aa6d..cc9bc6ed46fe57b00bc3016281b895347ff54fd3 100644 (file)
@@ -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 (file)
index 0000000..3bd0b0c
--- /dev/null
@@ -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>);
index 3b27653219cdff7b6e1586f6462de07af45b121f..9522e2f841989c91501b15592d2a4db0837e10e6 100644 (file)
@@ -1,3 +1,4 @@
+// { dg-options -fno-new-ttp-matching }
 // { dg-do compile }
 namespace mpl {
 template <typename, typename = int> struct lambda;
index 8449849540ecf7811dc398cc23e0487a000acd57..c60a16064c4ff8cbe0f3489f320bb8a09b24df6a 100644 (file)
@@ -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 (file)
index 0000000..88a1c50
--- /dev/null
@@ -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;
+}
index 6263652977daa2c9428a2c17cc56e8a29297c042..793be154ac033edf37d1ac59653f2d369cbddbac 100644 (file)
@@ -1,4 +1,4 @@
-2016-12-16  Jason Merrill  <jason@redhat.com>
+2016-12-21  Jason Merrill  <jason@redhat.com>
 
        * testsuite/util/testsuite_tr1.h (test_property): Don't define both
        variadic and non-variadic overloads.