diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 92c83e1bf10de1ee627d0e562835079a212af725..039a66fef09c28629817f06b904813f96d349d30 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -6618,12 +6618,10 @@ smallest_type_quals_location (const location_t *locations, 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) +add_decl_expr (location_t loc, tree type, tree *expr, bool set_name_p) { tree bind = NULL_TREE; - if (decl_context == TYPENAME || decl_context == PARM - || decl_context == FIELD) + if (expr) { bind = build3 (BIND_EXPR, void_type_node, NULL_TREE, NULL_TREE, NULL_TREE); @@ -6636,7 +6634,8 @@ add_decl_expr (location_t loc, enum decl_context decl_context, tree type, pushdecl (decl); DECL_ARTIFICIAL (decl) = 1; add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl)); - TYPE_NAME (type) = decl; + if (set_name_p) + TYPE_NAME (type) = decl; if (bind) { @@ -7635,7 +7634,12 @@ grokdeclarator (const struct c_declarator *declarator, type has a name/declaration of it's own, but special attention 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); + { + bool bind_p = decl_context == TYPENAME + || decl_context == FIELD + || decl_context == PARM; + add_decl_expr (loc, type, bind_p ? expr : NULL, true); + } type = c_build_pointer_type (type); @@ -7900,7 +7904,12 @@ grokdeclarator (const struct c_declarator *declarator, /* 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); + { + bool bind_p = decl_context == TYPENAME + || decl_context == FIELD + || decl_context == PARM; + add_decl_expr (loc, type, bind_p ? expr : NULL, true); + } type = c_build_pointer_type (type); type_quals = array_ptr_quals; @@ -9257,7 +9266,8 @@ is_flexible_array_member_p (bool is_last_field, tree finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, - class c_struct_parse_info *enclosing_struct_parse_info) + class c_struct_parse_info *enclosing_struct_parse_info, + tree *expr) { tree x; bool toplevel = file_scope == current_scope; @@ -9595,6 +9605,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, finish_incomplete_vars (incomplete_vars, toplevel); + /* Make sure a DECL_EXPR is created for structs with VLA members. + Because we do not know the context, we always pass expr + to force creation of a BIND_EXPR which is required in some + contexts. */ + if (c_type_variably_modified_p (t)) + add_decl_expr (loc, t, expr, false); + if (warn_cxx_compat) warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc); diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 5700ccccc4930e8a95c2228a01c395b2f6fd7f6b..0c301015d8803ae750dfb10a6095615a24a7ed87 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -4087,7 +4087,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) ret.spec = finish_struct (struct_loc, type, nreverse (contents), chainon (std_attrs, chainon (attrs, postfix_attrs)), - struct_info); + struct_info, &expr); ret.kind = ctsk_tagdef; ret.expr = expr; ret.expr_const_operands = true; diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index d0bdc3df2c2c2205052cc9478887eb4c0aeab348..b325723a7345d502d8d8a539331747c7ee93709c 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -656,7 +656,8 @@ extern void finish_decl (tree, location_t, tree, tree, tree); extern tree finish_enum (tree, tree, tree); extern void finish_function (location_t = input_location); extern tree finish_struct (location_t, tree, tree, tree, - class c_struct_parse_info *); + class c_struct_parse_info *, + tree *expr = NULL); extern tree c_simulate_enum_decl (location_t, const char *, vec<string_int_pair> *); extern tree c_simulate_record_decl (location_t, const char *, diff --git a/gcc/testsuite/gcc.dg/pr112488-1.c b/gcc/testsuite/gcc.dg/pr112488-1.c new file mode 100644 index 0000000000000000000000000000000000000000..b53295c4366da0aad1ccd097766191ef212cc4b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112488-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } + * { dg-options "-O1" } */ + +extern void abort(void); + +int test(int *n) { + struct T { char a[*n], b[*n]; }; + return sizeof(struct T) - sizeof(struct T); +} + +void f1(int *p) { + if (!test(p)) abort(); +} + diff --git a/gcc/testsuite/gcc.dg/pr112488-2.c b/gcc/testsuite/gcc.dg/pr112488-2.c new file mode 100644 index 0000000000000000000000000000000000000000..3f0fc43eeb630be49ba7cd1c5a407dcef784427c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112488-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } + * { dg-options "-std=gnu23 -O1" } */ + +extern void abort(void); + +int test(int *n, struct T { char a[*n], b[*n]; }*) { /* { dg-warning "declared inside parameter list" } */ + return sizeof(struct T) - sizeof(struct T); +} + +void f1(int *p) { + if (test(p, 0)) abort(); +} + diff --git a/gcc/testsuite/gcc.dg/pr112898.c b/gcc/testsuite/gcc.dg/pr112898.c new file mode 100644 index 0000000000000000000000000000000000000000..395f3afaf2e439de4c381661bfbd4e563ef5cf18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112898.c @@ -0,0 +1,9 @@ +/* { dg-do compile } + { dg-options "-O2 -finstrument-functions-once" } */ + +void func(int n) +{ + struct T { int x[n]; }; + struct T *t = __builtin_malloc(sizeof *t); +} + diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c index a42bf1282b2f8ac3eb03c8f87216041cc2eb3ddd..0383b81fdfb6c3d101e940d3ff9fea80ad9f21c2 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(-) */ + struct s1 { /* count(1) */ int x; int g[t]; };