Hi! The comment says that trying to fold VOID_TYPE_P COND_EXPRs is not worth bothering, but as the following testcase shows, that is not the case. fold_ternary can optimize COND_EXPRs where the condition is constant and the unused branch doesn't have any labels, and not folding it early means bogus warnings afterwards.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-11-24 Jakub Jelinek <ja...@redhat.com> PR c++/81675 * cp-gimplify.c (cp_fold) <case COND_EXPR>: Don't return immediately for VOID_TYPE_P COND_EXPRs, instead fold the operands and if op0 is INTEGER_CST, ensure that both op1 and op2 are non-NULL and fall through into normal folding, otherwise just rebuild x if any op changed. * g++.dg/warn/pr81675.C: New test. --- gcc/cp/cp-gimplify.c.jj 2017-11-21 20:23:01.000000000 +0100 +++ gcc/cp/cp-gimplify.c 2017-11-24 11:09:51.879647584 +0100 @@ -2299,13 +2299,6 @@ cp_fold (tree x) case VEC_COND_EXPR: case COND_EXPR: - - /* Don't bother folding a void condition, since it can't produce a - constant value. Also, some statement-level uses of COND_EXPR leave - one of the branches NULL, so folding would crash. */ - if (VOID_TYPE_P (TREE_TYPE (x))) - return x; - loc = EXPR_LOCATION (x); op0 = cp_fold_rvalue (TREE_OPERAND (x, 0)); op1 = cp_fold (TREE_OPERAND (x, 1)); @@ -2319,6 +2312,29 @@ cp_fold (tree x) if (!VOID_TYPE_P (TREE_TYPE (op2))) op2 = cp_truthvalue_conversion (op2); } + else if (VOID_TYPE_P (TREE_TYPE (x))) + { + if (TREE_CODE (op0) == INTEGER_CST) + { + /* If the condition is constant, fold can fold away + the COND_EXPR. If some statement-level uses of COND_EXPR + have one of the branches NULL, avoid folding crash. */ + if (!op1) + op1 = build_empty_stmt (loc); + if (!op2) + op2 = build_empty_stmt (loc); + } + else + { + /* Otherwise, don't bother folding a void condition, since + it can't produce a constant value. */ + if (op0 != TREE_OPERAND (x, 0) + || op1 != TREE_OPERAND (x, 1) + || op2 != TREE_OPERAND (x, 2)) + x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2); + break; + } + } if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1) --- gcc/testsuite/g++.dg/warn/pr81675.C.jj 2017-11-24 11:12:13.962912829 +0100 +++ gcc/testsuite/g++.dg/warn/pr81675.C 2017-11-24 11:11:56.000000000 +0100 @@ -0,0 +1,15 @@ +// PR c++/81675 +// { dg-do compile } +// { dg-options "-Wall" } + +struct S +{ + ~S () __attribute__((noreturn)); + int a; +}; + +int +foo () +{ + false ? 5 : S ().a; +} Jakub