[pushed] c++: C++26 returning reference to temporary

Message ID 20240401160359.506977-1-jason@redhat.com
State Committed
Commit bba118db3f63cb1e3953a014aa3ac2ad89908950
Headers
Series [pushed] c++: C++26 returning reference to temporary |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm warning Patch is already merged
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch is already merged

Commit Message

Jason Merrill April 1, 2024, 4:02 p.m. UTC
  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(-)


base-commit: d28ea8e5a70474cf9d28bf0c008092c936ad1358
  

Patch

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
 }