https://gcc.gnu.org/g:f31b72b75ef7cde61469c774162db7b1cc4c3d03

commit r15-4959-gf31b72b75ef7cde61469c774162db7b1cc4c3d03
Author: Simon Martin <si...@nasilyan.com>
Date:   Tue Nov 5 10:44:34 2024 +0100

    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.
    
            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/crash78.C: New test.
            * g++.dg/parse/crash78a.C: New test.
            * g++.dg/parse/crash79.C: New test.

Diff:
---
 gcc/cp/typeck.cc                      |  8 +++++++-
 gcc/testsuite/g++.dg/parse/crash78.C  | 15 +++++++++++++++
 gcc/testsuite/g++.dg/parse/crash78a.C | 22 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/parse/crash79.C  | 15 +++++++++++++++
 4 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 439681216bed..4c15e26f692a 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11239,6 +11239,8 @@ check_return_expr (tree retval, bool *no_warning, bool 
*dangling)
                   "function returning %qT", valtype);
       /* Remember that this function did return.  */
       current_function_returns_value = 1;
+      /* But suppress NRV  .*/
+      current_function_return_value = 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.  */
@@ -11449,7 +11451,11 @@ check_return_expr (tree retval, bool *no_warning, bool 
*dangling)
 
       /* If the conversion failed, treat this just like `return;'.  */
       if (retval == error_mark_node)
-       return retval;
+       {
+         /* And suppress NRV.  */
+         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/crash78.C 
b/gcc/testsuite/g++.dg/parse/crash78.C
new file mode 100644
index 000000000000..f30fe08df54b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash78.C
@@ -0,0 +1,15 @@
+// PR c++/117099
+// { dg-do "compile" }
+
+struct X {
+  ~X();
+};
+
+X test(bool b) {
+  {
+    X x;
+    return x;
+  }
+  return X();
+  if (!(b)) return; // { dg-error "return-statement with no value" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/crash78a.C 
b/gcc/testsuite/g++.dg/parse/crash78a.C
new file mode 100644
index 000000000000..241a5e390dee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash78a.C
@@ -0,0 +1,22 @@
+// PR c++/117099
+// With -fpermissive, make sure we don't do NRV in this case, but keep
+// executing fine. Note that the return at line 16 is undefined behaviour.
+// { dg-do "run" }
+// { dg-options "-fpermissive" }
+
+struct X {
+  ~X() {}
+};
+
+X test(bool b) {
+  X x;
+  if (b)
+    return x;
+  else
+    return; // { dg-warning "return-statement with no value" }
+}
+
+int main(int, char*[]) {
+  (void) test (false);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/parse/crash79.C 
b/gcc/testsuite/g++.dg/parse/crash79.C
new file mode 100644
index 000000000000..08d62af39c62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash79.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 }
+  }
+}

Reply via email to