c++: Fix wrong modifying const object error for COMPONENT_REF [PR94074]
authorMarek Polacek <polacek@redhat.com>
Fri, 6 Mar 2020 22:30:11 +0000 (17:30 -0500)
committerMarek Polacek <polacek@redhat.com>
Wed, 11 Mar 2020 20:25:09 +0000 (16:25 -0400)
commit7eb5be6ab91ec03f93038ac2bcf3028cf2e7c82b
treeb15b0adac3bc6bc93e0afe5acff854aa599b68fa
parent4512b7d85184c7131e98d29255e53cd2d913ddc2
c++: Fix wrong modifying const object error for COMPONENT_REF [PR94074]

I got a report that building Chromium fails with the "modifying a const
object" error.  After some poking I realized it's a bug in GCC, not in
their codebase.

Much like with ARRAY_REFs, which can be const even though the array
itself isn't, COMPONENT_REFs can be const although neither the object
nor the field were declared const.  So let's dial down the checking.
Here the COMPONENT_REF was const because of the "const_cast<const U &>(m)"
thing -- cxx_eval_component_reference then builds a COMPONENT_REF with
TREE_TYPE (t).

While looking into this I noticed that we don't detect modifying a const
object in certain cases like in
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94074#c2>.  That's because
we never evaluate an X::X() CALL_EXPR -- there's none.  Fixed as per
Jason's suggestion by setting TREE_READONLY on a CONSTRUCTOR after
initialization in cxx_eval_store_expression.

2020-03-11  Marek Polacek  <polacek@redhat.com>
    Jason Merrill  <jason@redhat.com>

PR c++/94074 - wrong modifying const object error for COMPONENT_REF.
* constexpr.c (cref_has_const_field): New function.
(modifying_const_object_p): Consider a COMPONENT_REF
const only if any of its fields are const.
(cxx_eval_store_expression): Mark a CONSTRUCTOR of a const type
as readonly after its initialization has been done.

* g++.dg/cpp1y/constexpr-tracking-const17.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const18.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const19.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const20.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const21.C: New test.
* g++.dg/cpp1y/constexpr-tracking-const22.C: New test.
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const18.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const20.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const21.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const22.C [new file with mode: 0644]