diff mbox series

C++ PATCH for c++/82336, ICE with init-list default arg

Message ID CADzB+2kaNBbxL8hbahSEP0BTMM7xdXNSupNS_gRvSWmvWu4XVg@mail.gmail.com
State New
Headers show
Series C++ PATCH for c++/82336, ICE with init-list default arg | expand

Commit Message

Jason Merrill March 14, 2018, 1:02 a.m. UTC
As analyzed by Nathan and Paolo, the problem here is that the test
conversion in check_default_arg is changing the expression, but then
we discard the result.  Excessive sharing of CONSTRUCTORs is an
ongoing issue, due to past decisions motivated by memory savings.  For
the time being, we can specifically unshare the default argument if it
is an initializer-list, since that's the problematic case.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox series

Patch

commit f905470ca5ccda134972fdab07f7ed9a0380bf25
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Mar 13 19:34:54 2018 -0400

            PR c++/82336 - link error with list-init default argument.
    
            * decl.c (check_default_argument): Unshare an initializer list.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index afd04cea630..6c113f25a3d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12661,7 +12661,9 @@  check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
      A default argument expression is implicitly converted to the
      parameter type.  */
   ++cp_unevaluated_operand;
-  perform_implicit_conversion_flags (decl_type, arg, complain,
+  /* Avoid digest_init clobbering the initializer.  */
+  tree carg = BRACE_ENCLOSED_INITIALIZER_P (arg) ? unshare_expr (arg): arg;
+  perform_implicit_conversion_flags (decl_type, carg, complain,
 				     LOOKUP_IMPLICIT);
   --cp_unevaluated_operand;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-defarg2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-defarg2.C
new file mode 100644
index 00000000000..65240355fc3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-defarg2.C
@@ -0,0 +1,8 @@ 
+// PR c++/82336
+// { dg-do link { target c++11 } }
+
+struct foo { int x = 5; };
+struct bar : foo { bar() = default; };
+struct baz { bar x; };
+void qux(baz = {}){}
+int main() { qux(); }