This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] [PR c++/84979] improve auto handling in explicit tmpl args for concepts


We fail to detect unresolved explicitly-passed auto template args.

The first hunk in pt.c, that changes fn_type_unification, arranges for
us to regard the template arg list as incomplete, although that's not
necessary for any of the testcases I tried.  I thought it might be
relevant in case the args become part of the type of the function, and
for us to continue overload resolution with processing_template_decl
nonzero.

The second hunk, that changes type_unification_real, is the actual fix
for the testcase in the PR.

The other hunks, that change unify, arrange for us to accept and
properly update the template arglist, at least when auto stands by
itself as a template argument.  Without this hunk, the slightly
modified testcase pr84979-2.C would fail, although there's no good
reason for the deduction to be regarded as a mismatch.

We still need some work, however: pr84979-3.C and pr84979-4.C should
be accepted, if we are to support non-toplevel auto in explicit
parameters (-3), or auto in parms whose index doesn't match the auto's
own index.


This is probably not good enough for inclusion, although I'm pretty sure
it passes regstrap.  The problem is the condition in unify() that
intends to allow proper uses of auto by do_auto_deduction, and the
AFAICT accidentally-working cases of auto deduction in explicit template
args: the condition that covers those cases is growing incredibly
hairier and fragile, and I'm growing convinced I took a wrong turn
somewhere that led me there.  I'm almost ready to conclude that I'm
either missing something, or that we shouldn't be supporting auto in
explicit template args at all, because I can't see that the
implementation was ever meant to support that use.  Is that so?  I could
use some advice there.  Thanks in advance,


for  gcc/cp/ChangeLog

	PR c++/84979
	* pt.c (fn_type_unification): Set incomplete if explicit args
	use auto.
	(type_unification_real): Do not skip deduction if explicit
	arg uses auto.
	(unify): Reject unsupported cases of auto in args.  Regard
	auto as a match, but proceed to update targ.

for  gcc/testsuite/ChangeLog

	PR c++/84979
	* g++.dg/concepts/pr84979.C: New.
	* g++.dg/concepts/pr84979-2.C: New.
	* g++.dg/concepts/pr84979-3.C: New.
	* g++.dg/concepts/pr84979-4.C: New.
---
 gcc/cp/pt.c                               |   56 +++++++++++++++++++++++++++--
 gcc/testsuite/g++.dg/concepts/pr84979-2.C |    9 +++++
 gcc/testsuite/g++.dg/concepts/pr84979-3.C |    9 +++++
 gcc/testsuite/g++.dg/concepts/pr84979-4.C |    9 +++++
 gcc/testsuite/g++.dg/concepts/pr84979.C   |    9 +++++
 5 files changed, 88 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979-2.C
 create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979-3.C
 create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979-4.C
 create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5293c2b5491b..2b9e5f1ada45 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19109,7 +19109,10 @@ fn_type_unification (tree fn,
               parameter_pack = TEMPLATE_PARM_PARAMETER_PACK (parm);
             }
 
-	  if (!parameter_pack && targ == NULL_TREE)
+	  if (!parameter_pack
+	      && (targ == NULL_TREE
+		  || (flag_concepts
+		      && type_uses_auto (targ))))
 	    /* No explicit argument for this template parameter.  */
 	    incomplete = true;
 
@@ -19891,7 +19894,12 @@ type_unification_real (tree tparms,
               ARGUMENT_PACK_EXPLICIT_ARGS (targ) = NULL_TREE;
             }
 
-	  if (targ || tparm == error_mark_node)
+	  if ((targ
+	       && (!flag_concepts
+		   /* We have to unify explicitly-passed template args
+		      involving auto types.  */
+		   || !type_uses_auto (targ)))
+	      || tparm == error_mark_node)
 	    continue;
 	  tparm = TREE_VALUE (tparm);
 
@@ -20952,6 +20960,37 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
   if (parm == any_targ_node || arg == any_targ_node)
     return unify_success (explain_p);
 
