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.
This commit is contained in:
parent
5821f5c8c8
commit
f31b72b75e
4 changed files with 59 additions and 1 deletions
|
@ -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
|
||||
|
|
15
gcc/testsuite/g++.dg/parse/crash78.C
Normal file
15
gcc/testsuite/g++.dg/parse/crash78.C
Normal file
|
@ -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" }
|
||||
}
|
22
gcc/testsuite/g++.dg/parse/crash78a.C
Normal file
22
gcc/testsuite/g++.dg/parse/crash78a.C
Normal file
|
@ -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;
|
||||
}
|
15
gcc/testsuite/g++.dg/parse/crash79.C
Normal file
15
gcc/testsuite/g++.dg/parse/crash79.C
Normal file
|
@ -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 }
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue