On Tue, Apr 11, 2023 at 11:47 AM Martin Uecker via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
>
>
> Ok, here is another attempt on fixing issues with size expression.
> Not all are regressions, but it does not make sense to try to split
> it up.

They might be regressions still from pre gimple (3.4 and before),
though I wonder how much value considering something which didn't work
in GCC 4.0+ these days as a regression.
Also splitting them up if possible is always welcomed to be able to
review each thing separately.

Thanks,
Andrew

>
> Martin
>
>
>
>         Fix ICEs related to VM types in C [PR106465, PR107557, PR108424, 
> PR109450]
>
>         Size expressions were sometimes lost and not gimplified correctly, 
> leading to
>         ICEs and incorrect evaluation order.  Fix this by 1) not recursing 
> into
>         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) tracking size 
> expressions for
>         struct/union members correctly, 3) emitting code to evaluate size 
> expressions
>         for missing cases (nested functions, empty declarations, and 
> structs/unions).
>
>         PR c/106465
>         PR c/107557
>         PR c/108423
>         PR c/109450
>
>         gcc/
>         * c/c-decl.cc (start_decl): Make sure size expression are
>         evaluated only in correct context.
>         (grokdeclarator): Size expression in fields may need a bind
>         expression, make sure DECL_EXPR is always created.
>         (grokfield, declspecs_add_type): Pass along size expressions.
>         (finish_struct): Remove unneeded DECL_EXPR.
>         (start_function): Evaluate size expressions for nested functions.
>         * c/c-parser.cc (c_parser_struct_declarations,
>         c_parser_struct_or_union_specifier): Pass along size expressions.
>         (c_parser_declaration_or_fndef): Evaluate size expression.
>         (c_parser_objc_at_property_declaration,
>         c_parser_objc_class_instance_variables): Adapt.
>         * 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/nested-vla-1.c: New test.
>         * gcc.dg/nested-vla-2.c: New test.
>         * gcc.dg/nested-vla-3.c: New test.
>         * gcc.dg/pr106465.c: New test.
>         * gcc.dg/pr107557-1.c: New test.
>         * gcc.dg/pr107557-2.c: New test.
>         * gcc.dg/pr108423-1.c: New test.
>         * gcc.dg/pr108423-2.c: New test.
>         * gcc.dg/pr108423-3.c: New test.
>         * gcc.dg/pr108423-4.c: New test.
>         * gcc.dg/pr108423-5.c: New test.
>         * gcc.dg/pr108423-6.c: New test.
>         * gcc.dg/pr109450-1.c: New test.
>         * gcc.dg/pr109450-2.c: New test.
>         * gcc.dg/typename-vla-2.c: New test.
>         * gcc.dg/typename-vla-3.c: New test.
>         * gcc.dg/typename-vla-4.c: New test.
>         * gcc.misc-tests/gcov-pr85350.c: Adapt.
>
> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> index e537d33f398..c76cbb3115f 100644
> --- a/gcc/c/c-decl.cc
> +++ b/gcc/c/c-decl.cc
> @@ -5371,7 +5371,8 @@ start_decl (struct c_declarator *declarator, struct 
> c_declspecs *declspecs,
>      if (lastdecl != error_mark_node)
>        *lastloc = DECL_SOURCE_LOCATION (lastdecl);
>
> -  if (expr)
> +  /* Make sure the size expression is evaluated at this point.  */
> +  if (expr && !current_scope->parm_flag)
>      add_stmt (fold_convert (void_type_node, expr));
>
>    if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))
> @@ -7500,7 +7501,8 @@ grokdeclarator (const struct c_declarator *declarator,
>                 && c_type_variably_modified_p (type))
>               {
>                 tree bind = NULL_TREE;
> -               if (decl_context == TYPENAME || decl_context == PARM)
> +               if (decl_context == TYPENAME || decl_context == PARM
> +                   || decl_context == FIELD)
>                   {
>                     bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
>                                    NULL_TREE, NULL_TREE);
> @@ -7509,10 +7511,9 @@ grokdeclarator (const struct c_declarator *declarator,
>                     push_scope ();
>                   }
>                 tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
> -               DECL_ARTIFICIAL (decl) = 1;
> -               pushdecl (decl);
> -               finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
> +               add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, 
> decl));
>                 TYPE_NAME (type) = decl;
> +
>                 if (bind)
>                   {
>                     pop_scope ();
> @@ -8711,7 +8712,7 @@ start_struct (location_t loc, enum tree_code code, tree 
> name,
>  tree
>  grokfield (location_t loc,
>            struct c_declarator *declarator, struct c_declspecs *declspecs,
> -          tree width, tree *decl_attrs)
> +          tree width, tree *decl_attrs, tree *expr)
>  {
>    tree value;
>
> @@ -8768,7 +8769,7 @@ grokfield (location_t loc,
>      }
>
>    value = grokdeclarator (declarator, declspecs, FIELD, false,
> -                         width ? &width : NULL, decl_attrs, NULL, NULL,
> +                         width ? &width : NULL, decl_attrs, expr, NULL,
>                           DEPRECATED_NORMAL);
>
>    finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
> @@ -9426,13 +9427,6 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
> tree attributes,
>
>    finish_incomplete_vars (incomplete_vars, toplevel);
>
> -  /* If we're inside a function proper, i.e. not file-scope and not still
> -     parsing parameters, then arrange for the size of a variable sized type
> -     to be bound now.  */
> -  if (building_stmt_list_p () && c_type_variably_modified_p(t))
> -    add_stmt (build_stmt (loc,
> -                         DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
> -
>    if (warn_cxx_compat)
>      warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc);
>
> @@ -10058,6 +10052,7 @@ start_function (struct c_declspecs *declspecs, struct 
> c_declarator *declarator,
>    tree restype, resdecl;
>    location_t loc;
>    location_t result_loc;
> +  tree expr = NULL;
>
>    current_function_returns_value = 0;  /* Assume, until we see it does.  */
>    current_function_returns_null = 0;
> @@ -10069,7 +10064,7 @@ start_function (struct c_declspecs *declspecs, struct 
> c_declarator *declarator,
>    in_statement = 0;
>
>    decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
> -                         &attributes, NULL, NULL, DEPRECATED_NORMAL);
> +                         &attributes, &expr, NULL, DEPRECATED_NORMAL);
>    invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
>
>    /* If the declarator is not suitable for a function definition,
> @@ -10078,6 +10073,11 @@ start_function (struct c_declspecs *declspecs, 
> struct c_declarator *declarator,
>        || TREE_CODE (decl1) != FUNCTION_DECL)
>      return false;
>
> +  /* Nested functions may have variably modified (return) type.
> +     Make sure the size expression is evaluated at this point.  */
> +  if (expr && !current_scope->parm_flag)
> +    add_stmt (fold_convert (void_type_node, expr));
> +
>    loc = DECL_SOURCE_LOCATION (decl1);
>
>    /* A nested function is not global.  */
> @@ -12282,10 +12282,13 @@ declspecs_add_type (location_t loc, struct 
> c_declspecs *specs,
>      }
>    else
>      {
> -      if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
> +      if (TREE_CODE (type) != ERROR_MARK)
>         {
> -         specs->typedef_p = true;
> -         specs->locations[cdw_typedef] = loc;
> +         if (spec.kind == ctsk_typeof)
> +           {
> +             specs->typedef_p = true;
> +             specs->locations[cdw_typedef] = loc;
> +           }
>           if (spec.expr)
>             {
>               if (specs->expr)
> diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
> index 21bc3167ce2..6008ca78c07 100644
> --- a/gcc/c/c-parser.cc
> +++ b/gcc/c/c-parser.cc
> @@ -1541,7 +1541,7 @@ static void c_parser_static_assert_declaration_no_semi 
> (c_parser *);
>  static void c_parser_static_assert_declaration (c_parser *);
>  static struct c_typespec c_parser_enum_specifier (c_parser *);
>  static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
> -static tree c_parser_struct_declaration (c_parser *);
> +static tree c_parser_struct_declaration (c_parser *, tree *);
>  static struct c_typespec c_parser_typeof_specifier (c_parser *);
>  static tree c_parser_alignas_specifier (c_parser *);
>  static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
> @@ -2263,6 +2263,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
> fndef_ok,
>           if (!handled_assume)
>             pedwarn (here, 0, "empty declaration");
>         }
> +      /* we still have to evaluate size expressions */
> +      if (specs->expr)
> +       add_stmt (fold_convert (void_type_node, specs->expr));
>        c_parser_consume_token (parser);
>        if (oacc_routine_data)
>         c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
> @@ -3782,6 +3785,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
>          so we'll be minimizing the number of node traversals required
>          by chainon.  */
>        tree contents;
> +      tree expr = NULL;
>        timevar_push (TV_PARSE_STRUCT);
>        contents = NULL_TREE;
>        c_parser_consume_token (parser);
> @@ -3843,7 +3847,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
>             }
>           /* Parse some comma-separated declarations, but not the
>              trailing semicolon if any.  */
> -         decls = c_parser_struct_declaration (parser);
> +         decls = c_parser_struct_declaration (parser, &expr);
>           contents = chainon (decls, contents);
>           /* If no semicolon follows, either we have a parse error or
>              are at the end of the struct or union and should
> @@ -3874,7 +3878,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
>                                          chainon (attrs, postfix_attrs)),
>                                 struct_info);
>        ret.kind = ctsk_tagdef;
> -      ret.expr = NULL_TREE;
> +      ret.expr = expr;
>        ret.expr_const_operands = true;
>        ret.has_enum_type_specifier = false;
>        timevar_pop (TV_PARSE_STRUCT);
> @@ -3936,7 +3940,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
>     expressions will be diagnosed as non-constant.  */
>
>  static tree
> -c_parser_struct_declaration (c_parser *parser)
> +c_parser_struct_declaration (c_parser *parser, tree *expr)
>  {
>    struct c_declspecs *specs;
>    tree prefix_attrs;
> @@ -3949,7 +3953,7 @@ c_parser_struct_declaration (c_parser *parser)
>        tree decl;
>        ext = disable_extension_diagnostics ();
>        c_parser_consume_token (parser);
> -      decl = c_parser_struct_declaration (parser);
> +      decl = c_parser_struct_declaration (parser, expr);
>        restore_extension_diagnostics (ext);
>        return decl;
>      }
> @@ -3995,7 +3999,7 @@ c_parser_struct_declaration (c_parser *parser)
>
>           ret = grokfield (c_parser_peek_token (parser)->location,
>                            build_id_declarator (NULL_TREE), specs,
> -                          NULL_TREE, &attrs);
> +                          NULL_TREE, &attrs, expr);
>           if (ret)
>             decl_attributes (&ret, attrs, 0);
>         }
> @@ -4056,7 +4060,7 @@ c_parser_struct_declaration (c_parser *parser)
>           if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
>             postfix_attrs = c_parser_gnu_attributes (parser);
>           d = grokfield (c_parser_peek_token (parser)->location,
> -                        declarator, specs, width, &all_prefix_attrs);
> +                        declarator, specs, width, &all_prefix_attrs, expr);
>           decl_attributes (&d, chainon (postfix_attrs,
>                                         all_prefix_attrs), 0);
>           DECL_CHAIN (d) = decls;
> @@ -11729,7 +11733,7 @@ c_parser_objc_class_instance_variables (c_parser 
> *parser)
>         }
>
>        /* Parse some comma-separated declarations.  */
> -      decls = c_parser_struct_declaration (parser);
> +      decls = c_parser_struct_declaration (parser, NULL);
>        if (decls == NULL)
>         {
>           /* There is a syntax error.  We want to skip the offending
> @@ -12868,7 +12872,7 @@ c_parser_objc_at_property_declaration (c_parser 
> *parser)
>    /* 'properties' is the list of properties that we read.  Usually a
>       single one, but maybe more (eg, in "@property int a, b, c;" there
>       are three).  */
> -  tree properties = c_parser_struct_declaration (parser);
> +  tree properties = c_parser_struct_declaration (parser, NULL);
>
>    if (properties == error_mark_node)
>      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
> diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
> index e6b6fe9a40e..7c5234e80fd 100644
> --- a/gcc/c/c-tree.h
> +++ b/gcc/c/c-tree.h
> @@ -656,7 +656,7 @@ extern tree c_simulate_record_decl (location_t, const 
> char *,
>  extern struct c_arg_info *build_arg_info (void);
>  extern struct c_arg_info *get_parm_info (bool, tree);
>  extern tree grokfield (location_t, struct c_declarator *,
> -                      struct c_declspecs *, tree, tree *);
> +                      struct c_declspecs *, tree, tree *, tree *);
>  extern tree groktypename (struct c_type_name *, tree *, bool *);
>  extern tree grokparm (const struct c_parm *, tree *);
>  extern tree implicitly_declare (location_t, tree);
> diff --git a/gcc/function.cc b/gcc/function.cc
> index edf0b2ec6cf..e50d9601509 100644
> --- a/gcc/function.cc
> +++ b/gcc/function.cc
> @@ -3873,30 +3873,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
> @@ -3932,14 +3908,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 ade6e335da7..a220886d973 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 
> *,
> @@ -17448,7 +17449,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)
> @@ -17556,6 +17557,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)
> +{
> +  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/nested-vla-1.c 
> b/gcc/testsuite/gcc.dg/nested-vla-1.c
> new file mode 100644
> index 00000000000..408a68524d8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/nested-vla-1.c
> @@ -0,0 +1,37 @@
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu99" } */
> +
> +
> +int main()
> +{
> +       int n = 1;
> +
> +       struct foo { char x[++n]; } bar(void) { }
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof(bar()))
> +               __builtin_abort();
> +
> +       n = 1;
> +
> +       struct bar { char x[++n]; } (*bar2)(void) = bar;        /* { 
> dg-warning "incompatible pointer type" } */
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof((*bar2)()))
> +               __builtin_abort();
> +
> +       n = 1;
> +
> +       struct { char x[++n]; } *bar3(void) { }
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof(*bar3()))
> +               __builtin_abort();
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/nested-vla-2.c 
> b/gcc/testsuite/gcc.dg/nested-vla-2.c
> new file mode 100644
> index 00000000000..504eec48c80
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/nested-vla-2.c
> @@ -0,0 +1,33 @@
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu99" } */
> +
> +
> +int main()
> +{
> +       int n = 1;
> +
> +       typeof(char (*)[++n]) bar(void) { }
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof(*bar()))
> +               __builtin_abort();
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       n = 1;
> +
> +       typeof(char (*)[++n]) (*bar2)(void) = bar;
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof(*(*bar2)()))
> +               __builtin_abort();
> +
> +       if (2 != n)
> +               __builtin_abort();
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/nested-vla-3.c 
> b/gcc/testsuite/gcc.dg/nested-vla-3.c
> new file mode 100644
> index 00000000000..e0e70b651ca
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/nested-vla-3.c
> @@ -0,0 +1,28 @@
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu99" } */
> +
> +
> +int main()
> +{
> +       int n = 1;
> +
> +       char (*bar(void))[++n] { }
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof(*bar()))
> +               __builtin_abort();
> +
> +       n = 1;
> +
> +       char (*(*bar2)(void))[++n] = bar;
> +
> +       if (2 != n)
> +               __builtin_abort();
> +
> +       if (2 != sizeof(*(*bar2)()))
> +               __builtin_abort();
> +
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr106465.c b/gcc/testsuite/gcc.dg/pr106465.c
> new file mode 100644
> index 00000000000..b03e2442f12
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr106465.c
> @@ -0,0 +1,86 @@
> +/* PR c/106465
> + * { dg-do run }
> + * { dg-options "-std=gnu99" }
> + * */
> +
> +int main()
> +{
> +       int n = 3;
> +
> +       void g1(int m, struct { char p[++m]; }* b)      /* { dg-warning 
> "anonymous struct" } */
> +       {
> +               if (3 != m)
> +                       __builtin_abort();
> +
> +               if (3 != sizeof(b->p))
> +                       __builtin_abort();
> +       }
> +
> +       void g2(struct { char p[++n]; }* b)     /* { dg-warning "anonymous 
> struct" } */
> +       {
> +               if (4 != n)
> +                       __builtin_abort();
> +
> +               if (4 != sizeof(b->p))
> +                       __builtin_abort();
> +       }
> +
> +       void g2b(struct { char (*p)[++n]; }* b) /* { dg-warning "anonymous 
> struct" } */
> +       {
> +               if (5 != n)
> +                       __builtin_abort();
> +
> +               if (5 != sizeof(*b->p))
> +                       __builtin_abort();
> +       }
> +
> +       if (3 != n)
> +               __builtin_abort();
> +
> +       g1(2, (void*)0);
> +       g2((void*)0);
> +       g2b((void*)0);
> +       n--;
> +
> +       if (4 != n)
> +               __builtin_abort();
> +
> +       struct foo { char (*p)[++n]; } x;
> +
> +       if (5 != n)
> +               __builtin_abort();
> +
> +       struct bar { char (*p)[++n]; };
> +
> +       if (6 != n)
> +               __builtin_abort();
> +
> +       auto struct z { char (*p)[++n]; } g3(void);
> +
> +       if (7 != n)
> +               __builtin_abort();
> +
> +       struct z g3(void) { };
> +
> +       if (7 != n)
> +               __builtin_abort();
> +
> +       struct { char (*p)[++n]; } g4(void) { };
> +
> +       if (8 != n)
> +               __builtin_abort();
> +
> +       __auto_type u = g3();
> +
> +       if (8 != n)
> +               __builtin_abort();
> +
> +       if (5 != sizeof *x.p)
> +               __builtin_abort();
> +
> +       if (7 != sizeof *u.p)
> +               __builtin_abort();
> +
> +       return 0;
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr107557-1.c 
> b/gcc/testsuite/gcc.dg/pr107557-1.c
> new file mode 100644
> index 00000000000..88c248b6564
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr107557-1.c
> @@ -0,0 +1,24 @@
> +/* PR107557
> + * { dg-do compile }
> + * { dg-options "-flto -fsanitize=undefined -fexceptions 
> -Wno-incompatible-pointer-types" }
> + */
> +
> +
> +int c[1][3*2];
> +int f(int * const m, int (**v)[*m * 2])
> +{
> +       return &(c[0][*m]) == &((*v)[0][*m]);
> +}
> +int test(int n, int (*(*fn)(void))[n])
> +{
> +       return (*fn())[0];
> +}
> +int main()
> +{
> +       int m = 3;
> +       int (*d)[3*2] = c;
> +       int (*fn[m])(void);
> +       return f(&m, &d) + test(m, &fn);
> +}
> +
> +
> diff --git a/gcc/testsuite/gcc.dg/pr107557-2.c 
> b/gcc/testsuite/gcc.dg/pr107557-2.c
> new file mode 100644
> index 00000000000..2d26bb0b16a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr107557-2.c
> @@ -0,0 +1,23 @@
> +/* PR107557
> + * { dg-do compile }
> + * { dg-options "-flto -fsanitize=undefined -fexceptions 
> -Wno-incompatible-pointer-types" }
> + */
> +
> +
> +int c[1][3*2];
> +int f(int * const m, int (**(*v))[*m * 2])
> +{
> +       return &(c[0][*m]) == &((*v)[0][*m]);   /* { dg-warning "lacks a 
> cast" } */
> +}
> +int test(int n, int (*(*(*fn))(void))[n])
> +{
> +       return (*(*fn)())[0];
> +}
> +int main()
> +{
> +       int m = 3;
> +       int (*d)[3*2] = c;
> +       int (*fn[m])(void);
> +       return f(&m, &d) + test(m, &fn);
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr108423-1.c 
> b/gcc/testsuite/gcc.dg/pr108423-1.c
> new file mode 100644
> index 00000000000..0c98d1d46b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr108423-1.c
> @@ -0,0 +1,16 @@
> +/* PR108423
> + * { dg-do compile }
> + * { dg-options "-O2 -Wno-int-conversion -Wno-incompatible-pointer-types" }
> + */
> +int f (int n, int (**(*a)(void))[n])
> +{
> +       return (*a())[0];
> +}
> +int g ()
> +{
> +       int m = 3;
> +       int (*a[m])(void);
> +       return f(m, &a);
> +}
> +
> +
> diff --git a/gcc/testsuite/gcc.dg/pr108423-2.c 
> b/gcc/testsuite/gcc.dg/pr108423-2.c
> new file mode 100644
> index 00000000000..006e45a9629
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr108423-2.c
> @@ -0,0 +1,16 @@
> +/* PR108423
> + * { dg-do compile }
> + * { dg-options "-O2" }
> + */
> +
> +void f(int n, int (*a(void))[n])
> +{
> +       (a())[0];
> +}
> +
> +void g(void)
> +{
> +       int (*a(void))[1];
> +       f(1, a);
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr108423-3.c 
> b/gcc/testsuite/gcc.dg/pr108423-3.c
> new file mode 100644
> index 00000000000..c1987c42b40
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr108423-3.c
> @@ -0,0 +1,17 @@
> +/* PR108423
> + * { dg-do compile }
> + * { dg-options "-O2" }
> + */
> +
> +void f(int n, int (*(*b)(void))[n])
> +{
> +    sizeof (*(*b)());
> +}
> +
> +int (*a(void))[1];
> +
> +void g(void)
> +{
> +           f(1, &a);
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr108423-4.c 
> b/gcc/testsuite/gcc.dg/pr108423-4.c
> new file mode 100644
> index 00000000000..91336f3f283
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr108423-4.c
> @@ -0,0 +1,17 @@
> +/* PR108423
> + * { dg-do compile }
> + * { dg-options "-O2" }
> + */
> +
> +void f(int n, int (*a(void))[n])
> +{
> +    sizeof (*a());
> +}
> +
> +int (*a(void))[1];
> +
> +void g(void)
> +{
> +           f(1, a);
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr108423-5.c 
> b/gcc/testsuite/gcc.dg/pr108423-5.c
> new file mode 100644
> index 00000000000..7e4fffb2870
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr108423-5.c
> @@ -0,0 +1,17 @@
> +/* PR108423
> + * { dg-do compile }
> + * { dg-options "-O2" }
> + */
> +
> +void f(int n, int (*(*a)(void))[n])
> +{
> +    sizeof ((*a)());
> +}
> +
> +int (*a(void))[1];
> +
> +void g(void)
> +{
> +           f(1, a);
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr108423-6.c 
> b/gcc/testsuite/gcc.dg/pr108423-6.c
> new file mode 100644
> index 00000000000..c36e45aaf45
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr108423-6.c
> @@ -0,0 +1,16 @@
> +/* PR108423
> + * { dg-do compile }
> + * { dg-options "-O2" }
> + */
> +
> +void f(int n, int (*a())[n])
> +{
> +       (a())[0];
> +}
> +
> +void g(void)
> +{
> +       int (*a())[1];
> +       f(1, a);
> +}
> +
> 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/typename-vla-2.c 
> b/gcc/testsuite/gcc.dg/typename-vla-2.c
> new file mode 100644
> index 00000000000..9cdd9467544
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/typename-vla-2.c
> @@ -0,0 +1,16 @@
> +/* { dg-do run }
> + * { dg-options "-std=c99" }
> + * */
> +
> +static int f(int n, char (*x)[sizeof (*(++n, (char (*)[n])0))])
> +{
> +  return sizeof *x;
> +}
> +
> +int main (void)
> +{
> +  if (2 != f(1, 0))
> +    __builtin_abort ();
> +  return 0;
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/typename-vla-3.c 
> b/gcc/testsuite/gcc.dg/typename-vla-3.c
> new file mode 100644
> index 00000000000..4c7c56bff8e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/typename-vla-3.c
> @@ -0,0 +1,16 @@
> +/* { dg-do run }
> + * { dg-options "-std=c99" }
> + * */
> +
> +static int f(int n, char (*x)[sizeof *(++n, (struct { char (*x)[n]; }){ 0 
> }).x]) /* { dg-warning "anonymous struct" } */
> +{
> +  return sizeof *x;
> +}
> +
> +int main (void)
> +{
> +  if (2 != f(1, 0))
> +    __builtin_abort ();
> +  return 0;
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/typename-vla-4.c 
> b/gcc/testsuite/gcc.dg/typename-vla-4.c
> new file mode 100644
> index 00000000000..a05c782b555
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/typename-vla-4.c
> @@ -0,0 +1,23 @@
> +/* { dg-do run }
> + * { dg-options "-std=gnu99" }
> + * */
> +
> +int main()
> +{
> +       int n = 1;
> +       sizeof(int[n++]);
> +       typeof(int[n++]);                       /* { dg-warning "empty 
> declaration" } */
> +       struct { int x[n++]; };                 /* { dg-warning "no instance" 
> } */
> +       struct foo { int x[n++]; };
> +       struct { int x[n++]; } x;
> +       struct bar { int x[n++]; } y;
> +       (int(*)[n++])0;
> +       (typeof(int(*)[n++]))0;
> +       (struct { int x[n++]; }*)0;
> +       (struct q { int x[n++]; }*)0;
> +       typeof(struct { int x[n++]; });         /* { dg-warning "empty 
> declaration" } */
> +       typeof(struct r { int x[n++]; });       /* { dg-warning "empty 
> declaration" } */
> +
> +       if (13 != n)
> +               __builtin_abort();
> +}
> diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c 
> b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
> index 0383b81fdfb..a42bf1282b2 100644
> --- a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
> +++ b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
> @@ -4,7 +4,7 @@
>  int main (void)
>  {
>    const int t = 2; /* count(1) */
> -  struct s1 {  /* count(1) */
> +  struct s1 {  /* count(-) */
>      int x;
>      int g[t];
>    };
>
>
>
>

Reply via email to