This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/69995 (wrong value with C++14 constexpr)


The bug here was that we were sharing the CONSTRUCTOR between the value of 'a' and the elements of 'result', so changing 'a' also changed the value of result[0]. Oops.

Tested x86_64-pc-linux-gnu, applying to trunk and 5.
commit 20c203ae124fd4fb2975eb3fb0c50ce7ade35e69
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Feb 28 23:50:41 2016 -0500

    	PR c++/69995
    	* constexpr.c (cxx_eval_store_expression): Unshare init.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 8d9168c..5e35940 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2925,6 +2925,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
 
   init = cxx_eval_constant_expression (&new_ctx, init, false,
 				       non_constant_p, overflow_p);
+  /* Don't share a CONSTRUCTOR that might be changed later.  */
+  init = unshare_expr (init);
   if (target == object)
     {
       /* The hash table might have moved since the get earlier.  */
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-array3.C
new file mode 100644
index 0000000..8cea41a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-array3.C
@@ -0,0 +1,43 @@
+// PR c++/69995
+// { dg-do compile { target c++14 } }
+
+#define assert(X) static_assert((X),#X)
+
+#define CONSTEXPR constexpr
+
+template <typename T, unsigned long Size>
+struct array {
+    T elems_[Size];
+
+    constexpr T const& operator[](unsigned long n) const
+    { return elems_[n]; }
+
+    constexpr T& operator[](unsigned long n)
+    { return elems_[n]; }
+};
+
+template <typename T>
+CONSTEXPR void my_swap(T& a, T& b) {
+    T tmp = a;
+    a = b;
+    b = tmp;
+}
+
+CONSTEXPR auto rotate2() {
+    array<array<int, 2>, 2> result{};
+    array<int, 2> a{{0, 1}};
+
+    result[0] = a;
+    my_swap(a[0], a[1]);
+    result[1] = a;
+
+    return result;
+}
+
+int main() {
+    CONSTEXPR auto indices = rotate2();
+    assert(indices[0][0] == 0);
+    assert(indices[0][1] == 1);
+    assert(indices[1][0] == 1);
+    assert(indices[1][1] == 0);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]