Here we're ICE'ing in do_narrow during error-recovery, because ocp_convert returns error_mark_node after it attempts to reduce a const decl to its erroneous DECL_INITIAL via scalar_constant_value, and we later pass this error_mark_node to fold_build2 which isn't prepared to handle error_mark_nodes.
We could fix this ICE in do_narrow by checking if ocp_convert returns error_mark_node, but for the sake of consistency and for better error recovery it seems it'd be better if ocp_convert didn't care that a const decl's initializer is erroneous and would instead proceed as if the decl was not const, which is the approach that this patch takes. Passes 'make check-c++', does this look OK to commit after full bootstrap and regtest? gcc/cp/ChangeLog: PR c++/94475 * cvt.c (ocp_convert): If the result of scalar_constant_value is erroneous, discard it and carry on with the original expression. gcc/testsuite/ChangeLog: PR c++/94475 * g++.dg/conversion/err-recover2.C: New test. * g++.dg/diagnostic/pr84138.C: Remove now-bogus warning. * g++.dg/warn/Wsign-compare-8.C: Remove now-bogus warning. --- gcc/cp/cvt.c | 6 +++--- gcc/testsuite/g++.dg/conversion/err-recover2.C | 10 ++++++++++ gcc/testsuite/g++.dg/diagnostic/pr84138.C | 2 +- gcc/testsuite/g++.dg/warn/Wsign-compare-8.C | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/conversion/err-recover2.C diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index a3b80968b33..b94231a6d08 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -723,10 +723,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags, if (!CLASS_TYPE_P (type)) { e = mark_rvalue_use (e); - e = scalar_constant_value (e); + tree v = scalar_constant_value (e); + if (!error_operand_p (v)) + e = v; } - if (error_operand_p (e)) - return error_mark_node; if (NULLPTR_TYPE_P (type) && null_ptr_cst_p (e)) { diff --git a/gcc/testsuite/g++.dg/conversion/err-recover2.C b/gcc/testsuite/g++.dg/conversion/err-recover2.C new file mode 100644 index 00000000000..437e1a919ea --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/err-recover2.C @@ -0,0 +1,10 @@ +// PR c++/94475 +// { dg-do compile } + +unsigned char +sr () +{ + const unsigned char xz = EI; // { dg-error "not declared" } + + return xz - (xz >> 1); +} diff --git a/gcc/testsuite/g++.dg/diagnostic/pr84138.C b/gcc/testsuite/g++.dg/diagnostic/pr84138.C index 5c48b9b164a..00352306a56 100644 --- a/gcc/testsuite/g++.dg/diagnostic/pr84138.C +++ b/gcc/testsuite/g++.dg/diagnostic/pr84138.C @@ -5,4 +5,4 @@ foo() { const int i = 0 = 0; // { dg-error "lvalue required as left operand" } return 1 ? 0 : (char)i; -} // { dg-warning "control reaches" } +} diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-8.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-8.C index 237ba84d526..4d2688157fc 100644 --- a/gcc/testsuite/g++.dg/warn/Wsign-compare-8.C +++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-8.C @@ -5,4 +5,4 @@ bool foo (char c) { const int i = 0 = 0; // { dg-error "lvalue" } return c = i; -} // { dg-warning "control reaches" } +} -- 2.26.1.107.gefe3874640