aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-10-29 20:34:43 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-10-29 20:34:43 +0000
commit0f1848002a137f3cac5026c5a3af6e16ceabe552 (patch)
tree4af514ce33b47850b73ec43906ac4a386d66cae7
parent6cd96bad607c5d6a2302e97ab6f749edb85b82ed (diff)
downloadgcc-0f1848002a137f3cac5026c5a3af6e16ceabe552.zip
gcc-0f1848002a137f3cac5026c5a3af6e16ceabe552.tar.gz
gcc-0f1848002a137f3cac5026c5a3af6e16ceabe552.tar.bz2
PR c++/91548 - fix detecting modifying const objects for ARRAY_REF.
This fixes a bogus "modifying a const object" error for an array that actually isn't declared const. The problem was how I handled ARRAY_REFs here; we shouldn't look at the ARRAY_REF itself, but at the array its accessing. * constexpr.c (cxx_eval_store_expression): Don't call modifying_const_object_p for ARRAY_REF. * g++.dg/cpp1y/constexpr-tracking-const15.C: New test. * g++.dg/cpp1y/constexpr-tracking-const16.C: New test. * g++.dg/cpp1z/constexpr-tracking-const1.C: New test. From-SVN: r277591
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/constexpr.c13
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const15.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const16.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-tracking-const1.C25
6 files changed, 90 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c244438..09d1c18 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-10-29 Marek Polacek <polacek@redhat.com>
+
+ PR c++/91548 - fix detecting modifying const objects for ARRAY_REF.
+ * constexpr.c (cxx_eval_store_expression): Don't call
+ modifying_const_object_p for ARRAY_REF.
+
2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
* cp-objcp-common.h (cxx_simulate_enum_decl): Declare.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 11a1eaa..6b4e854 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3910,10 +3910,6 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
tree elt = TREE_OPERAND (probe, 1);
if (TREE_CODE (elt) == FIELD_DECL && DECL_MUTABLE_P (elt))
mutable_p = true;
- if (evaluated
- && modifying_const_object_p (TREE_CODE (t), probe, mutable_p)
- && const_object_being_modified == NULL_TREE)
- const_object_being_modified = probe;
if (TREE_CODE (probe) == ARRAY_REF)
{
elt = eval_and_check_array_index (ctx, probe, false,
@@ -3921,6 +3917,15 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
if (*non_constant_p)
return t;
}
+ /* We don't check modifying_const_object_p for ARRAY_REFs. Given
+ "int a[10]", an ARRAY_REF "a[2]" can be "const int", even though
+ the array isn't const. Instead, check "a" in the next iteration;
+ that will detect modifying "const int a[10]". */
+ else if (evaluated
+ && modifying_const_object_p (TREE_CODE (t), probe,
+ mutable_p)
+ && const_object_being_modified == NULL_TREE)
+ const_object_being_modified = probe;
vec_safe_push (refs, elt);
vec_safe_push (refs, TREE_TYPE (probe));
probe = ob;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aba9922..cffd592 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2019-10-29 Marek Polacek <polacek@redhat.com>
+
+ PR c++/91548 - fix detecting modifying const objects for ARRAY_REF.
+ * g++.dg/cpp1y/constexpr-tracking-const15.C: New test.
+ * g++.dg/cpp1y/constexpr-tracking-const16.C: New test.
+ * g++.dg/cpp1z/constexpr-tracking-const1.C: New test.
+
2019-10-29 Martin Sebor <msebor@redhat.com>
PR testsuite/92144
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const15.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const15.C
new file mode 100644
index 0000000..db1b2bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const15.C
@@ -0,0 +1,21 @@
+// PR c++/91548 - fix detecting modifying const objects for ARRAY_REF.
+// { dg-do compile { target c++14 } }
+
+constexpr int& impl(const int (&array)[10], int index) {
+ return const_cast<int&>(array[index]);
+}
+
+struct A {
+ constexpr int& operator[](int i) { return impl(elems, i); }
+ int elems[10];
+};
+
+constexpr bool
+f()
+{
+ A arr = {};
+ arr[2] = true;
+ return false;
+}
+
+constexpr bool b = f();
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const16.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const16.C
new file mode 100644
index 0000000..5a5b92b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const16.C
@@ -0,0 +1,22 @@
+// PR c++/91548 - fix detecting modifying const objects for ARRAY_REF.
+// { dg-do compile { target c++14 } }
+
+constexpr int& impl(const int (&array)[10], int index) {
+ return const_cast<int&>(array[index]);
+}
+
+struct A {
+ constexpr int& operator[](int i) { return impl(elems, i); }
+ const int elems[10];
+};
+
+constexpr bool
+f()
+{
+ A arr = {};
+ arr[2] = 1; // { dg-error "modifying a const object" }
+ return false;
+}
+
+constexpr bool b = f(); // { dg-message "in .constexpr. expansion of " }
+// { dg-message "originally declared" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-tracking-const1.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-tracking-const1.C
new file mode 100644
index 0000000..a3856b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-tracking-const1.C
@@ -0,0 +1,25 @@
+// PR c++/91548 - fix detecting modifying const objects for ARRAY_REF.
+// { dg-do compile { target c++17 } }
+
+using size_t = decltype(sizeof(0));
+
+template <typename T, size_t N>
+constexpr T& impl(T const (&array)[N], size_t index) {
+ return const_cast<T&>(array[index]);
+}
+
+template <typename T, size_t N>
+struct my_array {
+ constexpr T& operator[](size_t i) { return impl(elems, i); }
+ constexpr T const& operator[](size_t i) const { return elems[i]; }
+ T elems[N];
+};
+
+bool f(int i) {
+ static constexpr auto table = []() {
+ my_array<bool, 256> arr = {};
+ arr[2] = true;
+ return arr;
+ }();
+ return table[i];
+}