]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/85765 - SFINAE and non-type default template arg.
authorJason Merrill <jason@redhat.com>
Mon, 4 Jun 2018 13:22:52 +0000 (09:22 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 4 Jun 2018 13:22:52 +0000 (09:22 -0400)
* pt.c (type_unification_real): Do full semantic processing if
substituting a partial args list replaces all template parms.

From-SVN: r261146

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C [new file with mode: 0644]

index 5d4caccdb39b4e18afa8c2189144c94ef0fb58e5..773e9334a5ebf236facfba9978bd03d3b114d4a0 100644 (file)
@@ -1,3 +1,9 @@
+2018-06-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/85765 - SFINAE and non-type default template arg.
+       * pt.c (type_unification_real): Do full semantic processing if
+       substituting a partial args list replaces all template parms.
+
 2018-06-03  Jason Merrill  <jason@redhat.com>
 
        PR c++/85739 - ICE with pointer to member template parm.
index 4c5890deeb8793d93ff6b526b5564c501df0a40a..d3915ddcddf2bf5a006159ff8d5ce08594182662 100644 (file)
@@ -20387,8 +20387,6 @@ type_unification_real (tree tparms,
          location_t save_loc = input_location;
          if (DECL_P (parm))
            input_location = DECL_SOURCE_LOCATION (parm);
-         if (saw_undeduced == 1)
-           ++processing_template_decl;
 
          if (saw_undeduced == 1
              && TREE_CODE (parm) == PARM_DECL
@@ -20396,11 +20394,14 @@ type_unification_real (tree tparms,
            {
              /* The type of this non-type parameter depends on undeduced
                 parameters.  Don't try to use its default argument yet,
+                since we might deduce an argument for it on the next pass,
                 but do check whether the arguments we already have cause
                 substitution failure, so that that happens before we try
                 later default arguments (78489).  */
+             ++processing_template_decl;
              tree type = tsubst (TREE_TYPE (parm), full_targs, complain,
                                  NULL_TREE);
+             --processing_template_decl;
              if (type == error_mark_node)
                arg = error_mark_node;
              else
@@ -20408,10 +20409,27 @@ type_unification_real (tree tparms,
            }
          else
            {
-             arg = tsubst_template_arg (arg, full_targs, complain, NULL_TREE);
+             tree substed = NULL_TREE;
+             if (saw_undeduced == 1 && processing_template_decl == 0)
+               {
+                 /* First instatiate in template context, in case we still
+                    depend on undeduced template parameters.  */
+                 ++processing_template_decl;
+                 substed = tsubst_template_arg (arg, full_targs, complain,
+                                                NULL_TREE);
+                 --processing_template_decl;
+                 if (substed != error_mark_node
+                     && !uses_template_parms (substed))
+                   /* We replaced all the tparms, substitute again out of
+                      template context.  */
+                   substed = NULL_TREE;
+               }
+             if (!substed)
+               substed = tsubst_template_arg (arg, full_targs, complain,
+                                              NULL_TREE);
 
-             if (!uses_template_parms (arg))
-               arg = convert_template_argument (parm, arg, full_targs,
+             if (!uses_template_parms (substed))
+               arg = convert_template_argument (parm, substed, full_targs,
                                                 complain, i, NULL_TREE);
              else if (saw_undeduced == 1)
                arg = NULL_TREE;
@@ -20419,8 +20437,6 @@ type_unification_real (tree tparms,
                arg = error_mark_node;
            }
 
-         if (saw_undeduced == 1)
-           --processing_template_decl;
          input_location = save_loc;
          *checks = get_deferred_access_checks ();
          pop_deferring_access_checks ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C
new file mode 100644 (file)
index 0000000..f0f9dfb
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/85765
+// { dg-do compile { target c++11 } }
+
+struct il { il(); il(const il&); };
+
+int* begin(il);
+
+template<class T> T&& declval();
+
+template<class T, class U = decltype(begin(declval<T&>())), decltype(*U(),0) = 0>
+U g(T& t, long) { return begin(t); } // #1
+
+template<class T>
+int g(T& t, ...); // #2
+
+volatile il a;
+
+auto n = g(a, 0); // calls #1 and ends with a hard error, should call #2