diff mbox series

[v2] c++: Fix crash during NRV optimization with invalid input [PR117099, PR117129]

Message ID 010201929ae34be2-65ab82c7-d542-481d-959d-05fac1213d0c-000000@eu-west-1.amazonses.com
State New
Headers show
Series [v2] c++: Fix crash during NRV optimization with invalid input [PR117099, PR117129] | expand

Commit Message

Simon Martin Oct. 17, 2024, 2:30 p.m. UTC
Hi,

The issue reported in PR117129 is pretty similar to the one in PR117099,

so here’s an updated version of the patch that fixes both issues, by
ensuring that finish_return_expr sets current_function_return_value to
error_mark_node in case of error with said return value.

Successfully tested on x86_64-pc-linux-gnu. OK for trunk?

Thanks, Simon
From ff01d18d97893ef65259f9063794945d5062cf4e Mon Sep 17 00:00:00 2001
From: Simon Martin <simon@nasilyan.com>
Date: Wed, 16 Oct 2024 15:47:12 +0200
Subject: [PATCH] c++: Fix crash during NRV optimization with invalid input [PR117099, PR117129]

PR117099 and PR117129 are ICEs upon invalid code that happen when NRVO
is activated, and both due to the fact that we don't consistently set
current_function_return_value to error_mark_node upon error in
finish_return_expr.

This patch fixes this inconsistency which fixes both cases since we skip
calling finalize_nrv when current_function_return_value is
error_mark_node.

Successfully tested on x86_64-pc-linux-gnu.

	PR c++/117099
	PR c++/117129

gcc/cp/ChangeLog:

	* typeck.cc (check_return_expr): Upon error, set
	current_function_return_value to error_mark_node.

gcc/testsuite/ChangeLog:

	* g++.dg/parse/crash77.C: New test.
	* g++.dg/parse/crash78.C: New test.

---
 gcc/cp/typeck.cc                     | 11 ++++++++---
 gcc/testsuite/g++.dg/parse/crash77.C | 14 ++++++++++++++
 gcc/testsuite/g++.dg/parse/crash78.C | 15 +++++++++++++++
 3 files changed, 37 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/crash77.C
 create mode 100644 gcc/testsuite/g++.dg/parse/crash78.C
diff mbox series

Patch

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 71d879abef1..485e8b347bb 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11232,8 +11232,9 @@  check_return_expr (tree retval, bool *no_warning, bool *dangling)
       if (functype != error_mark_node)
 	permerror (input_location, "return-statement with no value, in "
 		   "function returning %qT", valtype);
-      /* Remember that this function did return.  */
+      /* Remember that this function returns an error.  */
       current_function_returns_value = 1;
+      retval = error_mark_node;
       /* And signal caller that TREE_NO_WARNING should be set on the
 	 RETURN_EXPR to avoid control reaches end of non-void function
 	 warnings in tree-cfg.cc.  */
@@ -11442,9 +11443,13 @@  check_return_expr (tree retval, bool *no_warning, bool *dangling)
 	   tf_warning_or_error);
       retval = convert (valtype, retval);
 
-      /* If the conversion failed, treat this just like `return;'.  */
+      /* If the conversion failed, treat this just like
+	 `return <ERROR>;'.  */
       if (retval == error_mark_node)
-	return retval;
+	{
+	  current_function_return_value = error_mark_node;
+	  return retval;
+	}
       /* We can't initialize a register from a AGGR_INIT_EXPR.  */
       else if (! cfun->returns_struct
 	       && TREE_CODE (retval) == TARGET_EXPR
diff --git a/gcc/testsuite/g++.dg/parse/crash77.C b/gcc/testsuite/g++.dg/parse/crash77.C
new file mode 100644
index 00000000000..8c3dddc13d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash77.C
@@ -0,0 +1,14 @@ 
+// PR c++/117099
+// { dg-do "compile" }
+
+struct X {
+  ~X();
+};
+
+X test(bool b) {
+  {
+    X x;
+    return x;
+  } 
+  if (!(b)) return; // { dg-error "return-statement with no value" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/crash78.C b/gcc/testsuite/g++.dg/parse/crash78.C
new file mode 100644
index 00000000000..08d62af39c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash78.C
@@ -0,0 +1,15 @@ 
+// PR c++/117129
+// { dg-do "compile" { target c++11 } }
+
+struct Noncopyable {
+  Noncopyable();
+  Noncopyable(const Noncopyable &) = delete; // { dg-note "declared here" }
+  virtual ~Noncopyable();
+};
+Noncopyable nrvo() { 
+  {
+    Noncopyable A;
+    return A; // { dg-error "use of deleted function" }
+	      // { dg-note "display considered" "" { target *-*-* } .-1 }
+  }
+}