On 3/10/20 7:38 PM, Marek Polacek wrote:
This is a bad interaction between sharing a constructor for an array
and stripping its trailing zero-initializers. Here we reuse a ctor
and then strip its 0s. This breaks overload resolution in this test:
D can be initialized from {} but not from {0}, so if we truncate the
constructor not to include the zero, the F(D) overload becomes valid
and then we get the ambiguous conversion error.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
OK.
PR c++/94124 - wrong conversion error with non-viable overload.
* decl.c (reshape_init_array_1): Unshare a constructor if we
stripped trailing zero-initializers.
* g++.dg/cpp0x/initlist-overload1.C: New test.
---
gcc/cp/decl.c | 7 +++++++
gcc/testsuite/g++.dg/cpp0x/initlist-overload1.C | 15 +++++++++++++++
2 files changed, 22 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-overload1.C
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bb242743074..aa58e5f88ae 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6062,6 +6062,13 @@ reshape_init_array_1 (tree elt_type, tree max_index,
reshape_iter *d,
else if (last_nonzero < nelts - 1)
nelts = last_nonzero + 1;
+ /* Sharing a stripped constructor can get in the way of
+ overload resolution. E.g., initializing a class from
+ {{0}} might be invalid while initializing the same class
+ from {{}} might be valid. */
+ if (reuse)
+ new_init = unshare_constructor (new_init);
+
vec_safe_truncate (CONSTRUCTOR_ELTS (new_init), nelts);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-overload1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-overload1.C
new file mode 100644
index 00000000000..12bb606ce67
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-overload1.C
@@ -0,0 +1,15 @@
+// PR c++/94124 - wrong conversion error with non-viable overload.
+// { dg-do compile { target c++11 } }
+
+template <int N> struct A { typedef int _Type[N]; };
+template <int N> struct B { typename A<N>::_Type _M_elems; };
+class C { };
+struct D {
+ D(C);
+};
+
+struct F {
+ F(B<2>);
+ F(D); // This overload should not be viable.
+};
+F fn1() { return {{{0}}}; }
base-commit: 0b7f1e24316cfc1f85408918d1734d3266d65089