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

> +     {
> +       cxx_mark_addressable (*tp);
> +       recompute_tree_invariant_for_addr_expr (*tp);
> +     }
> +      *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: 44d4a1086d965fb5280daf65c7c4a253ad6cc8a1
> -- 
> 2.48.1
> 
> 

Reply via email to