Am Montag, den 18.10.2021, 12:35 -0400 schrieb Jason Merrill: > On 10/17/21 09:52, Uecker, Martin wrote: > > > > Here is the 4th version of the patch. I tried to implement > > Jason's suggestion and this also fixes the problem. But > > I am not sure I understand the condition on > > the TREE_SIDE_EFFECTS ... > > Checking TREE_SIDE_EFFECTS filters out many trivial cases that we don't > need to worry about.
Yes, but are we sure there are always side effects in the cases we care about? I assume that the problematic case are only those where the size expression depends on a variable and then there was a write to one.. But I am not sure. > I think we also want to check > variably_modified_type_p, which ought to avoid the OMP problem below. I don't think so because the problem below involves VM types. Martin > > And there is now another problem: > > > > c_finish_omp_for in c-family/c-omp.c does not seem > > to understand the expressions anymore and I get a test > > failure in > > > > testsuite/c-c++-common/gomp/for-5.c > > > > where I now get an "invalid increment expression" > > instead of the expected error. > > (bootstrapping and all other tests work fine) > > > > > > Martin > > > > > > > > > > Fix ICE when mixing VLAs and statement expressions [PR91038] > > > > When returning VM-types from statement expressions, this can > > lead to an ICE when declarations from the statement expression > > are referred to later. Most of these issues can be addressed by > > gimplifying the base expression earlier in gimplify_compound_lval. > > > > Another issue is fixed by adding SAVE_EXPRs in pointer_int_sum > > in the FE to force a correct order of evaluation. This fixes > > PR91038 and some of the test cases from PR29970 (structs with > > VLA members need further work). > > > > > > 2021-08-01 Martin Uecker <muec...@gwdg.de> > > > > 2021-08-01 Martin Uecker <muec...@gwdg.de> > > > > gcc/ > > PR c/91038 > > PR c/29970 > > > > * gimplify.c (gimplify_var_or_parm_decl): Update comment. > > (gimplify_compound_lval): > > Gimplify base expression first. > > (gimplify_target_expr): Add comment. > > * c-family/c- > > common.c (pointer_int_sum): Wrap pointer > > operand in SAVE_EXPR and also it to the integer > > argument. > > > > gcc/testsuite/ > > PR c/91038 > > PR c/29970 > > * gcc.dg/vla-stexp-3.c: > > New test. > > * gcc.dg/vla-stexp-4.c: New test. > > * gcc.dg/vla-stexp-5.c: New test. > > * > > gcc.dg/vla-stexp-6.c: New test. > > * gcc.dg/vla-stexp-7.c: New test. > > * gcc.dg/vla-stexp- > > 8.c: New test. > > * gcc.dg/vla-stexp-9.c: New test. > > > > > > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c > > index 9d19e352725..522085664f5 100644 > > --- a/gcc/c-family/c-common.c > > +++ b/gcc/c-family/c-common.c > > @@ -3348,6 +3348,16 @@ pointer_int_sum (location_t loc, enum tree_code > > resultcode, > > intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype), > > TYPE_UNSIGNED (sizetype)), intop); > > > > + /* Wrap the pointer expression in a SAVE_EXPR to make sure it > > + * is evaluated first because the size expression may depend on it > > + * for VM types. > > + */ > > We usually don't give the trailing */ its own line. > > > + if (TREE_SIDE_EFFECTS (size_exp)) > > + { > > + ptrop = build1_loc (loc, SAVE_EXPR, TREE_TYPE (ptrop), ptrop); > > Why not use the save_expr function? > > > + intop = build2 (COMPOUND_EXPR, TREE_TYPE (intop), ptrop, intop); > > + } > > + > > /* Replace the integer argument with a suitable product by the object > > size. > > Do this multiplication as signed, then convert to the appropriate > > type > > for the pointer operation and disregard an overflow that occurred > > only > > diff --git a/gcc/gimplify.c b/gcc/gimplify.c > > index d8e4b139349..be5b00b6716 100644 > > --- a/gcc/gimplify.c > > +++ b/gcc/gimplify.c > > @@ -2958,7 +2958,10 @@ gimplify_var_or_parm_decl (tree *expr_p) > > declaration, for which we've already issued an error. It would > > be really nice if the front end wouldn't leak these at all. > > Currently the only known culprit is C++ destructors, as seen > > - in g++.old-deja/g++.jason/binding.C. */ > > + in g++.old-deja/g++.jason/binding.C. > > + Another possible culpit are size expressions for variably modified > > + types which are lost in the FE or not gimplified correctly. > > + */ > > As above. > > > if (VAR_P (decl) > > && !DECL_SEEN_IN_BIND_EXPR_P (decl) > > && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl) > > @@ -3103,16 +3106,22 @@ gimplify_compound_lval (tree *expr_p, gimple_seq > > *pre_p, gimple_seq > > *post_p, > > expression until we deal with any variable bounds, sizes, or > > positions in order to deal with PLACEHOLDER_EXPRs. > > > > - So we do this in three steps. First we deal with the annotations > > - for any variables in the components, then we gimplify the base, > > - then we gimplify any indices, from left to right. */ > > + The base expression may contain a statement expression that > > + has declarations used in size expressions, so has to be > > + gimplified before gimplifying the size expressions. > > + > > + So we do this in three steps. First we deal with variable > > + bounds, sizes, and positions, then we gimplify the base, > > + then we deal with the annotations for any variables in the > > + components and any indices, from left to right. */ > > + > > for (i = expr_stack.length () - 1; i >= 0; i--) > > { > > tree t = expr_stack[i]; > > > > if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) > > { > > - /* Gimplify the low bound and element type size and put them into > > + /* Deal with the low bound and element type size and put them into > > the ARRAY_REF. If these values are set, they have already been > > gimplified. */ > > if (TREE_OPERAND (t, 2) == NULL_TREE) > > @@ -3121,18 +3130,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq > > *pre_p, gimple_seq > > *post_p, > > if (!is_gimple_min_invariant (low)) > > { > > TREE_OPERAND (t, 2) = low; > > - tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, > > - post_p, is_gimple_reg, > > - fb_rvalue); > > - ret = MIN (ret, tret); > > } > > } > > - else > > - { > > - tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, > > - is_gimple_reg, fb_rvalue); > > - ret = MIN (ret, tret); > > - } > > > > if (TREE_OPERAND (t, 3) == NULL_TREE) > > { > > @@ -3149,18 +3148,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq > > *pre_p, gimple_seq > > *post_p, > > elmt_size, factor); > > > > TREE_OPERAND (t, 3) = elmt_size; > > - tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, > > - post_p, is_gimple_reg, > > - fb_rvalue); > > - ret = MIN (ret, tret); > > } > > } > > - else > > - { > > - tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p, > > - is_gimple_reg, fb_rvalue); > > - ret = MIN (ret, tret); > > - } > > } > > else if (TREE_CODE (t) == COMPONENT_REF) > > { > > @@ -3180,18 +3169,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq > > *pre_p, gimple_seq > > *post_p, > > offset, factor); > > > > TREE_OPERAND (t, 2) = offset; > > - tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, > > - post_p, is_gimple_reg, > > - fb_rvalue); > > - ret = MIN (ret, tret); > > } > > } > > - else > > - { > > - tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, > > - is_gimple_reg, fb_rvalue); > > - ret = MIN (ret, tret); > > - } > > } > > } > > > > @@ -3202,21 +3181,34 @@ gimplify_compound_lval (tree *expr_p, gimple_seq > > *pre_p, gimple_seq > > *post_p, > > fallback | fb_lvalue); > > ret = MIN (ret, tret); > > > > - /* And finally, the indices and operands of ARRAY_REF. During this > > - loop we also remove any useless conversions. */ > > + /* Step 3: gimplify size expressions and the indices and operands of > > + ARRAY_REF. During this loop we also remove any useless conversions. > > */ > > + > > for (; expr_stack.length () > 0; ) > > { > > tree t = expr_stack.pop (); > > > > if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) > > { > > + /* Gimplify the low bound and element type size. */ > > + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, > > + is_gimple_reg, fb_rvalue); > > + ret = MIN (ret, tret); > > + > > + tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p, > > + is_gimple_reg, fb_rvalue); > > + ret = MIN (ret, tret); > > + > > /* Gimplify the dimension. */ > > - if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))) > > - { > > - tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p, > > - is_gimple_val, fb_rvalue); > > - ret = MIN (ret, tret); > > - } > > + tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p, > > + is_gimple_val, fb_rvalue); > > + ret = MIN (ret, tret); > > + } > > + else if (TREE_CODE (t) == COMPONENT_REF) > > + { > > + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, > > + is_gimple_reg, fb_rvalue); > > + ret = MIN (ret, tret); > > } > > > > STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0)); > > @@ -6914,6 +6906,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq > > *pre_p, gimple_seq *post_p) > > { > > if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp))) > > gimplify_type_sizes (TREE_TYPE (temp), pre_p); > > + /* FIXME: this is correct only when the size of the type does > > + not depend on expressions evaluated in init. */ > > gimplify_vla_decl (temp, pre_p); > > } > > else > >