public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Martin Uecker <uecker@tugraz.at>
To: Richard Biener <richard.guenther@gmail.com>
Cc: gcc-patches@gcc.gnu.org, Joseph Myers <joseph@codesourcery.com>,
	Richard Biener <rguenther@suse.de>
Subject: Re: [C PATCH v3] Fix ICEs related to VM types in C 2/2
Date: Tue, 23 May 2023 08:24:16 +0200	[thread overview]
Message-ID: <1e82fc2dcce84019104d693420daf601c03dcbf8.camel@tugraz.at> (raw)
In-Reply-To: <CAFiYyc3J2VQ1Qa2rdSs+f754pGqX7F8RUB4RtZhvcKcwZXVS2A@mail.gmail.com>

Am Dienstag, dem 23.05.2023 um 08:13 +0200 schrieb Richard Biener:
> On Mon, May 22, 2023 at 7:24 PM Martin Uecker via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> > 
> > 
> > 
> > This version contains the middle-end changes for PR109450
> > and test cases as before.  The main middle-end change is that
> > we use gimplify_type_sizes also for parameters and remove
> > the special code that also walked into pointers (which is
> > incorrect).
> > 
> > In addition, in the C FE this patch now also adds DECL_EXPR
> > for vm-types which are pointed-to by parameters declared
> > as arrays.  The new function created contains the exact
> > code previously used only for regular pointers, and is
> > now also called for parameters declared as arrays.
> > 
> > 
> > Martin
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> >     Fix ICEs related to VM types in C 2/2 [PR109450]
> > 
> >     Size expressions were sometimes lost and not gimplified correctly,
> >     leading to ICEs and incorrect evaluation order.  Fix this by 1) not
> >     recursing pointers when gimplifying parameters in the middle-end
> >     (the code is merged with gimplify_type_sizes), which is incorrect
> >     because it might access variables declared later for incomplete
> >     structs, and 2) adding a decl expr for variably-modified arrays
> >     that are pointed to by parameters declared as arrays.
> > 
> >             PR c/109450
> > 
> >             gcc/
> >             * c/c-decl.cc (add_decl_expr): New function.
> >             (grokdeclarator): Add decl expr for size expression in
> >             types pointed to by parameters declared as arrays.
> >             * function.cc (gimplify_parm_type): Remove function.
> >             (gimplify_parameters): Call gimplify_parm_sizes.
> >             * gimplify.cc (gimplify_type_sizes): Make function static.
> >             (gimplify_parm_sizes): New function.
> > 
> >             gcc/testsuite/
> >             * gcc.dg/pr109450-1.c: New test.
> >             * gcc.dg/pr109450-2.c: New test.
> >             * gcc.dg/vla-26.c: New test.
> > 
> > diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> > index 494d3cf1747..c35347734b2 100644
> > --- a/gcc/c/c-decl.cc
> > +++ b/gcc/c/c-decl.cc
> > @@ -6490,6 +6490,55 @@ smallest_type_quals_location (const location_t *locations,
> >    return loc;
> >  }
> > 
> > +
> > +/* We attach an artificial TYPE_DECL to pointed-to type
> > +   and arrange for it to be included in a DECL_EXPR.  This
> > +   forces the sizes evaluation at a safe point and ensures it
> > +   is not deferred until e.g. within a deeper conditional context.
> > +
> > +   PARM contexts have no enclosing statement list that
> > +   can hold the DECL_EXPR, so we need to use a BIND_EXPR
> > +   instead, and add it to the list of expressions that
> > +   need to be evaluated.
> > +
> > +   TYPENAME contexts do have an enclosing statement list,
> > +   but it would be incorrect to use it, as the size should
> > +   only be evaluated if the containing expression is
> > +   evaluated.  We might also be in the middle of an
> > +   expression with side effects on the pointed-to type size
> > +   "arguments" prior to the pointer declaration point and
> > +   the fake TYPE_DECL in the enclosing context would force
> > +   the size evaluation prior to the side effects.  We therefore
> > +   use BIND_EXPRs in TYPENAME contexts too.  */
> > +static void
> > +add_decl_expr(location_t loc, enum decl_context decl_context, tree type, tree *expr)
> > +{
> > +  tree bind = NULL_TREE;
> > +  if (decl_context == TYPENAME || decl_context == PARM || decl_context == FIELD)
> > +    {
> > +      bind = build3 (BIND_EXPR, void_type_node, NULL_TREE, NULL_TREE, NULL_TREE);
> > +      TREE_SIDE_EFFECTS (bind) = 1;
> > +      BIND_EXPR_BODY (bind) = push_stmt_list ();
> > +      push_scope ();
> > +    }
> > +
> > +  tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
> > +  pushdecl (decl);
> > +  DECL_ARTIFICIAL (decl) = 1;
> > +  add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
> > +  TYPE_NAME (type) = decl;
> > +
> > +  if (bind)
> > +    {
> > +      pop_scope ();
> > +      BIND_EXPR_BODY (bind) = pop_stmt_list (BIND_EXPR_BODY (bind));
> > +      if (*expr)
> > +       *expr = build2 (COMPOUND_EXPR, void_type_node, *expr, bind);
> > +      else
> > +       *expr = bind;
> > +    }
> > +}
> > +
> >  /* Given declspecs and a declarator,
> >     determine the name and type of the object declared
> >     and construct a ..._DECL node for it.
> > @@ -7474,58 +7523,9 @@ grokdeclarator (const struct c_declarator *declarator,
> > 
> >                This is expected to happen automatically when the pointed-to
> >                type has a name/declaration of it's own, but special attention
> > -              is required if the type is anonymous.
> > -
> > -              We attach an artificial TYPE_DECL to such pointed-to type
> > -              and arrange for it to be included in a DECL_EXPR.  This
> > -              forces the sizes evaluation at a safe point and ensures it
> > -              is not deferred until e.g. within a deeper conditional context.
> > -
> > -              PARM contexts have no enclosing statement list that
> > -              can hold the DECL_EXPR, so we need to use a BIND_EXPR
> > -              instead, and add it to the list of expressions that
> > -              need to be evaluated.
> > -
> > -              TYPENAME contexts do have an enclosing statement list,
> > -              but it would be incorrect to use it, as the size should
> > -              only be evaluated if the containing expression is
> > -              evaluated.  We might also be in the middle of an
> > -              expression with side effects on the pointed-to type size
> > -              "arguments" prior to the pointer declaration point and
> > -              the fake TYPE_DECL in the enclosing context would force
> > -              the size evaluation prior to the side effects.  We therefore
> > -              use BIND_EXPRs in TYPENAME contexts too.  */
> > -           if (!TYPE_NAME (type)
> > -               && c_type_variably_modified_p (type))
> > -             {
> > -               tree bind = NULL_TREE;
> > -               if (decl_context == TYPENAME || decl_context == PARM
> > -                   || decl_context == FIELD)
> > -                 {
> > -                   bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
> > -                                  NULL_TREE, NULL_TREE);
> > -                   TREE_SIDE_EFFECTS (bind) = 1;
> > -                   BIND_EXPR_BODY (bind) = push_stmt_list ();
> > -                   push_scope ();
> > -                 }
> > -               tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
> > -               pushdecl (decl);
> > -               DECL_ARTIFICIAL (decl) = 1;
> > -               add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
> > -               TYPE_NAME (type) = decl;
> > -
> > -               if (bind)
> > -                 {
> > -                   pop_scope ();
> > -                   BIND_EXPR_BODY (bind)
> > -                     = pop_stmt_list (BIND_EXPR_BODY (bind));
> > -                   if (*expr)
> > -                     *expr = build2 (COMPOUND_EXPR, void_type_node, *expr,
> > -                                     bind);
> > -                   else
> > -                     *expr = bind;
> > -                 }
> > -             }
> > +              is required if the type is anonymous. */
> > +           if (!TYPE_NAME (type) && c_type_variably_modified_p (type))
> > +             add_decl_expr (loc, decl_context, type, expr);
> > 
> >             type = c_build_pointer_type (type);
> > 
> > @@ -7787,6 +7787,11 @@ grokdeclarator (const struct c_declarator *declarator,
> >             if (type_quals)
> >               type = c_build_qualified_type (type, type_quals, orig_qual_type,
> >                                              orig_qual_indirect);
> > +
> > +           /* The pointed-to type may need a decl expr (see above).  */
> > +           if (!TYPE_NAME (type) && c_type_variably_modified_p (type))
> > +             add_decl_expr (loc, decl_context, type, expr);
> > +
> >             type = c_build_pointer_type (type);
> >             type_quals = array_ptr_quals;
> >             if (type_quals)
> > diff --git a/gcc/function.cc b/gcc/function.cc
> > index f0ae641512d..5699b9d495d 100644
> > --- a/gcc/function.cc
> > +++ b/gcc/function.cc
> > @@ -3872,30 +3872,6 @@ assign_parms (tree fndecl)
> >      }
> >  }
> > 
> > -/* A subroutine of gimplify_parameters, invoked via walk_tree.
> > -   For all seen types, gimplify their sizes.  */
> > -
> > -static tree
> > -gimplify_parm_type (tree *tp, int *walk_subtrees, void *data)
> > -{
> > -  tree t = *tp;
> > -
> > -  *walk_subtrees = 0;
> > -  if (TYPE_P (t))
> > -    {
> > -      if (POINTER_TYPE_P (t))
> > -       *walk_subtrees = 1;
> > -      else if (TYPE_SIZE (t) && !TREE_CONSTANT (TYPE_SIZE (t))
> > -              && !TYPE_SIZES_GIMPLIFIED (t))
> > -       {
> > -         gimplify_type_sizes (t, (gimple_seq *) data);
> > -         *walk_subtrees = 1;
> > -       }
> > -    }
> > -
> > -  return NULL;
> > -}
> > -
> >  /* Gimplify the parameter list for current_function_decl.  This involves
> >     evaluating SAVE_EXPRs of variable sized parameters and generating code
> >     to implement callee-copies reference parameters.  Returns a sequence of
> > @@ -3931,14 +3907,7 @@ gimplify_parameters (gimple_seq *cleanup)
> >          SAVE_EXPRs (amongst others) onto a pending sizes list.  This
> >          turned out to be less than manageable in the gimple world.
> >          Now we have to hunt them down ourselves.  */
> > -      walk_tree_without_duplicates (&data.arg.type,
> > -                                   gimplify_parm_type, &stmts);
> > -
> > -      if (TREE_CODE (DECL_SIZE_UNIT (parm)) != INTEGER_CST)
> > -       {
> > -         gimplify_one_sizepos (&DECL_SIZE (parm), &stmts);
> > -         gimplify_one_sizepos (&DECL_SIZE_UNIT (parm), &stmts);
> > -       }
> > +      gimplify_parm_sizes (parm, &stmts);
> > 
> >        if (data.arg.pass_by_reference)
> >         {
> > diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
> > index d0d16a24820..fd990c328eb 100644
> > --- a/gcc/gimplify.cc
> > +++ b/gcc/gimplify.cc
> > @@ -242,6 +242,7 @@ static struct gimplify_omp_ctx *gimplify_omp_ctxp;
> >  static bool in_omp_construct;
> > 
> >  /* Forward declaration.  */
> > +static void gimplify_type_sizes (tree type, gimple_seq *list_p);
> >  static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
> >  static hash_map<tree, tree> *oacc_declare_returns;
> >  static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
> > @@ -17425,7 +17426,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
> >  /* Look through TYPE for variable-sized objects and gimplify each such
> >     size that we find.  Add to LIST_P any statements generated.  */
> > 
> > -void
> > +static void
> >  gimplify_type_sizes (tree type, gimple_seq *list_p)
> >  {
> >    if (type == NULL || type == error_mark_node)
> > @@ -17533,6 +17534,21 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
> >      }
> >  }
> > 
> > +/* Gimplify sizes in parameter declarations.  */
> > +
> > +void
> > +gimplify_parm_sizes (tree parm, gimple_seq *list_p)
> 
> Can you instead inline this at the single caller in gimplify_parameters?
> It looks like both gimplify_type_sizes and gimplify_one_sizepos are
> already exported.  So just add the missing gimplify_type_sizes () call
> at the single call site.
> 
> The middle-end changes are OK with that change.

