Am Donnerstag, den 23.09.2021, 17:37 -0400 schrieb Jason Merrill:
> On 9/23/21 15:49, Uecker, Martin wrote:
> > Am Mittwoch, den 22.09.2021, 17:18 -0400 schrieb Jason Merrill:
> > > On 9/5/21 15:14, Uecker, Martin wrote:
> > > > Here is the third version of the patch. This also
> > > > fixes the index zero case.  Thus, this should be
> > > > a complete fix for 91038 and should fix all cases
> > > > also supported by clang.  Still not working is
> > > > returning a struct of variable size from a
> > > > statement expression (29970) when the size depends
> > > > on computations inside the statement expression.
> > > > 
> > > > Bootstrapped and regression tested
> > > > on x86-64 for all languages.
> > > > 
> > > > 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 not reording some size-related expressions
> > > > during folding. 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>
> > > >       
> > > >       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): Do not gimplify size expression.
> > > >         * fold-const.c (fold_binary_loc): Do not reorder SAVE_EXPR
> > > >         in pointer arithmetic for variably modified types.
> > > >       
> > > >       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/fold-const.c b/gcc/fold-const.c
> > > > index ff23f12f33c..1e6f50692b5 100644
> > > > --- a/gcc/fold-const.c
> > > > +++ b/gcc/fold-const.c
> > > > @@ -10854,7 +10854,15 @@ fold_binary_loc (location_t loc, enum 
> > > > tree_code code, tree type,
> > > >           return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND 
> > > > (arg0, 0),
> > > >                              tem);
> > > >         }
> > > > -      if (TREE_CODE (arg1) == COMPOUND_EXPR)
> > > > +      /* This interleaves execution of the two sub-expressions
> > > > +        which is allowed in C.  For pointer arithmetic when the
> > > > +        the pointer has a variably modified type, the right expression
> > > > +        might have a SAVE_EXPR which depends on the left expr, so
> > > > +        do not fold in this case.  */
> > > > +      if (TREE_CODE (arg1) == COMPOUND_EXPR
> > > > +         && !(code == POINTER_PLUS_EXPR
> > > > +              && TREE_CODE (TREE_OPERAND (arg1, 0)) == SAVE_EXPR)
> > > > +              && variably_modified_type_p (type, NULL_TREE))
> > > 
> > > This seems pretty fragile.  If the problem is that the SAVE_EXPR depends
> > > on a statement-expr on the LHS, can't that happen with expressions other
> > > than POINTER_PLUS_EXPR?
> > 
> > I intentionally limited the change to this specific
> > case to avoid accidentally breaking or pessimizing
> > anything else. I did not notice any other cases that
> > need fixing. It is of course possible that
> > I have missed some...
> > 
> > > Maybe we should include the statement-expr in the SAVE_EXPR?
> > 
> > I am not really sure how to implement this.
> 
> Nor am I, I'm not at all familiar with the VLA handling code.  But if 
> the generated trees rely on evaluation happening with a stricter order 
> than is actually guaranteed, that seems like a bug in the generation of 
> the expression trees, not the folding code.

Is there a definition about what is guaranteed?

It seems to be based on the somewhat scary
C semantics where in

(a, b) op (c, d)

evaluation order could be

a, c, b, d.

If I remember correctly

({ int N; int x[N]; &x; })[0]

becomes

TARGET_EXPR <D, { int N; int x[N]; D = &x }> + (SAVE_EXPR <N> * 0)

which (somehow involving the rule above) becomes

SAVE_EXPR <N>; TARGET_EXPR <D, { int N; int x[N]; D = &x })

which then fails to gimplify.

It is not entirely clear to me what code the FE
should generate to avoid this.

> Could someone that knows more about VLA weigh in?

> > Maybe we could apply this patch first (because
> > I have to work around this bug in a couple of
> > projects which is a bit annoying)? I am happy
> > to implement an alternative later if there is
> > a better way (which I can understand).
> 
> The gimplify_compound_lval change is OK now.
> 
> What's the rationale for the gimplify_target_expr change?

It seems another case where size expressions are
gimplified earlier than expressions they might
depend
on.

But I can't seem to find a case anymore where this
change makes a difference.


Martin

