From patchwork Thu May 18 12:46:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Uecker X-Patchwork-Id: 1783252 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=d9h5065F; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QMV9R003Bz20dn for ; Thu, 18 May 2023 22:47:06 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E43283857031 for ; Thu, 18 May 2023 12:47:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E43283857031 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1684414023; bh=W1ZdW7zZ8MNV4FZsfy8+fpkpkDbYQ1wK3F3HuEkyTTk=; h=Subject:To:Cc:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=d9h5065F28HyJrLzyL2Dcp+RsxEQnHWHAXmWxuX+rZs4TbQ5vXkhF1Kd+muw3wrC7 1oHB/tPMzpcO/8fsLMibKvR3kv/ebG6nuzUwOiiDXNEztIOdBLmBM6vFGhc/spO5gi a5cykRQrwogFn+QF8ddVP3/zlJeFVVW+cDoOUW5U= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mailrelay.tugraz.at (mailrelay.tugraz.at [129.27.2.202]) by sourceware.org (Postfix) with ESMTPS id A13113858CDB for ; Thu, 18 May 2023 12:46:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A13113858CDB Received: from vra-168-227.tugraz.at (vra-168-227.tugraz.at [129.27.168.227]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4QMV8q53mjz3wCT; Thu, 18 May 2023 14:46:35 +0200 (CEST) Message-ID: <4769c136aec5728c2954e39bfbca2af27c390593.camel@tugraz.at> Subject: [PING] [C PATCH] Fix ICEs related to VM types in C [PR106465, PR107557, PR108423, PR109450] To: gcc-patches@gcc.gnu.org Cc: joseph@codesourcery.com, richard.guenther@gmail.com Date: Thu, 18 May 2023 14:46:34 +0200 User-Agent: Evolution 3.38.3-1+deb11u1 MIME-Version: 1.0 X-TUG-Backscatter-control: G/VXY7/6zeyuAY/PU2/0qw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.116 X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Martin Uecker via Gcc-patches From: Martin Uecker Reply-To: Martin Uecker Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Ping. Ok, for trunk? Bootstrapped and tested on x86_64-linux-gnu with no regressions. Fix ICEs related to VM types in C [PR106465, PR107557, PR108423, 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 90d7cd27cd5..f63c1108ab5 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5378,7 +5378,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)) @@ -7510,7 +7511,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); @@ -7519,10 +7521,11 @@ 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); + DECL_ARTIFICIAL (decl) = 1; + add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl)); TYPE_NAME (type) = decl; + if (bind) { pop_scope (); @@ -8721,7 +8724,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; @@ -8778,7 +8781,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); @@ -9436,13 +9439,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); @@ -10068,6 +10064,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; @@ -10079,7 +10076,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, @@ -10088,6 +10085,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. */ @@ -12292,10 +12294,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 c9f06930e3a..8e9948dff89 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; @@ -11732,7 +11736,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 @@ -12871,7 +12875,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 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 3740a8979af..88ca2655ce4 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 *oacc_declare_returns; static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *, @@ -17467,7 +17468,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) @@ -17575,6 +17576,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.dg/typename-vla-5.c b/gcc/testsuite/gcc.dg/typename-vla-5.c new file mode 100644 index 00000000000..b959cb924af --- /dev/null +++ b/gcc/testsuite/gcc.dg/typename-vla-5.c @@ -0,0 +1,13 @@ +/* { dg-do run } + * { dg-options "-std=gnu99" } + * */ + +int +main (void) +{ + int a = 1; + if (sizeof (*(++a, (struct { char (*x)[a]; }){ 0 }).x) != 2) + __builtin_abort (); +} + + diff --git a/gcc/testsuite/gcc.dg/typename-vla-6.c b/gcc/testsuite/gcc.dg/typename-vla-6.c new file mode 100644 index 00000000000..6dfb126870f --- /dev/null +++ b/gcc/testsuite/gcc.dg/typename-vla-6.c @@ -0,0 +1,15 @@ +/* { dg-do run } + * { dg-options "-std=gnu99" } + * */ + + + +int +main (void) +{ + int a = 1; + if ((++a, sizeof(*((struct { char (*x)[a]; }){ 0 }).x)) != 2) + __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]; };