We don't unshare CONSTRUCTORs as often during constexpr evaluation, so we
need to unshare them here.

Many thanks to bin cheng for the analysis and initial patch.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * constexpr.c (cxx_eval_outermost_constant_expr): Don't assume
        CONSTRUCTORs are already unshared.
---
 gcc/cp/constexpr.c                            |  6 ++---
 .../g++.dg/cpp0x/constexpr-array22.C          | 27 +++++++++++++++++++
 2 files changed, 30 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 9306a7dce4a..3ca3b9ecd65 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6347,10 +6347,10 @@ cxx_eval_outermost_constant_expr (tree t, bool 
allow_non_constant,
   if (!non_constant_p && overflow_p)
     non_constant_p = true;
 
-  /* Unshare the result unless it's a CONSTRUCTOR in which case it's already
-     unshared.  */
+  /* Unshare the result.  */
   bool should_unshare = true;
-  if (r == t || TREE_CODE (r) == CONSTRUCTOR)
+  if (r == t || (TREE_CODE (t) == TARGET_EXPR
+                && TARGET_EXPR_INITIAL (t) == r))
     should_unshare = false;
 
   if (non_constant_p && !allow_non_constant)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C
new file mode 100644
index 00000000000..80e24e2d697
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C
@@ -0,0 +1,27 @@
+// PR c++/93143
+// { dg-do run { target c++11 } }
+
+struct A { char a[2]; };
+
+static constexpr A foo () { return A{1}; }
+
+void bar ()
+{
+  A a = foo ();
+  if (a.a[0] != 1)
+    __builtin_abort(); 
+}
+
+void foobar ()
+{
+  A x[] = { foo (), foo () };
+  A a = foo ();
+  if (a.a[0] != 1)
+    __builtin_abort(); 
+}
+
+int main()
+{
+  bar();
+  foobar();
+}

base-commit: c9f70c28f33768726b227eb188575882cd40ed52
-- 
2.18.1

Reply via email to