On Tue, 1 Apr 2025, Jakub Jelinek wrote:

> Hi!
> 
> The following testcases ICE on invalid code which defines
> labels inside of statement expressions and then uses &&label
> from code outside of the statement expressions.
> The C++ FE diagnoses that with a warning (not specifically for
> assume attribute, genericallly about taking address of a label
> outside of a statement expression so computed goto could violate
> the requirement that statement expression is not entered from
> outside of it through a jump into it), the C FE doesn't diagnose
> anything.
> Normal direct gotos to such labels are diagnosed by both C and C++.
> In the assume attribute case it is actually worse than for
> addresses of labels in normal statement expressions, in that case
> the labels are still in the current function, so invalid program
> can still jump to those (and in case of OpenMP/OpenACC where it
> is also invalid and stuff is moved to a separate function, such
> movement is done post cfg discovery of FORCED_LABELs and worst
> case one can run into cases which fail to assemble, but I haven't
> succeeded in creating ICE for that).
> For assume at -O0 we'd just throw away the assume expression if
> it is not a simple condition and so the label is then not defined
> anywhere and we ICE during cfg pass.
> The gimplify.cc hunks fix that, as we don't have FORCED_LABELs
> discovery done yet, it preserves all assume expressions which contain
> used user labels.
> With that we ICE during IRA, which is upset about an indirect jump
> to a label which doesn't exist.
> So, the gimple-low.cc hunks add diagnostics of the problem, it gathers
> uids of all the user used labels inside of the assume expressions (usually
> none) and if it finds any, walks the IL to find uses of those from outside
> of those expressions now outlined into separate magic functions.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 2025-04-01  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR middle-end/119537
>       * gimplify.cc (find_used_user_labels): New function.
>       (gimplify_call_expr): Don't remove complex assume expression at -O0
>       if it defines any user labels.
>       * gimple-low.cc: Include diagnostic-core.h.
>       (assume_labels): New variable.
>       (diagnose_assume_labels): New function.
>       (lower_function_body): Call it via walk_gimple_seq if assume_labels
>       is non-NULL, then BITMAP_FREE assume_labels.
>       (find_assumption_locals_r): Record in assume_labels uids of user
>       labels defined in assume attribute expressions.
> 
>       * c-c++-common/pr119537-1.c: New test.
>       * c-c++-common/pr119537-2.c: New test.
> 
> --- gcc/gimplify.cc.jj        2025-03-31 12:53:44.853727077 +0200
> +++ gcc/gimplify.cc   2025-03-31 17:05:40.854893880 +0200
> @@ -4508,6 +4508,21 @@ gimplify_variant_call_expr (tree expr, f
>  }
>  
>  
> +/* Helper function for gimplify_call_expr, called via walk_tree.
> +   Find used user labels.  */
> +
> +static tree
> +find_used_user_labels (tree *tp, int *, void *)
> +{
> +  if (TREE_CODE (*tp) == LABEL_EXPR
> +      && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp))
> +      && DECL_NAME (LABEL_EXPR_LABEL (*tp))
> +      && TREE_USED (LABEL_EXPR_LABEL (*tp)))
> +    return *tp;
> +  return NULL_TREE;
> +}
> +
> +
>  /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
>     WANT_VALUE is true if the result of the call is desired.  */
>  
> @@ -4568,8 +4583,14 @@ gimplify_call_expr (tree *expr_p, gimple
>                                                  fndecl, 0));
>                 return GS_OK;
>               }
> -           /* If not optimizing, ignore the assumptions.  */
> -           if (!optimize || seen_error ())
> +           /* If not optimizing, ignore the assumptions unless there
> +              are used user labels in it.  */
> +           if ((!optimize
> +                && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p,
> +                                                                  0),
> +                                                  find_used_user_labels,
> +                                                  NULL))
> +               || seen_error ())
>               {
>                 *expr_p = NULL_TREE;
>                 return GS_ALL_DONE;
> --- gcc/gimple-low.cc.jj      2025-03-21 20:25:38.396064280 +0100
> +++ gcc/gimple-low.cc 2025-03-31 20:20:38.961772695 +0200
> @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.
>  #include "tree-inline.h"
>  #include "gimple-walk.h"
>  #include "attribs.h"
> +#include "diagnostic-core.h"
>  
>  /* The differences between High GIMPLE and Low GIMPLE are the
>     following:
> @@ -78,6 +79,10 @@ struct lower_data
>    bool cannot_fallthru;
>  };
>  
> +/* Bitmap of LABEL_DECL uids for user labels moved into assume outlined
> +   functions.  */
> +static bitmap assume_labels;
> +
>  static void lower_stmt (gimple_stmt_iterator *, struct lower_data *);
>  static void lower_gimple_bind (gimple_stmt_iterator *, struct lower_data *);
>  static void lower_try_catch (gimple_stmt_iterator *, struct lower_data *);
> @@ -87,6 +92,29 @@ static void lower_builtin_posix_memalign
>  static void lower_builtin_assume_aligned (gimple_stmt_iterator *);
>  
>  
> +/* Helper function for lower_function_body, called via walk_gimple_seq.
> +   Diagnose uses of user labels defined inside of assume attribute
> +   expressions.  */
> +
> +static tree
> +diagnose_assume_labels (tree *tp, int *, void *data)
> +{
> +  if (TREE_CODE (*tp) == LABEL_DECL
> +      && !DECL_ARTIFICIAL (*tp)
> +      && DECL_NAME (*tp)
> +      && bitmap_bit_p (assume_labels, DECL_UID (*tp)))
> +    {
> +      struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
> +      auto_diagnostic_group d;
> +      error_at (gimple_location (gsi_stmt (wi->gsi)),
> +             "reference to label %qD defined inside of %<assume%> "
> +             "attribute expression from outside of the attribute", *tp);
> +      inform (DECL_SOURCE_LOCATION (*tp), "%qD defined here", *tp);
> +    }
> +  return NULL_TREE;
> +}
> +
> +
>  /* Lower the body of current_function_decl from High GIMPLE into Low
>     GIMPLE.  */
>  
> @@ -169,6 +197,15 @@ lower_function_body (void)
>       lowered sequence.  */
>    gimple_set_body (current_function_decl, lowered_body);
>  
> +  if (assume_labels)
> +    {
> +      struct walk_stmt_info wi;
> +
> +      memset (&wi, 0, sizeof (wi));
> +      walk_gimple_seq (lowered_body, NULL, diagnose_assume_labels, &wi);
> +      BITMAP_FREE (assume_labels);
> +    }
> +
>    gcc_assert (data.block == DECL_INITIAL (current_function_decl));
>    BLOCK_SUBBLOCKS (data.block)
>      = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
> @@ -335,6 +372,12 @@ find_assumption_locals_r (gimple_stmt_it
>        {
>       tree label = gimple_label_label (as_a <glabel *> (stmt));
>       data->id.decl_map->put (label, label);
> +     if (DECL_NAME (label) && !DECL_ARTIFICIAL (label))
> +       {
> +         if (assume_labels == NULL)
> +           assume_labels = BITMAP_ALLOC (NULL);
> +         bitmap_set_bit (assume_labels, DECL_UID (label));
> +       }
>       break;
>        }
>      case GIMPLE_RETURN:
> --- gcc/testsuite/c-c++-common/pr119537-1.c.jj        2025-03-31 
> 20:31:06.299160568 +0200
> +++ gcc/testsuite/c-c++-common/pr119537-1.c   2025-03-31 20:34:24.526439291 
> +0200
> @@ -0,0 +1,23 @@
> +/* PR middle-end/119537 */
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +
> +volatile int v;
> +void *bar (void *, void *);
> +
> +void
> +foo (bool z)
> +{
> +  if (z)
> +    goto *&&x;                               /* { dg-error "reference to 
> label 'x' defined inside of 'assume' attribute expression from outside of the 
> attribute" } */
> +                                     /* { dg-message "as a possible target 
> of computed goto" "" { target c++ } .-1 } */
> +  [[gnu::assume (({ x: v += 1; true; }))]];/* { dg-message "'x' defined 
> here" } */
> +                                     /* { dg-warning "jump to label 'x'" "" 
> { target c++ } .-1 } */
> +                                     /* { dg-message "enters statement 
> expression" "" { target c++ } .-2 } */
> +  [[gnu::assume (({ y: v += 1; true; }))]];/* { dg-message "'y' defined 
> here" } */
> +                                     /* { dg-warning "jump to label 'y'" "" 
> { target c++ } .-1 } */
> +  goto *bar (&&x, &&y);                      /* { dg-error "reference to 
> label 'x' defined inside of 'assume' attribute expression from outside of the 
> attribute" } */
> +                                     /* { dg-error "reference to label 'y' 
> defined inside of 'assume' attribute expression from outside of the 
> attribute" "" { target *-*-* } .-1 } */
> +                                     /* { dg-message "as a possible target 
> of computed goto" "" { target c++ } .-2 } */
> +                                     /* { dg-message "enters statement 
> expression" "" { target c++ } .-3 } */
> +}
> --- gcc/testsuite/c-c++-common/pr119537-2.c.jj        2025-03-31 
> 20:31:13.570060752 +0200
> +++ gcc/testsuite/c-c++-common/pr119537-2.c   2025-03-31 20:34:29.773367259 
> +0200
> @@ -0,0 +1,23 @@
> +/* PR middle-end/119537 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +volatile int v;
> +void *bar (void *, void *);
> +
> +void
> +foo (bool z)
> +{
> +  if (z)
> +    goto *&&x;                               /* { dg-error "reference to 
> label 'x' defined inside of 'assume' attribute expression from outside of the 
> attribute" } */
> +                                     /* { dg-message "as a possible target 
> of computed goto" "" { target c++ } .-1 } */
> +  [[gnu::assume (({ x: v += 1; true; }))]];/* { dg-message "'x' defined 
> here" } */
> +                                     /* { dg-warning "jump to label 'x'" "" 
> { target c++ } .-1 } */
> +                                     /* { dg-message "enters statement 
> expression" "" { target c++ } .-2 } */
> +  [[gnu::assume (({ y: v += 1; true; }))]];/* { dg-message "'y' defined 
> here" } */
> +                                     /* { dg-warning "jump to label 'y'" "" 
> { target c++ } .-1 } */
> +  goto *bar (&&x, &&y);                      /* { dg-error "reference to 
> label 'x' defined inside of 'assume' attribute expression from outside of the 
> attribute" } */
> +                                     /* { dg-error "reference to label 'y' 
> defined inside of 'assume' attribute expression from outside of the 
> attribute" "" { target *-*-* } .-1 } */
> +                                     /* { dg-message "as a possible target 
> of computed goto" "" { target c++ } .-2 } */
> +                                     /* { dg-message "enters statement 
> expression" "" { target c++ } .-3 } */
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to