https://gcc.gnu.org/g:486c32501aafce188649da2c234229dfbd2fd202
commit r12-11255-g486c32501aafce188649da2c234229dfbd2fd202 Author: Jakub Jelinek <ja...@redhat.com> Date: Mon Jul 7 09:51:51 2025 +0200 Revert "c++: Fix up cp_build_array_ref COND_EXPR handling [PR120471]" This reverts commit b5f0faa4eb71650a9dde3938c3a98eda710534de. Diff: --- gcc/cp/typeck.cc | 130 ++-------------------------------- gcc/testsuite/g++.dg/parse/pr120471.C | 42 ----------- gcc/testsuite/g++.dg/ubsan/pr120471.C | 21 ------ 3 files changed, 7 insertions(+), 186 deletions(-) diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 19dfaf18928f..89ff595ec513 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -3811,129 +3811,13 @@ cp_build_array_ref (location_t loc, tree array, tree idx, } case COND_EXPR: - tree op0, op1, op2; - op0 = TREE_OPERAND (array, 0); - op1 = TREE_OPERAND (array, 1); - op2 = TREE_OPERAND (array, 1); - if (TREE_SIDE_EFFECTS (idx) || !tree_invariant_p (idx)) - { - /* If idx could possibly have some SAVE_EXPRs, turning - (op0 ? op1 : op2)[idx] into - op0 ? op1[idx] : op2[idx] can lead into temporaries - initialized in one conditional path and uninitialized - uses of them in the other path. - And if idx is a really large expression, evaluating it - twice is also not optimal. - On the other side, op0 must be sequenced before evaluation - of op1 and op2 and for C++17 op0, op1 and op2 must be - sequenced before idx. - If idx is INTEGER_CST, we can just do the optimization - without any SAVE_EXPRs, if op1 and op2 are both ARRAY_TYPE - VAR_DECLs or COMPONENT_REFs thereof (so their address - is constant or relative to frame), optimize into - (SAVE_EXPR <op0>, SAVE_EXPR <idx>, SAVE_EXPR <op0>) - ? op1[SAVE_EXPR <idx>] : op2[SAVE_EXPR <idx>] - Otherwise avoid this optimization. */ - if (flag_strong_eval_order == 2) - { - if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) - { - tree xop1 = op1; - tree xop2 = op2; - while (xop1 && handled_component_p (xop1)) - { - switch (TREE_CODE (xop1)) - { - case ARRAY_REF: - case ARRAY_RANGE_REF: - if (!tree_invariant_p (TREE_OPERAND (xop1, 1)) - || TREE_OPERAND (xop1, 2) != NULL_TREE - || TREE_OPERAND (xop1, 3) != NULL_TREE) - { - xop1 = NULL_TREE; - continue; - } - break; - - case COMPONENT_REF: - if (TREE_OPERAND (xop1, 2) != NULL_TREE) - { - xop1 = NULL_TREE; - continue; - } - break; - - default: - break; - } - xop1 = TREE_OPERAND (xop1, 0); - } - if (xop1) - STRIP_ANY_LOCATION_WRAPPER (xop1); - while (xop2 && handled_component_p (xop2)) - { - switch (TREE_CODE (xop2)) - { - case ARRAY_REF: - case ARRAY_RANGE_REF: - if (!tree_invariant_p (TREE_OPERAND (xop2, 1)) - || TREE_OPERAND (xop2, 2) != NULL_TREE - || TREE_OPERAND (xop2, 3) != NULL_TREE) - { - xop2 = NULL_TREE; - continue; - } - break; - - case COMPONENT_REF: - if (TREE_OPERAND (xop2, 2) != NULL_TREE) - { - xop2 = NULL_TREE; - continue; - } - break; - - default: - break; - } - xop2 = TREE_OPERAND (xop2, 0); - } - if (xop2) - STRIP_ANY_LOCATION_WRAPPER (xop2); - - if (!xop1 - || !xop2 - || !(CONSTANT_CLASS_P (xop1) - || decl_address_invariant_p (xop1)) - || !(CONSTANT_CLASS_P (xop2) - || decl_address_invariant_p (xop2))) - { - /* Force default conversion on array if - we can't optimize this and array is ARRAY_TYPE - COND_EXPR, we can't leave COND_EXPRs with - ARRAY_TYPE in the IL. */ - array = cp_default_conversion (array, complain); - if (error_operand_p (array)) - return error_mark_node; - break; - } - } - else if (!POINTER_TYPE_P (TREE_TYPE (array)) - || !tree_invariant_p (op1) - || !tree_invariant_p (op2)) - break; - } - if (TREE_SIDE_EFFECTS (idx)) - { - idx = save_expr (idx); - op0 = save_expr (op0); - tree tem = build_compound_expr (loc, op0, idx); - op0 = build_compound_expr (loc, tem, op0); - } - } - op1 = cp_build_array_ref (loc, op1, idx, complain); - op2 = cp_build_array_ref (loc, op2, idx, complain); - ret = build_conditional_expr (loc, op0, op1, op2, complain); + ret = build_conditional_expr + (loc, TREE_OPERAND (array, 0), + cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx, + complain), + cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx, + complain), + complain); protected_set_expr_location (ret, loc); return ret; diff --git a/gcc/testsuite/g++.dg/parse/pr120471.C b/gcc/testsuite/g++.dg/parse/pr120471.C deleted file mode 100644 index ad47e380404a..000000000000 --- a/gcc/testsuite/g++.dg/parse/pr120471.C +++ /dev/null @@ -1,42 +0,0 @@ -// PR c++/120471 -// { dg-do compile } - -extern int a1[], a2[], a3[], a4[]; - -int corge (int); - -int -foo (int p) -{ - return (p ? a1 : a2)[1]; -} - -int -bar (int p, int q) -{ - return (p ? a1 : a2)[q]; -} - -int -garply (int p, int q) -{ - return (p ? a1 : a2)[corge (q)]; -} - -int -baz (int p, int q) -{ - return (p ? q ? a1 : a2 : q ? a3 : a4)[1]; -} - -int -qux (int p, int q, int r) -{ - return (p ? q ? a1 : a2 : q ? a3 : a4)[r]; -} - -int -fred (int p, int q, int r) -{ - return (p ? q ? a1 : a2 : q ? a3 : a4)[corge (r)]; -} diff --git a/gcc/testsuite/g++.dg/ubsan/pr120471.C b/gcc/testsuite/g++.dg/ubsan/pr120471.C deleted file mode 100644 index 31b781f9aa7f..000000000000 --- a/gcc/testsuite/g++.dg/ubsan/pr120471.C +++ /dev/null @@ -1,21 +0,0 @@ -// PR c++/120471 -// { dg-do run } -// { dg-options "-fsanitize=undefined" } - -volatile int b[1], a[1]; - -void -foo (int x) -{ - volatile int c = 21; - volatile int v = (x % 2 ? b : a)[c % 3]; - if (v != 0) - __builtin_abort (); -} - -int -main () -{ - foo (1); - foo (2); -}