Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
P2748R5 makes it ill-formed to return a reference to temporary in C++26; implementing this is a simple matter of changing the existing warning to a permerror. For most of the tests I just changed dg-warning to dg-message to accept both; I test the specific diagnostic type in Wreturn-local-addr-5.C. gcc/cp/ChangeLog: * typeck.cc (maybe_warn_about_returning_address_of_local): Permerror in C++26. gcc/testsuite/ChangeLog: * g++.dg/conversion/pr16333.C: Change dg-warning to dg-message. * g++.dg/cpp0x/constexpr-48324.C * g++.dg/other/pr94326.C * g++.dg/warn/Wreturn-local-addr-2.C * g++.old-deja/g++.jason/warning8.C: Likewise. * g++.dg/cpp1y/auto-fn6.C: Check that others don't complain. * g++.dg/warn/Wreturn-local-addr-5.C: Expect error in C++26. --- gcc/cp/typeck.cc | 6 ++++-- gcc/testsuite/g++.dg/conversion/pr16333.C | 2 +- gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C | 2 +- gcc/testsuite/g++.dg/cpp1y/auto-fn6.C | 8 ++++---- gcc/testsuite/g++.dg/other/pr94326.C | 2 +- gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C | 4 ++-- gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C | 3 ++- gcc/testsuite/g++.old-deja/g++.jason/warning8.C | 2 +- 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index f5a0a2273be..88ed38e4f30 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -10626,8 +10626,10 @@ maybe_warn_about_returning_address_of_local (tree retval, location_t loc) || TREE_CODE (whats_returned) == TARGET_EXPR) { if (TYPE_REF_P (valtype)) - warning_at (loc, OPT_Wreturn_local_addr, - "returning reference to temporary"); + /* P2748 made this an error in C++26. */ + emit_diagnostic (cxx_dialect >= cxx26 ? DK_PERMERROR : DK_WARNING, + loc, OPT_Wreturn_local_addr, + "returning reference to temporary"); else if (TYPE_PTR_P (valtype)) warning_at (loc, OPT_Wreturn_local_addr, "returning pointer to temporary"); diff --git a/gcc/testsuite/g++.dg/conversion/pr16333.C b/gcc/testsuite/g++.dg/conversion/pr16333.C index a00bc5c167c..d0049304790 100644 --- a/gcc/testsuite/g++.dg/conversion/pr16333.C +++ b/gcc/testsuite/g++.dg/conversion/pr16333.C @@ -6,5 +6,5 @@ struct X { int a[3]; X foo1 () { return a; } -const X &foo2 () { return a; } // { dg-warning "returning reference to temporary" } +const X &foo2 () { return a; } // { dg-message "returning reference to temporary" } X &foo3 () { return a; } // { dg-error "cannot bind non-const lvalue ref" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C index 37ed0e1d163..f53fd4ddbd3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C @@ -7,7 +7,7 @@ struct S { }; constexpr const int& to_ref(int i) { - return S(i).val; // { dg-warning "reference to temporary" } + return S(i).val; // { dg-message "reference to temporary" } } constexpr int ary[to_ref(98)] = { }; // { dg-error "25:size of array .ary. is not an integral" } diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C index 17ca6f22c50..7fada180841 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C @@ -8,11 +8,11 @@ char& g(char); double&& g(double); template <class T> auto&& f(T t) -{ return g(t); } // { dg-warning "reference to temporary" } +{ return g(t); } // { dg-message "reference to temporary" } int main() { - ST<decltype(f(1)),int&&>(); - ST<decltype(f('\0')),char&>(); - ST<decltype(f(1.0)),double&&>(); + ST<decltype(f(1)),int&&>(); // { dg-message "required from here" } + ST<decltype(f('\0')),char&>(); // { dg-bogus "required from here" } + ST<decltype(f(1.0)),double&&>(); // { dg-bogus "required from here" } } diff --git a/gcc/testsuite/g++.dg/other/pr94326.C b/gcc/testsuite/g++.dg/other/pr94326.C index 4069c038d52..5df72a648fd 100644 --- a/gcc/testsuite/g++.dg/other/pr94326.C +++ b/gcc/testsuite/g++.dg/other/pr94326.C @@ -3,7 +3,7 @@ // { dg-options "-fcompare-debug" } template <typename = int> struct A { - const int &foo() { return 0; } // { dg-warning "returning reference to temporary" } + const int &foo() { return 0; } // { dg-message "returning reference to temporary" } template <typename _Kt> void bar(_Kt) { foo(); } }; struct B { diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C index c483601e6b2..a9f984c153d 100644 --- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C +++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C @@ -3,9 +3,9 @@ struct Base2 { int m_foo; }; struct Derived2 : public Base2 {}; -const Base2& f8() { return Derived2(); } // { dg-warning "reference to temporary" } +const Base2& f8() { return Derived2(); } // { dg-message "reference to temporary" } struct foo { }; struct bar { foo base; }; -const foo& f9() { return bar().base; } // { dg-warning "reference to temporary" } +const foo& f9() { return bar().base; } // { dg-message "reference to temporary" } diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C index 76096279a64..69f1e682363 100644 --- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C +++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C @@ -5,4 +5,5 @@ int&& f() { int i = 0; return std::move(i); } // { dg-warning "reference to local variable" } int&& g() { int i = 0; return std::forward<int>(i); } // { dg-warning "reference to local variable" } -int&& h() { long l = 0; return std::forward<int>(l); } // { dg-warning "reference to temporary" } +int&& h() { long l = 0; return std::forward<int>(l); } // { dg-warning "reference to temporary" "" { target { ! c++26 } } } +// { dg-error "reference to temporary" "" { target c++26 } .-1 } diff --git a/gcc/testsuite/g++.old-deja/g++.jason/warning8.C b/gcc/testsuite/g++.old-deja/g++.jason/warning8.C index b5ff3f3de60..23830716ab4 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/warning8.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/warning8.C @@ -13,5 +13,5 @@ struct B { const B& f () { A a; - return a; // { dg-warning "" } returning reference to temporary + return a; // { dg-message "" } returning reference to temporary } base-commit: d28ea8e5a70474cf9d28bf0c008092c936ad1358 -- 2.44.0