ok?

Am Samstag, dem 29.06.2024 um 20:30 +0200 schrieb Martin Uecker:
> Probably not entirely fool-proof when using statement
> expressions in initializers, but should be good enough.
> 
> 
> Bootstrapped and regression tested on x86_64.
> 
> 
> 
>     c: Diagnose declarations that are used only in their own initializer 
> [PR115027]
>     
>     Track the declaration that is currently being initialized and do not
>     mark it as read when it is used in its own initializer.  This then
>     allows it to be diagnosed as set-but-unused when it is not used
>     elsewhere.
>     
>             PR c/115027
>     
>     gcc/c/
>             * c-tree.h (in_decl_init): Declare variable.
>             * c-parser.cc (c_parser_initializer): Record decl being 
> initialized.
>             * c-typeck.cc (in_decl_init): Defintie variable.
>             (mark_exp_read): Ignore decl currently being initialized.
>     
>     gcc/testsuite/
>             * gcc.dg/pr115027.c: New test.
> 
> diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
> index 8c4e697a4e1..46060665115 100644
> --- a/gcc/c/c-parser.cc
> +++ b/gcc/c/c-parser.cc
> @@ -6126,11 +6126,14 @@ c_parser_type_name (c_parser *parser, bool alignas_ok)
>  static struct c_expr
>  c_parser_initializer (c_parser *parser, tree decl)
>  {
> +  struct c_expr ret;
> +  tree save = in_decl_init;
> +  in_decl_init = decl;
> +
>    if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
> -    return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
> +    ret = c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
>    else
>      {
> -      struct c_expr ret;
>        location_t loc = c_parser_peek_token (parser)->location;
>        ret = c_parser_expr_no_commas (parser, NULL);
>        if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
> @@ -6154,8 +6157,9 @@ c_parser_initializer (c_parser *parser, tree decl)
>             || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
>                                           (ret.value))))
>       ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
> -      return ret;
>      }
> +    in_decl_init = save;
> +    return ret;
>  }
>  
>  /* The location of the last comma within the current initializer list,
> diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
> index 15da875a029..8013963b06d 100644
> --- a/gcc/c/c-tree.h
> +++ b/gcc/c/c-tree.h
> @@ -740,6 +740,8 @@ extern int in_typeof;
>  extern bool c_in_omp_for;
>  extern bool c_omp_array_section_p;
>  
> +extern tree in_decl_init;
> +
>  extern tree c_last_sizeof_arg;
>  extern location_t c_last_sizeof_loc;
>  
> diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
> index 455dc374b48..34279dc1d1a 100644
> --- a/gcc/c/c-typeck.cc
> +++ b/gcc/c/c-typeck.cc
> @@ -73,6 +73,9 @@ int in_sizeof;
>  /* The level of nesting inside "typeof".  */
>  int in_typeof;
>  
> +/* When inside an initializer, this is set to the decl being initialized.  */
> +tree in_decl_init;
> +
>  /* True when parsing OpenMP loop expressions.  */
>  bool c_in_omp_for;
>  
> @@ -2047,7 +2050,8 @@ mark_exp_read (tree exp)
>      {
>      case VAR_DECL:
>      case PARM_DECL:
> -      DECL_READ_P (exp) = 1;
> +      if (exp != in_decl_init)
> +     DECL_READ_P (exp) = 1;
>        break;
>      case ARRAY_REF:
>      case COMPONENT_REF:
> diff --git a/gcc/testsuite/gcc.dg/pr115027.c b/gcc/testsuite/gcc.dg/pr115027.c
> new file mode 100644
> index 00000000000..ac2699f8392
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr115027.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Wunused-but-set-variable" } */
> +
> +void f(void)
> +{
> +     struct foo { void *p; };
> +     struct foo g = { &g };  /* { dg-warning "set but not used" } */
> +}
> 

Reply via email to