+  /* Concepts allows 'auto' in template arguments, even multiple
+     'auto's in a single argument.  We don't know how to deal with
+     them here: see how do_auto_deduction uses extract_autos to
+     construct a separate template args vec, that such autos index.
+     Since we don't do any of that, we can only substitute toplevel
+     auto parameters, and only when their index happens to match their
+     position in the template argument list.  Catch deviations instead
+     of corrupting targs.  */
+  if (flag_concepts && is_auto (parm)
+      && ((TEMPLATE_TYPE_IDX (parm)
+	   >= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (targs)))
+	  || (TREE_CODE (TREE_VALUE (TREE_VEC_ELT
+				     (tparms, TEMPLATE_TYPE_IDX (parm))))
+	      != TYPE_DECL)
+	  || (TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs),
+			    TEMPLATE_TYPE_IDX (parm)) != parm
+	      /* do_auto_deduction calls us properly, i.e., with the
+		 extra targs level, so don't complain about its uses.
+		 ??? Is there a better/surer way to test for the
+		 proper uses?  */
+	      && TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs),
+			       TEMPLATE_TYPE_IDX (parm)) != NULL_TREE
+	      && type_uses_auto (TREE_VEC_ELT
+				 (INNERMOST_TEMPLATE_ARGS (targs),
+				  TEMPLATE_TYPE_IDX (parm))))))
+    {
+      if (complain & tf_error)
+	sorry ("unsupported use of auto in explicit template parameter list");
+      return unify_invalid (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
@@ -21147,8 +21186,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	{
 	  /* Deduce template name TT from TT, TT<>, TT<T> and TT<i>.  */
 
+	  /* Substitute (some) concepts-specified auto parms.
+	     ??? Can autos ever pass the test above?  */
+	  if (targ != NULL_TREE && flag_concepts && parm == targ
+	      && is_auto (parm))
+	    ;
 	  /* Simple cases: Value already set, does match or doesn't.  */
-	  if (targ != NULL_TREE && template_args_equal (targ, arg))
+	  else if (targ != NULL_TREE && template_args_equal (targ, arg))
 	    return unify_success (explain_p);
 	  else if (targ)
 	    return unify_inconsistency (explain_p, parm, targ, arg);
@@ -21170,8 +21214,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	  if (arg == error_mark_node)
 	    return unify_invalid (explain_p);
 
+	  /* Substitute (some) concepts-specified auto parms.  */
+	  if (targ != NULL_TREE && flag_concepts && parm == targ
+	      && is_auto (parm))
+	    ;
 	  /* Simple cases: Value already set, does match or doesn't.  */
-	  if (targ != NULL_TREE && same_type_p (targ, arg))
+	  else if (targ != NULL_TREE && same_type_p (targ, arg))
 	    return unify_success (explain_p);
 	  else if (targ)
 	    return unify_inconsistency (explain_p, parm, targ, arg);
diff --git a/gcc/testsuite/g++.dg/concepts/pr84979-2.C b/gcc/testsuite/g++.dg/concepts/pr84979-2.C
new file mode 100644
index 000000000000..140b051b311e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr84979-2.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+template<typename T, int> void foo(T t) {}
+
+void bar()
+{
+  foo<auto, 0>(bar);
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr84979-3.C b/gcc/testsuite/g++.dg/concepts/pr84979-3.C
new file mode 100644
index 000000000000..93a0140e8390
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr84979-3.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+template<typename T, int> void foo(T t) {}
+
+void bar()
+{
+  foo<auto (*)(), 0>(bar); // { dg-bogus "unimplemented|no matching function" "" { xfail *-*-* } }
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr84979-4.C b/gcc/testsuite/g++.dg/concepts/pr84979-4.C
new file mode 100644
index 000000000000..08054d0d832a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr84979-4.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+template<int, typename T> void foo(T t) {}
+
+void bar()
+{
+  foo<0, auto>(bar); // { dg-bogus "unimplemented|no matching function" "" { xfail *-*-* } }
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr84979.C b/gcc/testsuite/g++.dg/concepts/pr84979.C
new file mode 100644
index 000000000000..c70b3756f2b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr84979.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+template<typename> void foo() {}
+
+void bar()
+{
+  foo<auto>(); // { dg-error "invalid|no match" }
+}


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]