diff mbox series

C++ PATCH for c++/85765, SFINAE and non-type default template argument

Message ID CADzB+2=kCVWMsK=FeJovWfE1hvLekrz_b18R3FH8sOOODUTemQ@mail.gmail.com
State New
Headers show
Series C++ PATCH for c++/85765, SFINAE and non-type default template argument | expand

Commit Message

Jason Merrill June 4, 2018, 1:21 p.m. UTC
My patch for 84785 started setting processing_template_decl while
substituting into a default template argument that might use template
parameters we don't yet have arguments for.  That broke this testcase
because when processing_template_decl is set, we don't actually try to
perform the conversion:

  /* In a template, there is no need to perform all of the work that
     is normally done.  We are only interested in the type of the call
     expression, i.e., the return type of the function.  Any semantic
     errors will be deferred until the template is instantiated.  */

But in this case we aren't actually in a template, so we want to get
the error for SFINAE.

With this patch, if the initial substitution replaces all template
parameters, we then do a full substitution.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox series

Patch

commit a2223328af8276d1796501e8706ca3c6b559eff6
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jun 4 09:41:04 2018 +0200

            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.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4c5890deeb8..d3915ddcddf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 00000000000..f0f9dfb73dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C
@@ -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