On Wed, Nov 08, 2017 at 05:42:07PM +0100, Marek Polacek wrote: > > Not sure about the COND_EXPR/VEC_COND_EXPR cases, right now I'm passing > > false as LVAL for the first operand (condition) and lval as LVAL for the > > other two (i.e. if called with lval == true on the whole *_COND_EXPR > > decl_constant_value_for_optimization etc. isn't performed on op1/op2, while > > without it it is). Can one take address of the whole COND_EXPR, or > > have it on LHS of anything in C? > > I don't think so, the ?: operator does not yield an lvalue.
Ok, I'll pass false then. > > @@ -218,12 +235,51 @@ c_fully_fold_internal (tree expr, bool i > > op2 = TREE_OPERAND (expr, 2); > > op3 = TREE_OPERAND (expr, 3); > > op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, > > - maybe_const_itself, for_int_const); > > + maybe_const_itself, for_int_const, lval); > > STRIP_TYPE_NOPS (op0); > > op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, > > - maybe_const_itself, for_int_const); > > + maybe_const_itself, for_int_const, false); > > STRIP_TYPE_NOPS (op1); > > - op1 = decl_constant_value_for_optimization (op1); > > + /* Fold "foo"[2] in initializers. */ > > + if (!lval > > + && in_init > > + && TREE_CODE (op0) == STRING_CST > > + && TREE_CODE (op1) == INTEGER_CST > > + && TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE > > Does this also handle 2["foobar"]? Yes, because build_array_ref has: 2607 if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE 2608 && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE 2609 /* Allow vector[index] but not index[vector]. */ 2610 && !VECTOR_TYPE_P (TREE_TYPE (array))) 2611 { 2612 if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE 2613 && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) 2614 { 2615 error_at (loc, 2616 "subscripted value is neither array nor pointer nor vector"); 2617 2618 return error_mark_node; 2619 } 2620 std::swap (array, index); 2621 swapped = true; 2622 } > > + && tree_fits_uhwi_p (op1)) > > + { > > + tree ary = op0; > > + tree index = op1; > > + unsigned len = 0; > > + tree elem_type = TREE_TYPE (TREE_TYPE (ary)); > > + unsigned elem_nchars = (TYPE_PRECISION (elem_type) > > + / TYPE_PRECISION (char_type_node)); > > + len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars; > > + > > + tree nelts = array_type_nelts (TREE_TYPE (ary)); > > + bool dummy1 = true, dummy2 = true; > > + nelts = c_fully_fold_internal (nelts, in_init, &dummy1, &dummy2, > > + for_int_const, false); > > + unsigned HOST_WIDE_INT i = tree_to_uhwi (index); > > + if (tree_int_cst_le (index, nelts) > > + && i < len > > + && i + elem_nchars <= len) > > + { > > + tree type = TREE_TYPE (expr); > > + if (elem_nchars == 1) > > + ret = build_int_cst (type, > > + TREE_STRING_POINTER (ary)[i]); > > + else > > + { > > + const unsigned char *ptr > > + = ((const unsigned char *)TREE_STRING_POINTER (ary) > > + + i * elem_nchars); > > + ret = native_interpret_expr (type, ptr, elem_nchars); > > + } > > + if (ret) > > + goto out; > > + } > > + } > > So this code comes from gimple-fold.c? I would probably move it to a new > function. No, this comes from very simplified cp/constexpr.c (extract_string_elt, cxx_eval_array_reference). Can outline it into a separate function, sure. Jakub