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?

        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
-- 
Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA

Reply via email to