In this testcase, we refer to the a parameter through a reference in its own member, which we asserted couldn't happen by marking the parameter as 'restrict'. This assumption could also be broken if the address escapes from the constructor.
Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/97474 * call.c (type_passed_as): Don't mark invisiref restrict. gcc/testsuite/ChangeLog: PR c++/97474 * g++.dg/torture/pr97474.C: New test. --- gcc/cp/call.c | 6 +----- gcc/testsuite/g++.dg/torture/pr97474.C | 28 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr97474.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5977582e279..87a7af12796 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8263,11 +8263,7 @@ type_passed_as (tree type) { /* Pass classes with copy ctors by invisible reference. */ if (TREE_ADDRESSABLE (type)) - { - type = build_reference_type (type); - /* There are no other pointers to this temporary. */ - type = cp_build_qualified_type (type, TYPE_QUAL_RESTRICT); - } + type = build_reference_type (type); else if (targetm.calls.promote_prototypes (NULL_TREE) && INTEGRAL_TYPE_P (type) && COMPLETE_TYPE_P (type) diff --git a/gcc/testsuite/g++.dg/torture/pr97474.C b/gcc/testsuite/g++.dg/torture/pr97474.C new file mode 100644 index 00000000000..6ce117e43a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr97474.C @@ -0,0 +1,28 @@ +// PR c++/97474 +// { dg-do run } + +extern "C" int printf (const char *, ...); +extern "C" void abort (); + +struct A { + int a; + int& b; + + A(int x) : a(x), b(a) {} + A(const A& other) : a(other.a), b(a) {} + A() : a(0), b(a) {} +}; + +int foo(A a) { + a.a *= a.b; + return a.b; +} + + +int main() { + A a(3); + + int r = foo (a); + if (r != 9) + abort (); +} base-commit: a4dfd0f089af33f2af57bf422f9859405b9b4a16 -- 2.27.0