On Wed, Feb 19, 2025 at 10:14:21AM -0500, Patrick Palka wrote:
> On Wed, 19 Feb 2025, Marek Polacek wrote:
>
> > I suppose it's safer to leave this for GCC 16, but anyway:
> >
> > Bootstrapped/regtested on x86_64-pc-linux-gnu.
> >
> > -- >8 --
> > Since r10-7718 the attached tests produce an ICE in verify_address:
> >
> > error: constant not recomputed when 'ADDR_EXPR' changed
> >
> > but before that we wrongly rejected the tests with "is not a constant
> > expression". This patch fixes both problems.
> >
> > Since r10-7718 replace_decl_r can replace
> >
> > {._M_dataplus=&<retval>._M_local_buf, ._M_local_buf=0}
> >
> > with
> >
> > {._M_dataplus=&HelloWorld._M_local_buf, ._M_local_buf=0}
> >
> > The initial &<retval>._M_local_buf was not constant, but since
> > HelloWorld is a static VAR_DECL, the resulting &HelloWorld._M_local_buf
> > should have been marked as TREE_CONSTANT. And since we're taking
> > its address, the whole thing should be TREE_ADDRESSABLE.
> >
> > PR c++/114913
> > PR c++/110822
> >
> > gcc/cp/ChangeLog:
> >
> > * constexpr.cc (replace_decl_r): If we've replaced something
> > inside of an ADDR_EXPR, call cxx_mark_addressable and
> > recompute_tree_invariant_for_addr_expr on the resulting ADDR_EXPR.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/cpp0x/constexpr-nsdmi4.C: New test.
> > * g++.dg/cpp0x/constexpr-nsdmi5.C: New test.
> > ---
> > gcc/cp/constexpr.cc | 17 ++++++++++++++++-
> > gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C | 19 +++++++++++++++++++
> > gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C | 15 +++++++++++++++
> > 3 files changed, 50 insertions(+), 1 deletion(-)
> > create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
> > create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
> >
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 59dd0668af3..c41454057cb 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -2707,7 +2707,22 @@ replace_decl_r (tree *tp, int *walk_subtrees, void
> > *data)
> > {
> > replace_decl_data *d = (replace_decl_data *) data;
> >
> > - if (*tp == d->decl)
> > + /* We could be replacing
> > + &<retval>.bar -> &foo.bar
> > + where foo is a static VAR_DECL, so we need to recompute TREE_CONSTANT
> > + on the ADDR_EXPR around it. */
> > + if (TREE_CODE (*tp) == ADDR_EXPR)
> > + {
> > + d->pset->add (*tp);
> > + cp_walk_tree (&TREE_OPERAND (*tp, 0), replace_decl_r, d, nullptr);
> > + if (d->changed)
>
> d->changed could already be true if something before the ADDR_EXPR was
> replaced. I think we should clear/restore d->changed around the
> cp_walk_tree call to accurately track whether anything inside the
> ADDR_EXPR was replaced. Otherwise LGTM
You're right! I believe I have to restore d->changed like this. Thanks.
Tested on x86_64-pc-linux-gnu.
-- >8 --
Since r10-7718 the attached tests produce an ICE in verify_address:
error: constant not recomputed when 'ADDR_EXPR' changed
but before that we wrongly rejected the tests with "is not a constant
expression". This patch fixes both problems.
Since r10-7718 replace_decl_r can replace
{._M_dataplus=&<retval>._M_local_buf, ._M_local_buf=0}
with
{._M_dataplus=&HelloWorld._M_local_buf, ._M_local_buf=0}
The initial &<retval>._M_local_buf was not constant, but since
HelloWorld is a static VAR_DECL, the resulting &HelloWorld._M_local_buf
should have been marked as TREE_CONSTANT. And since we're taking
its address, the whole thing should be TREE_ADDRESSABLE.
PR c++/114913
PR c++/110822
gcc/cp/ChangeLog:
* constexpr.cc (replace_decl_r): If we've replaced something
inside of an ADDR_EXPR, call cxx_mark_addressable and
recompute_tree_invariant_for_addr_expr on the resulting ADDR_EXPR.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/constexpr-nsdmi4.C: New test.
* g++.dg/cpp0x/constexpr-nsdmi5.C: New test.
---
gcc/cp/constexpr.cc | 21 ++++++++++++++++++-
gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C | 19 +++++++++++++++++
gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C | 15 +++++++++++++
3 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 59dd0668af3..a478faddbb5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2707,7 +2707,26 @@ replace_decl_r (tree *tp, int *walk_subtrees, void *data)
{
replace_decl_data *d = (replace_decl_data *) data;
- if (*tp == d->decl)
+ /* We could be replacing
+ &<retval>.bar -> &foo.bar
+ where foo is a static VAR_DECL, so we need to recompute TREE_CONSTANT
+ on the ADDR_EXPR around it. */
+ if (TREE_CODE (*tp) == ADDR_EXPR)
+ {
+ d->pset->add (*tp);
+ auto save_changed = d->changed;
+ d->changed = false;
+ cp_walk_tree (&TREE_OPERAND (*tp, 0), replace_decl_r, d, nullptr);
+ if (d->changed)
+ {
+ cxx_mark_addressable (*tp);
+ recompute_tree_invariant_for_addr_expr (*tp);
+ }
+ else
+ d->changed = save_changed;
+ *walk_subtrees = 0;
+ }
+ else if (*tp == d->decl)
{
*tp = unshare_expr (d->replacement);
d->changed = true;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
new file mode 100644
index 00000000000..360470dbccb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
@@ -0,0 +1,19 @@
+// PR c++/114913
+// { dg-do compile { target c++11 } }
+
+struct strt {
+ char *_M_dataplus;
+ char _M_local_buf = 0;
+ constexpr strt()
+ : _M_dataplus(&_M_local_buf) {}
+ constexpr strt(const strt &)
+ : _M_dataplus(&_M_local_buf) {}
+};
+
+constexpr strt
+f ()
+{
+ return {};
+}
+constexpr strt HelloWorld = f();
+const char *a() { return HelloWorld._M_dataplus; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
new file mode 100644
index 00000000000..0a0acaa9fdf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
@@ -0,0 +1,15 @@
+// PR c++/110822
+// { dg-do compile { target c++11 } }
+
+void __ostream_insert(const char*);
+struct basic_string {
+ const char* _M_p;
+ char _M_local_buf[16] = {};
+ constexpr basic_string() : _M_p(_M_local_buf) {}
+ const char *data() const { return _M_p; }
+};
+constexpr basic_string f() { return {}; }
+constexpr basic_string text = f();
+int main() {
+ __ostream_insert(text._M_p);
+}
base-commit: ee6619b1246b38cfb36f6efd931a6f475a9033c7
--
2.48.1