> > > >         {
> > > >           tem = fold_build2_loc (loc, code, type, op0,
> > > >                              fold_convert_loc (loc, TREE_TYPE (op1),
> > > > diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> > > > index 99d1c7fcce4..8ee205f593c 100644
> > > > --- a/gcc/gimplify.c
> > > > +++ b/gcc/gimplify.c
> > > > @@ -2840,7 +2840,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.
> > > > +  */
> > > >      if (VAR_P (decl)
> > > >          && !DECL_SEEN_IN_BIND_EXPR_P (decl)
> > > >          && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
> > > > @@ -2985,16 +2988,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)
> > > > @@ -3003,18 +3012,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)
> > > >             {
> > > > @@ -3031,18 +3030,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)
> > > >         {
> > > > @@ -3062,18 +3051,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);
> > > > -           }
> > > >         }
> > > >        }
> > > >    
> > > > @@ -3084,21 +3063,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));
> > > > @@ -6766,8 +6758,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq 
> > > > *pre_p, gimple_seq
> > > > *post_p)
> > > >          to the temps list.  Handle also variable length TARGET_EXPRs.  
> > > > */
> > > >          if (!poly_int_tree_p (DECL_SIZE (temp)))
> > > >         {
> > > > -         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
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-3.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-3.c
> > > > new file mode 100644
> > > > index 00000000000..e663de1cd72
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-3.c
> > > > @@ -0,0 +1,11 @@
> > > > +/* PR91038 */
> > > > +/* { dg-do compile } */
> > > > +/* { dg-options "" } */
> > > > +
> > > > +
> > > > +void bar(void)
> > > > +{
> > > > +       ({ int N = 2; int (*x)[9][N] = 0; x; })[1];
> > > > +       ({ int N = 2; int (*x)[9][N] = 0; x; })[0];     // should not 
> > > > ice
> > > > +}
> > > > +
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-4.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-4.c
> > > > new file mode 100644
> > > > index 00000000000..612b5a802fc
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-4.c
> > > > @@ -0,0 +1,94 @@
> > > > +/* PR29970, PR91038 */
> > > > +/* { dg-do run } */
> > > > +/* { dg-options "-O0 -Wunused-variable" } */
> > > > +
> > > > +int foo3b(void)   // should not return 0
> > > > +{
> > > > +        int n = 0;
> > > > +        return sizeof *({ n = 10; int x[n]; &x; });
> > > > +}
> > > > +
> > > > +int foo4(void)   // should not ICE
> > > > +{
> > > > +        return (*({
> > > > +                        int n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +int foo5(void)   // should return 1, returns 0
> > > > +{
> > > > +        int n = 0;
> > > > +        return (*({
> > > > +                        n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +int foo5c(void)   // should return 400
> > > > +{
> > > > +        int n = 0;
> > > > +        return sizeof(*({
> > > > +                        n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }));
> > > > +}
> > > > +
> > > > +int foo5b(void)   // should return 1, returns 0
> > > > +{
> > > > +       int n = 0;                      /* { dg-warning "unused 
> > > > variable" } */
> > > > +        return (*({
> > > > +                        int n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +int foo5a(void)   // should return 1, returns 0
> > > > +{
> > > > +        return (*({
> > > > +                        int n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +
> > > > +
> > > > +
> > > > +int main()
> > > > +{
> > > > +       if (sizeof(int[10]) != foo3b())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo4())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (400 != foo5c())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo5a())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo5b()) // -O0
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo5())
> > > > +               __builtin_abort();
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-5.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-5.c
> > > > new file mode 100644
> > > > index 00000000000..d6a7f2b34b8
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-5.c
> > > > @@ -0,0 +1,30 @@
> > > > +/* PR29970 */
> > > > +/* { dg-do run } */
> > > > +/* { dg-options "-Wunused-variable" } */
> > > > +
> > > > +
> > > > +
> > > > +
> > > > +int foo2a(void)   // should not ICE
> > > > +{
> > > > +        return ({ int n = 20; struct { int x[n];} x; x.x[12] = 1; 
> > > > sizeof(x); });
> > > > +}
> > > > +
> > > > +
> > > > +int foo2b(void)   // should not ICE
> > > > +{
> > > > +        return sizeof *({ int n = 20; struct { int x[n];} x; x.x[12] = 
> > > > 1; &x; });
> > > > +}
> > > > +
> > > > +int main()
> > > > +{
> > > > +       if (sizeof(struct { int x[20]; }) != foo2a())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (sizeof(struct { int x[20]; }) != foo2b())
> > > > +               __builtin_abort();
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-6.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-6.c
> > > > new file mode 100644
> > > > index 00000000000..3d96d38898b
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-6.c
> > > > @@ -0,0 +1,94 @@
> > > > +/* PR29970, PR91038 */
> > > > +/* { dg-do run } */
> > > > +/* { dg-options "-O2 -Wunused-variable" } */
> > > > +
> > > > +int foo3b(void)   // should not return 0
> > > > +{
> > > > +        int n = 0;
> > > > +        return sizeof *({ n = 10; int x[n]; &x; });
> > > > +}
> > > > +
> > > > +int foo4(void)   // should not ICE
> > > > +{
> > > > +        return (*({
> > > > +                        int n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +int foo5(void)   // should return 1, returns 0
> > > > +{
> > > > +        int n = 0;
> > > > +        return (*({
> > > > +                        n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +int foo5c(void)   // should return 400
> > > > +{
> > > > +        int n = 0;
> > > > +        return sizeof(*({
> > > > +                        n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }));
> > > > +}
> > > > +
> > > > +int foo5b(void)   // should return 1, returns 0
> > > > +{
> > > > +       int n = 0;      /* { dg-warning "unused variable" } */
> > > > +        return (*({
> > > > +                        int n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +int foo5a(void)   // should return 1, returns 0
> > > > +{
> > > > +        return (*({
> > > > +                        int n = 20;
> > > > +                        char (*x)[n][n] = __builtin_malloc(n * n);
> > > > +                        (*x)[12][1] = 1;
> > > > +                        (*x)[0][1] = 0;
> > > > +                        x;
> > > > +                }))[12][1];
> > > > +}
> > > > +
> > > > +
> > > > +
> > > > +
> > > > +int main()
> > > > +{
> > > > +       if (sizeof(int[10]) != foo3b())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo4())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (400 != foo5c())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo5a())
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo5b()) // -O0
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != foo5())
> > > > +               __builtin_abort();
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-7.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-7.c
> > > > new file mode 100644
> > > > index 00000000000..3091b9184c2
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-7.c
> > > > @@ -0,0 +1,44 @@
> > > > +/* PR91038 */
> > > > +/* { dg-do run } */
> > > > +/* { dg-options "-O2 -Wunused-variable" } */
> > > > +
> > > > +
> > > > +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> > > > +
> > > > +struct lbm {
> > > > +
> > > > +       int D;
> > > > +       const int* DQ;
> > > > +
> > > > +} D2Q9 = { 2,
> > > > +       (const int*)&(const int[9][2]){
> > > > +               { 0, 0 },
> > > > +               { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 },
> > > > +               { 1, 1 }, { -1, 1 }, { -1, -1 }, { 1, -1 },
> > > > +       }
> > > > +};
> > > > +
> > > > +void zouhe_left(void)
> > > > +{
> > > > +       __auto_type xx = (*({ int N = 2; struct lbm __x = D2Q9; ((const
> > > > int(*)[9][N])__x.DQ); }));
> > > > +
> > > > +       if (1 != xx[1][0])
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (2 != ARRAY_SIZE(xx[1]))
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (1 != (*({ int N = 2; struct lbm __x = D2Q9; ((const 
> > > > int(*)[9][N])__x.DQ);
> > > > }))[1][0])
> > > > +               __builtin_abort();
> > > > +
> > > > +       if (2 != ARRAY_SIZE(*({ int N = 2; struct lbm __x = D2Q9; 
> > > > ((const
> > > > int(*)[9][N])__x.DQ);
> > > > })[1]))
> > > > +               __builtin_abort();
> > > > +}
> > > > +
> > > > +int main()
> > > > +{
> > > > +       zouhe_left();
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-8.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-8.c
> > > > new file mode 100644
> > > > index 00000000000..5b475eb6cf2
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-8.c
> > > > @@ -0,0 +1,47 @@
> > > > +/* PR29970, PR91038 */
> > > > +/* { dg-do compile } */
> > > > +/* { dg-options "-O2 -Wunused-variable" } */
> > > > +
> > > > +
> > > > +int foo0(void)
> > > > +{
> > > > +       int c = *(*(*({ int n = 10; int (*x)[n][n] = 
> > > > __builtin_malloc(sizeof *x); x; }) + 5)
> > > > + 5);
> > > > +       return c;
> > > > +}
> > > > +
> > > > +int foo1(void)
> > > > +{
> > > > +       int c = *(5 + *(5 + *({ int n = 10; int (*x)[n][n] = 
> > > > __builtin_malloc(sizeof *x); x;
> > > > })));
> > > > +       return c;
> > > > +}
> > > > +
> > > > +int bar2(void)
> > > > +{
> > > > +       int c = (*({ int n = 10; struct { int y[n]; int z; }* x = 
> > > > __builtin_malloc(sizeof
> > > > *x); x;
> > > > })).z;
> > > > +       return c;
> > > > +}
> > > > +
> > > > +int bar3(void)
> > > > +{
> > > > +       int n = 2;      /* { dg-warning "unused variable" } */
> > > > +       int c = (*({ int n = 3;         /* { dg-warning "unused 
> > > > variable" } */
> > > > +               ({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof 
> > > > *x); x; });
> > > > }))[5][5];
> > > > +       return c;
> > > > +}
> > > > +
> > > > +int bar3b(void)
> > > > +{
> > > > +       int n = 2;      /* { dg-warning "unused variable" } */
> > > > +       int c = (*({ int n = 3;         /* { dg-warning "unused 
> > > > variable" } */
> > > > +               ({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof 
> > > > *x); x; });
> > > > }))[0][0];
> > > > +       return c;
> > > > +}
> > > > +
> > > > +int bar4(void)
> > > > +{
> > > > +       int n = 2;      /* { dg-warning "unused variable" } */
> > > > +       int c = *(5 + *( 5 + *({ int n = 3;     /* { dg-warning "unused 
> > > > variable" } */
> > > > +               ({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof 
> > > > *x); x; }); })));
> > > > +       return c;
> > > > +}
> > > > +
> > > > diff --git a/gcc/testsuite/gcc.dg/vla-stexp-9.c 
> > > > b/gcc/testsuite/gcc.dg/vla-stexp-9.c
> > > > new file mode 100644
> > > > index 00000000000..3593a790785
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/vla-stexp-9.c
> > > > @@ -0,0 +1,53 @@
> > > > +/* PR91038 */
> > > > +/* { dg-do run } */
> > > > +/* { dg-options "-O2 -Wunused-variable" } */
> > > > +
> > > > +
> > > > +
> > > > +void foo(void)
> > > > +{
> > > > +       if (2 * sizeof(int) != sizeof((*({ int N = 2; int (*x)[9][N] = 
> > > > 0; x; })[1])))
> > > > +               __builtin_abort();
> > > > +}
> > > > +
> > > > +void bar(void)
> > > > +{
> > > > +       if (2 * sizeof(int) != sizeof((*({ int N = 2; int (*x)[9][N] = 
> > > > 0; x; })[0])))
> > > > +               __builtin_abort();
> > > > +}
> > > > +
> > > > +void bar0(void)
> > > > +{
> > > > +       if (2 * 9 *  sizeof(int) != sizeof((*({ int N = 2; int 
> > > > (*x)[9][N] = 0; x; }))))
> > > > +               __builtin_abort();
> > > > +}
> > > > +
> > > > +void bar11(void)
> > > > +{
> > > > +       sizeof(*((*({ int N = 2; int (*x)[9][N] = 0; x; }) + 0)));
> > > > +}
> > > > +
> > > > +void bar12(void)
> > > > +{
> > > > +       if (2 * sizeof(int) != sizeof(*((*({ int N = 2; int (*x)[9][N] 
> > > > = 0; x; })    ))))
> > > > +               __builtin_abort();
> > > > +}
> > > > +
> > > > +void bar1(void)
> > > > +{
> > > > +       if (2 * sizeof(int) != sizeof(*((*({ int N = 2; int (*x)[9][N] 
> > > > = 0; x; }) + 0))))
> > > > +               __builtin_abort();
> > > > +}
> > > > +
> > > > +
> > > > +
> > > > +
> > > > +int main()
> > > > +{
> > > > +       foo();
> > > > +       bar0();
> > > > +       bar12();
> > > > +       bar1();
> > > > +       bar();
> > > > +}
> > > > +
> > > > 

Reply via email to