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]

Re: C++ PATCH for c++/85977, array reference size deduction failure


On Wed, Jun 06, 2018 at 06:22:16PM +0200, Jason Merrill wrote:
> Right, you want to test conversion to the element type, not the array or
> init list type.

Indeed.  Please tell me this is the right approach :).

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-06-06  Marek Polacek  <polacek@redhat.com>

	PR c++/85977
	* pt.c (unify): If ELTTYPE has no deducible template parms, skip
	deduction from the list elements.
	(type_unification_real): Check convertibility of list elements.

	* g++.dg/cpp0x/initlist102.C: New test.
	* g++.dg/cpp0x/initlist103.C: New test.
	* g++.dg/cpp0x/initlist104.C: New test.

diff --git gcc/cp/pt.c gcc/cp/pt.c
index 448cd69b722..d8880eb138d 100644
--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -20370,6 +20370,22 @@ type_unification_real (tree tparms,
 	    if (check_non_deducible_conversion (parm, arg, strict, flags,
 						explain_p))
 	      return 1;
+
+	    if (BRACE_ENCLOSED_INITIALIZER_P (arg)
+		&& (TREE_CODE (parm) == ARRAY_TYPE || is_std_init_list (parm)))
+	      {
+		tree elt, elttype;
+		unsigned int i;
+
+		if (TREE_CODE (parm) == ARRAY_TYPE)
+		  elttype = TREE_TYPE (parm);
+		else
+		  elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+		FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+		  if (check_non_deducible_conversion (elttype, elt, strict,
+						      flags, explain_p))
+		    return 1;
+	      }
 	  }
 
       /* Now substitute into the default template arguments.  */
@@ -21404,24 +21420,30 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	    return unify_success (explain_p);
 	}
 
-      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
-	{
-	  int elt_strict = strict;
+      if (strict != DEDUCE_EXACT
+	  && TYPE_P (elttype)
+	  && !uses_deducible_template_parms (elttype))
+	/* If ELTTYPE has no deducible template parms, skip deduction from
+	   the list elements.  */;
+      else
+	FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+	  {
+	    int elt_strict = strict;
 
-	  if (elt == error_mark_node)
-	    return unify_invalid (explain_p);
+	    if (elt == error_mark_node)
+	      return unify_invalid (explain_p);
 
-	  if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
-	    {
-	      tree type = TREE_TYPE (elt);
-	      if (type == error_mark_node)
-		return unify_invalid (explain_p);
-	      /* It should only be possible to get here for a call.  */
-	      gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
-	      elt_strict |= maybe_adjust_types_for_deduction
-		(DEDUCE_CALL, &elttype, &type, elt);
-	      elt = type;
-	    }
+	    if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
+	      {
+		tree type = TREE_TYPE (elt);
+		if (type == error_mark_node)
+		  return unify_invalid (explain_p);
+		/* It should only be possible to get here for a call.  */
+		gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
+		elt_strict |= maybe_adjust_types_for_deduction
+		  (DEDUCE_CALL, &elttype, &type, elt);
+		elt = type;
+	      }
 
 	  RECUR_AND_CHECK_FAILURE (tparms, targs, elttype, elt, elt_strict,
 				   explain_p);
diff --git gcc/testsuite/g++.dg/cpp0x/initlist102.C gcc/testsuite/g++.dg/cpp0x/initlist102.C
index e69de29bb2d..e114866292f 100644
--- gcc/testsuite/g++.dg/cpp0x/initlist102.C
+++ gcc/testsuite/g++.dg/cpp0x/initlist102.C
@@ -0,0 +1,39 @@
+// PR c++/85977, Incorrect handling of array reference size deduction
+// { dg-do compile { target c++11 } }
+
+template <int N>
+void fn1 (const char (&)[N]) { static_assert (N == 3, "fn1");}
+
+template <int N>
+void fn2 (const short (&)[N]) { static_assert (N == 3, "fn2");}
+
+template <int N>
+void fn3 (const int (&)[N]) { static_assert (N == 3, "fn2");}
+
+template <int N>
+void fn4 (const long (&)[N]) { static_assert (N == 3, "fn4");}
+
+template <int N>
+void fn5 (const unsigned char (&)[N]) { static_assert (N == 3, "fn5");}
+
+template <int N>
+void fn6 (const unsigned short (&)[N]) { static_assert (N == 3, "fn6");}
+
+template <int N>
+void fn7 (const unsigned int (&)[N]) { static_assert (N == 3, "fn7");}
+
+template <int N>
+void fn8 (const unsigned int (&)[N]) { static_assert (N == 3, "fn8");}
+
+void
+bar ()
+{
+  fn1 ({1, 2, 3});
+  fn2 ({1, 2, 3});
+  fn3 ({1, 2, 3});
+  fn4 ({1, 2, 3});
+  fn5 ({1, 2, 3});
+  fn6 ({1, 2, 3});
+  fn7 ({1, 2, 3});
+  fn8 ({1, 2, 3});
+}
diff --git gcc/testsuite/g++.dg/cpp0x/initlist103.C gcc/testsuite/g++.dg/cpp0x/initlist103.C
index e69de29bb2d..0c1923c6ab0 100644
--- gcc/testsuite/g++.dg/cpp0x/initlist103.C
+++ gcc/testsuite/g++.dg/cpp0x/initlist103.C
@@ -0,0 +1,11 @@
+// PR c++/85977, Incorrect handling of array reference size deduction
+// { dg-do compile { target c++11 } }
+
+template <int N>
+void fn (const char (&)[N]) { }
+
+void
+bar ()
+{
+  fn ({1.2}); // { dg-error "narrowing" }
+}
diff --git gcc/testsuite/g++.dg/cpp0x/initlist104.C gcc/testsuite/g++.dg/cpp0x/initlist104.C
index e69de29bb2d..99487a70607 100644
--- gcc/testsuite/g++.dg/cpp0x/initlist104.C
+++ gcc/testsuite/g++.dg/cpp0x/initlist104.C
@@ -0,0 +1,11 @@
+// PR c++/85977, Incorrect handling of array reference size deduction
+// { dg-do compile { target c++11 } }
+
+template <typename T, int N>
+void fn (const T (&)[N]) { static_assert (N == 3, "fn"); }
+
+void
+bar ()
+{
+  fn ({1, 2, 3});
+}


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