diff options
author | Marek Polacek <polacek@redhat.com> | 2019-10-29 20:34:43 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-10-29 20:34:43 +0000 |
commit | 0f1848002a137f3cac5026c5a3af6e16ceabe552 (patch) | |
tree | 4af514ce33b47850b73ec43906ac4a386d66cae7 /gcc | |
parent | 6cd96bad607c5d6a2302e97ab6f749edb85b82ed (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const15.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const16.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/constexpr-tracking-const1.C | 25 |
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]; +} |