We are failing to deduce the template parameter N here template <int N> void foo(const long int (&)[N]) {}
void bar() { foo ({1,2,3}); } because of the type mismatch; parm is long int (element type of the array), while arg is int (element type of {1, 2, 3}), and unify doesn't like that: 21789 /* We have already checked cv-qualification at the top of the 21790 function. */ 21791 if (!same_type_ignoring_top_level_qualifiers_p (arg, parm)) 21792 return unify_type_mismatch (explain_p, parm, arg); But since the parameter type is array, we should see if there exists an implicit conversion sequence for each element of the array from the corresponding element of the initializer list, and that's what I tried, and it seems to work. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2018-05-30 Marek Polacek <pola...@redhat.com> PR c++/85977 * pt.c (unify): Handle the [over.ics.list]/6 case. * 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 d0fc9ee51a5..4c899b58764 100644 --- gcc/cp/pt.c +++ gcc/cp/pt.c @@ -21398,6 +21398,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, if (!BRACE_ENCLOSED_INITIALIZER_P (elt)) { + /* [over.ics.list]/6 says we should try an implicit conversion + from each list element to the corresponding array element + type. */ + if (TREE_CODE (parm) == ARRAY_TYPE) + { + tree x = perform_implicit_conversion (elttype, elt, complain); + if (x != error_mark_node) + elt = x; + } + tree type = TREE_TYPE (elt); if (type == error_mark_node) return unify_invalid (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}); +}