Thanks Richard!  

I did this in this way because this was the only outside use of
gimplify_type_sizes. Then one can unexport gimplify_type_size.
In fact, it is declared static (see above) and removed from the
header (see below) in the patch. I thought this is better logical
encapsulation.   (BTW:  gimplify_one_sizepos then has only 
one remaining use in the Ada FE, so maybe we make a copy there
and also unexport it?).

What do you think?

Martin

> Thanks,
> Richard.
> 
> > +{
> > +  gimplify_type_sizes (TREE_TYPE (parm), list_p);
> > +
> > +  if (TREE_CODE (DECL_SIZE_UNIT (parm)) != INTEGER_CST)
> > +    {
> > +      gimplify_one_sizepos (&DECL_SIZE (parm), list_p);
> > +      gimplify_one_sizepos (&DECL_SIZE_UNIT (parm), list_p);
> > +    }
> > +}
> > +
> > +
> >  /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
> >     a size or position, has had all of its SAVE_EXPRs evaluated.
> >     We add any required statements to *STMT_P.  */
> > diff --git a/gcc/gimplify.h b/gcc/gimplify.h
> > index f4a3eea2606..17ea0580647 100644
> > --- a/gcc/gimplify.h
> > +++ b/gcc/gimplify.h
> > @@ -78,7 +78,7 @@ extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
> > 
> >  int omp_construct_selector_matches (enum tree_code *, int, int *);
> > 
> > -extern void gimplify_type_sizes (tree, gimple_seq *);
> > +extern void gimplify_parm_sizes (tree, gimple_seq *);
> >  extern void gimplify_one_sizepos (tree *, gimple_seq *);
> >  extern gbind *gimplify_body (tree, bool);
> >  extern enum gimplify_status gimplify_arg (tree *, gimple_seq *, location_t,
> > diff --git a/gcc/testsuite/gcc.dg/pr109450-1.c b/gcc/testsuite/gcc.dg/pr109450-1.c
> > new file mode 100644
> > index 00000000000..aec127f2afc
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/pr109450-1.c
> > @@ -0,0 +1,21 @@
> > +/* PR c/109450
> > + * { dg-do run }
> > + * { dg-options "-std=gnu99" }
> > + * */
> > +
> > +int bar(int n, struct foo* x)  /* { dg-warning "not be visible" } */
> > +{
> > +       int a = n;
> > +       struct foo { char buf[n++]; }* p = x;
> > +       return a;
> > +}
> > +
> > +int main()
> > +{
> > +       if (1 != bar(1, 0))
> > +               __builtin_abort();
> > +}
> > +
> > +
> > +
> > +
> > diff --git a/gcc/testsuite/gcc.dg/pr109450-2.c b/gcc/testsuite/gcc.dg/pr109450-2.c
> > new file mode 100644
> > index 00000000000..06799f6df23
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/pr109450-2.c
> > @@ -0,0 +1,18 @@
> > +/* PR c/109450
> > + * { dg-do run }
> > + * { dg-options "-std=gnu99" }
> > + * */
> > +
> > +int bar(int n, struct foo *x)  /* { dg-warning "not be visible" } */
> > +{
> > +       int a = n;
> > +       struct foo { char buf[a++]; }* p = x;
> > +       return n == a;
> > +}
> > +
> > +int main()
> > +{
> > +       if (bar(1, 0))
> > +               __builtin_abort();
> > +}
> > +
> > diff --git a/gcc/testsuite/gcc.dg/vla-26.c b/gcc/testsuite/gcc.dg/vla-26.c
> > new file mode 100644
> > index 00000000000..5d2fa3e280a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/vla-26.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c99 -O2" } */
> > +
> > +void ed(int n, float s[3][n])
> > +{
> > +       for (int i = 0; i < n; i++)
> > +               s[1][i];
> > +}
> > +
> > +void e(int n, float s[3][n])
> > +{
> > +       ed(n, s);
> > +}
> > +
> > +
> > 
> > 



  reply	other threads:[~2023-05-23  6:24 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-22 17:23 Martin Uecker
2023-05-22 20:22 ` Joseph Myers
2023-05-23  6:13 ` Richard Biener
2023-05-23  6:24   ` Martin Uecker [this message]
2023-05-23  8:18     ` Richard Biener
2023-05-23  9:25       ` Martin Uecker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1e82fc2dcce84019104d693420daf601c03dcbf8.camel@tugraz.at \
    --to=uecker@tugraz.at \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    --cc=rguenther@suse.de \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).