re PR c++/85977 (Incorrect handling of array reference size deduction)
authorMarek Polacek <polacek@redhat.com>
Wed, 6 Jun 2018 17:51:19 +0000 (17:51 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 6 Jun 2018 17:51:19 +0000 (17:51 +0000)
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.

From-SVN: r261241

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

index f03c9df..68df054 100644 (file)
@@ -1,3 +1,10 @@
+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.
+
 2018-06-06  Jason Merrill  <jason@redhat.com>
 
        PR c++/86060 - ICE on range for with -std=c++98.
index 448cd69..d8880eb 100644 (file)
@@ -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);
index f63c9d7..14f575e 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-06  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/85977
+       * g++.dg/cpp0x/initlist102.C: New test.
+       * g++.dg/cpp0x/initlist103.C: New test.
+       * g++.dg/cpp0x/initlist104.C: New test.
+
 2018-06-06  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.dg/torture/pr86066.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist102.C b/gcc/testsuite/g++.dg/cpp0x/initlist102.C
new file mode 100644 (file)
index 0000000..e114866
--- /dev/null
@@ -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 a/gcc/testsuite/g++.dg/cpp0x/initlist103.C b/gcc/testsuite/g++.dg/cpp0x/initlist103.C
new file mode 100644 (file)
index 0000000..0c1923c
--- /dev/null
@@ -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 a/gcc/testsuite/g++.dg/cpp0x/initlist104.C b/gcc/testsuite/g++.dg/cpp0x/initlist104.C
new file mode 100644 (file)
index 0000000..99487a7
--- /dev/null
@@ -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});
+}