Am Montag, den 16.08.2021, 00:30 -0400 schrieb Jason Merrill:
> On 8/1/21 1:36 PM, Uecker, Martin wrote:
> > 
> > Here is an attempt to fix some old and annoying bugs related
> > to VLAs and statement expressions. In particulary, this seems
> > to fix the issues with variably-modified types which are
> > returned from statement expressions (which works on clang),
> > but there are still bugs remaining related to structs
> > with VLA members (which seems to be a FE bug).
> > 
> > Of course, I might be doing something stupid...
> > 
> > The patch survives bootstrapping and regresstion testing
> > on x86_64.
> 
> Including Ada?


It broke PLACEHOLDER_EXPRs as you pointed out below.

Please take a look at the new version:

https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577402.html

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. Some of these issues can be addressed by
> > gimplifying the base expression earlier in gimplify_compound_lval.
> > 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.
> >      
> >      gcc/testsuite/
> >     PR c/91038
> >     PR c/29970
> >     * gcc.dg/vla-stexp-01.c: New test.
> >     * gcc.dg/vla-stexp-02.c: New test.
> >     * gcc.dg/vla-stexp-03.c: New test.
> >     * gcc.dg/vla-stexp-04.c: New test.
> > 
> > 
> > diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> > index 21ff32ee4aa..885d5f73585 100644
> > --- a/gcc/gimplify.c
> > +++ b/gcc/gimplify.c
> > @@ -2839,7 +2839,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 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)
> > @@ -2984,9 +2987,23 @@ 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.  */
> > +     So we do this in three steps.  First we gimplify the base,
> > +     then we deal with the annotations for any variables in the
> > +     components, 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 first. */
> 
> The previous paragraph says,
> 
> >                               But we can't gimplify the
> > inner                                                   
> >      expression until we deal with any variable bounds, sizes,
> > or                                              
> >      positions in order to deal with PLACEHOLDER_EXPRs. 
> 
> so I would expect your change to break examples that the current code 
> was designed to handle.  The change to delay gimplifying the inner 
> expression was in r0-59131 (SVN r83474), by Richard Kenner.  But there 
> aren't any testcases in that commit.  Richard, any insight?  Can you 
> review this patch?



> > +  /* Step 1 is to gimplify the base expression.  Make sure lvalue is set
> > +     so as to match the min_lval predicate.  Failure to do so may result
> > +     in the creation of large aggregate temporaries.  */
> > +  tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
> > +                   fallback | fb_lvalue);
> > +
> > +  ret = MIN (ret, tret);
> > +
> > +
> >     for (i = expr_stack.length () - 1; i >= 0; i--)
> >       {
> >         tree t = expr_stack[i];
> > @@ -3076,12 +3093,6 @@ gimplify_compound_lval (tree *expr_p, gimple_seq 
> > *pre_p, gimple_seq
> > *post_p,
> >     }
> >       }
> >   
> > -  /* Step 2 is to gimplify the base expression.  Make sure lvalue is set
> > -     so as to match the min_lval predicate.  Failure to do so may result
> > -     in the creation of large aggregate temporaries.  */
> > -  tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
> > -                   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.  */
> > diff --git a/gcc/testsuite/gcc.dg/vla-stexpr-01.c 
> > b/gcc/testsuite/gcc.dg/vla-stexpr-01.c
> > new file mode 100644
> > index 00000000000..27e1817eb63
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/vla-stexpr-01.c
> > @@ -0,0 +1,94 @@
> > +/* PR29970, PR91038 */
> > +/* { dg-do run } */
> > +/* { dg-options "-O0" } */
> > +
> > +int foo3b(void)   // should not return 0
> > +{
> > +        int n = 0;
> > +        return sizeof *({ n = 10; int x[n]; x; &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;
> > +        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-stexpr-02.c 
> > b/gcc/testsuite/gcc.dg/vla-stexpr-02.c
> > new file mode 100644
> > index 00000000000..99b4f571e52
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/vla-stexpr-02.c
> > @@ -0,0 +1,31 @@
> > +/* PR29970 */
> > +/* { dg-do run } */
> > +/* { dg-options "" } */
> > +
> > +
> > +
> > +
> > +int foo2a(void)   // should not ICE
> > +{
> > +        return ({ int n = 20; struct { int x[n];} x; x.x[12] = 1; 
> > sizeof(x); });
> > +}
> > +
> > +#if 0
> > +int foo2b(void)   // should not ICE
> > +{
> > +        return sizeof *({ int n = 20; struct { int x[n];} x; x.x[12] = 1; 
> > &x; });
> > +}
> > +#endif
> > +
> > +int main()
> > +{
> > +   if (sizeof(struct { int x[20]; }) != foo2a())
> > +           __builtin_abort();
> > +#if 0
> > +   if (sizeof(struct { int x[20]; }) != foo2b())
> > +           __builtin_abort();
> > +#endif
> > +   return 0;
> > +}
> > +
> > +
> > diff --git a/gcc/testsuite/gcc.dg/vla-stexpr-03.c 
> > b/gcc/testsuite/gcc.dg/vla-stexpr-03.c
> > new file mode 100644
> > index 00000000000..61f8986eaa3
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/vla-stexpr-03.c
> > @@ -0,0 +1,94 @@
> > +/* PR29970, PR91038 */
> > +/* { dg-do run } */
> > +/* { dg-options "-O2" } */
> > +
> > +int foo3b(void)   // should not return 0
> > +{
> > +        int n = 0;
> > +        return sizeof *({ n = 10; int x[n]; x; &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;
> > +        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-stexpr-04.c 
> > b/gcc/testsuite/gcc.dg/vla-stexpr-04.c
> > new file mode 100644
> > index 00000000000..ffc8b12fa9b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/vla-stexpr-04.c
> > @@ -0,0 +1,38 @@
> > +/* PR91038 */
> > +/* { dg-do run } */
> > +/* { dg-options "" } */
> > +
> > +
> > +#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();
> > +}
> > +
> > +int main()
> > +{
> > +   zouhe_left();
> > +   return 0;
> > +}
> > +
> > +
> > 

Reply via email to