This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Add LVAL argument to c_fully_fold* and propagate it through (PR c/66618, PR c/69960)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Marek Polacek <polacek at redhat dot com>
- Cc: "Joseph S. Myers" <joseph at codesourcery dot com>, gcc-patches at gcc dot gnu dot org
- Date: Wed, 8 Nov 2017 18:03:14 +0100
- Subject: Re: [PATCH] Add LVAL argument to c_fully_fold* and propagate it through (PR c/66618, PR c/69960)
- Authentication-results: sourceware.org; auth=none
- References: <20171108162245.GV14653@tucnak> <20171108164207.GI1743@redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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