]> git.ipfire.org Git - thirdparty/gcc.git/commit
c++: Don't replace INDIRECT_REFs by a const capture proxy too eagerly [PR117504]
authorSimon Martin <simon@nasilyan.com>
Thu, 6 Mar 2025 09:10:45 +0000 (10:10 +0100)
committerSimon Martin <simon@nasilyan.com>
Thu, 6 Mar 2025 09:11:26 +0000 (10:11 +0100)
commitfdf846fdddcc0467b9f025757f081c5d54319d08
treebd6a1982273dc811e090ee1ebee6bcb7e8d85ec4
parent0aa9b079aec260b120b7c9fdba8c21066425c73d
c++: Don't replace INDIRECT_REFs by a const capture proxy too eagerly [PR117504]

We have been miscompiling the following valid code since GCC8, and
r8-3497-g281e6c1d8f1b4c

=== cut here ===
struct span {
  span (const int (&__first)[1]) : _M_ptr (__first) {}
  int operator[] (long __i) { return _M_ptr[__i]; }
  const int *_M_ptr;
};
void foo () {
  constexpr int a_vec[]{1};
  auto vec{[&a_vec]() -> span { return a_vec; }()};
}
=== cut here ===

The problem is that perform_implicit_conversion_flags (via
mark_rvalue_use) replaces "a_vec" in the return statement by a
CONSTRUCTOR representing a_vec's constant value, and then takes its
address when invoking span's constructor. So we end up with an instance
that points to garbage instead of a_vec's storage.

As per Jason's suggestion, this patch simply removes the calls to
mark_*_use from perform_implicit_conversion_flags, which fixes the PR.

PR c++/117504

gcc/cp/ChangeLog:

* call.cc (perform_implicit_conversion_flags): Don't call
mark_{l,r}value_use.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-117504.C: New test.
* g++.dg/cpp2a/constexpr-117504a.C: New test.
gcc/cp/call.cc
gcc/testsuite/g++.dg/cpp2a/constexpr-117504.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/constexpr-117504a.C [new file with mode: 0644]