From patchwork Thu Nov 16 21:39:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Uecker X-Patchwork-Id: 1864890 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=tugraz.at header.i=@tugraz.at header.a=rsa-sha256 header.s=mailrelay header.b=lw6TPVBD; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SWYN82RFyz1yRy for ; Fri, 17 Nov 2023 08:39:52 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BD3123858D28 for ; Thu, 16 Nov 2023 21:39:49 +0000 (GMT) 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 4699F3858D28 for ; Thu, 16 Nov 2023 21:39:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4699F3858D28 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=tugraz.at Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tugraz.at ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4699F3858D28 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=129.27.2.202 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700170779; cv=none; b=LSwkIKpz9XyoQlUrs0p/e0nzbCwhD0jMFv5h7Yg9fWKYFJTh/0MdIAdrNRH1izQAcX/1tADL9l4WNf6fGnCiU3totRKbnKF1DE3sMSYrXFlW98y8C8TWlCAF8K8JB9fIko8ABKibnbk5OQ2dKIkW4i08g81caKmtN/QdJYrii5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700170779; c=relaxed/simple; bh=2yAd6LJeZwVwZOz9NllBtroyZVgle+vVHN0Zugfii+U=; h=DKIM-Signature:Message-ID:Subject:From:To:Date:MIME-Version; b=d1B5oPcxX7URKBduRvvZZgHVGAB8C6R+sBLL9CFl/kJn5CgeSxxJc7RnQ8y6BQN8k9ojxKfJTi0GIc6eNSoSilg81nZipcQz7Y2uGX00FV+T6IMqMdBL3psSV+mrFnXdnGTw2tnvwHIyEsCunT/a1dnpTtsxrLr7GCI6mRceWro= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from vra-171-78.tugraz.at (vra-171-78.tugraz.at [129.27.171.78]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4SWYMf6JWvz1LM0K; Thu, 16 Nov 2023 22:39:26 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4SWYMf6JWvz1LM0K DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1700170767; bh=r9cHizGsYq9cXW2Mtm0+skLtgE8aDXEzxbfHA2OEIjA=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=lw6TPVBDqhx/2jo1HF7rWWGLclZ0yhdXRlDikXaHgIaT4a0iCX5SZfwuHy9JaagU7 JBXR50QEP8Ap9Ye9vQHgnjT93IkUxI/exGusoZi1333LAG9BeNydwlMz73trlSIWxT C+7lmqgFMXTBTQFpsNQOWtT7Sprb5BinqXbE0dFQ= Message-ID: <223aa096afbdbb177d4ad5245696d439ad4cf87f.camel@tugraz.at> Subject: [PATCH 3/4] c23: aliasing of compatible tagged types From: Martin Uecker To: gcc-patches@gcc.gnu.org Cc: Joseph Myers Date: Thu, 16 Nov 2023 22:39:26 +0100 In-Reply-To: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at> References: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at> User-Agent: Evolution 3.46.4-2 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.117 X-Spam-Status: No, score=-11.1 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Tell the backend which types are equivalent by setting TYPE_CANONICAL to one struct in the set of equivalent structs. Structs are considered equivalent by ignoring all sizes of arrays nested in types below field level. gcc/c: * c-decl.cc (c_struct_hasher): Hash stable for struct types. (c_struct_hasher::hash, c_struct_hasher::equal): New functions. (finish_struct): Set TYPE_CANONICAL to first struct in equivalence class. * c-objc-common.cc (c_get_alias_set): Let structs or unions with variable size alias anything. * c-tree.h (comptypes_equiv): New prototype. * c-typeck.cc (comptypes_equiv): New function. (comptypes_internal): Implement equivalence mode. (tagged_types_tu_compatible): Implement equivalence mode. gcc/testsuite: * gcc.dg/c23-tag-2.c: Activate. * gcc.dg/c23-tag-6.c: Activate. * gcc.dg/c23-tag-alias-1.c: New test. * gcc.dg/c23-tag-alias-2.c: New test. * gcc.dg/c23-tag-alias-3.c: New test. * gcc.dg/c23-tag-alias-4.c: New test. * gcc.dg/c23-tag-alias-5.c: New test. * gcc.dg/c23-tag-alias-6.c: New test. * gcc.dg/c23-tag-alias-7.c: New test. * gcc.dg/c23-tag-alias-8.c: New test. * gcc.dg/gnu23-tag-alias-1.c: New test. --- gcc/c/c-decl.cc | 48 +++++++++++++ gcc/c/c-objc-common.cc | 5 ++ gcc/c/c-tree.h | 1 + gcc/c/c-typeck.cc | 31 ++++++++ gcc/testsuite/gcc.dg/c23-tag-2.c | 4 +- gcc/testsuite/gcc.dg/c23-tag-5.c | 5 +- gcc/testsuite/gcc.dg/c23-tag-alias-1.c | 48 +++++++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-2.c | 73 +++++++++++++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-3.c | 48 +++++++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-4.c | 73 +++++++++++++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-5.c | 30 ++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-6.c | 77 ++++++++++++++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-7.c | 86 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/c23-tag-alias-8.c | 90 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/gnu23-tag-alias-1.c | 33 +++++++++ 15 files changed, 648 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-1.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-2.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-3.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-4.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-5.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-6.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-7.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-alias-8.c create mode 100644 gcc/testsuite/gcc.dg/gnu23-tag-alias-1.c diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index e5d48c3fa56..d0a405087c3 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -634,6 +634,36 @@ public: auto_vec typedefs_seen; }; + +/* Hash table for structs and unions. */ +struct c_struct_hasher : ggc_ptr_hash +{ + static hashval_t hash (tree t); + static bool equal (tree, tree); +}; + +/* Hash an RECORD OR UNION. */ +hashval_t +c_struct_hasher::hash (tree type) +{ + inchash::hash hstate; + + hstate.add_int (TREE_CODE (type)); + hstate.add_object (TYPE_NAME (type)); + + return hstate.end (); +} + +/* Compare two RECORD or UNION types. */ +bool +c_struct_hasher::equal (tree t1, tree t2) +{ + return comptypes_equiv_p (t1, t2); +} + +/* All tagged typed so that TYPE_CANONICAL can be set correctly. */ +static GTY (()) hash_table *c_struct_htab; + /* Information for the struct or union currently being parsed, or NULL if not parsing a struct or union. */ static class c_struct_parse_info *struct_parse_info; @@ -9646,6 +9676,24 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, C_TYPE_BEING_DEFINED (t) = 0; + /* Set type canonical based on equivalence class. */ + if (flag_isoc23) + { + if (NULL == c_struct_htab) + c_struct_htab = hash_table::create_ggc (61); + + hashval_t hash = c_struct_hasher::hash (t); + + tree *e = c_struct_htab->find_slot_with_hash (t, hash, INSERT); + if (*e) + TYPE_CANONICAL (t) = *e; + else + { + TYPE_CANONICAL (t) = t; + *e = t; + } + } + tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)); for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) { diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index c8f49aa2370..738afbad770 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -389,6 +389,11 @@ c_get_alias_set (tree t) if (TREE_CODE (t) == ENUMERAL_TYPE) return get_alias_set (ENUM_UNDERLYING_TYPE (t)); + /* Structs with variable size can alias different incompatible + structs. Let them alias anything. */ + if (RECORD_OR_UNION_TYPE_P (t) && C_TYPE_VARIABLE_SIZE (t)) + return 0; + return c_common_get_alias_set (t); } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index a5dd9a37944..ece5b6a5d26 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -758,6 +758,7 @@ extern tree require_complete_type (location_t, tree); extern bool same_translation_unit_p (const_tree, const_tree); extern int comptypes (tree, tree); extern bool comptypes_same_p (tree, tree); +extern int comptypes_equiv_p (tree, tree); extern int comptypes_check_different_types (tree, tree, bool *); extern int comptypes_check_enum_int (tree, tree, bool *); extern bool c_mark_addressable (tree, bool = false); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 8116c9b3e68..262b04c582f 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -1063,6 +1063,7 @@ struct comptypes_data { bool different_types_p; bool warning_needed; bool anon_field; + bool equiv; const struct tagged_tu_seen_cache* cache; }; @@ -1123,6 +1124,21 @@ comptypes_check_different_types (tree type1, tree type2, return ret ? (data.warning_needed ? 2 : 1) : 0; } + + +/* Like comptypes, but if it returns nonzero for struct and union + types considered equivalent for aliasing purposes. */ + +int +comptypes_equiv_p (tree type1, tree type2) +{ + struct comptypes_data data = { }; + data.equiv = true; + bool ret = comptypes_internal (type1, type2, &data); + + return ret; +} + /* Return true if TYPE1 and TYPE2 are compatible types for assignment or various other operations. If they are compatible but a warning may @@ -1250,6 +1266,9 @@ comptypes_internal (const_tree type1, const_tree type2, if ((d1 == NULL_TREE) != (d2 == NULL_TREE)) data->different_types_p = true; + /* ignore size mismatches */ + if (data->equiv) + return 1; /* Sizes must match unless one is missing or variable. */ if (d1 == NULL_TREE || d2 == NULL_TREE || d1 == d2) return true; @@ -1467,6 +1486,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2))) return false; + if (data->equiv && (C_TYPE_VARIABLE_SIZE (t1) || C_TYPE_VARIABLE_SIZE (t2))) + return 0; + for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2)) @@ -1486,6 +1508,15 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), DECL_FIELD_BIT_OFFSET (s2)) != 1) return false; + + tree st1 = TYPE_SIZE (TREE_TYPE (s1)); + tree st2 = TYPE_SIZE (TREE_TYPE (s2)); + + if (data->equiv + && st1 && TREE_CODE (st1) == INTEGER_CST + && st2 && TREE_CODE (st2) == INTEGER_CST + && !tree_int_cst_equal (st1, st2)) + return 0; } return true; diff --git a/gcc/testsuite/gcc.dg/c23-tag-2.c b/gcc/testsuite/gcc.dg/c23-tag-2.c index 5dd4a21e9df..e28c2b5eea2 100644 --- a/gcc/testsuite/gcc.dg/c23-tag-2.c +++ b/gcc/testsuite/gcc.dg/c23-tag-2.c @@ -1,5 +1,5 @@ -/* { dg-do compile { target { ! "*-*-*" } } } - * { dg-options "-std=c23" } +/* { dg-do compile } + * { dg-options "-std=c2x" } */ // compatibility of structs in assignment diff --git a/gcc/testsuite/gcc.dg/c23-tag-5.c b/gcc/testsuite/gcc.dg/c23-tag-5.c index ff40d07aef1..95a04bf9b0e 100644 --- a/gcc/testsuite/gcc.dg/c23-tag-5.c +++ b/gcc/testsuite/gcc.dg/c23-tag-5.c @@ -1,5 +1,6 @@ -/* { dg-do run { target { ! "*-*-*" } } } - * { dg-options "-std=c23" } +/* + * { dg-do run } + * { dg-options "-std=c2x" } */ // nesting and parameters diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-1.c b/gcc/testsuite/gcc.dg/c23-tag-alias-1.c new file mode 100644 index 00000000000..6704ba9c8b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-1.c @@ -0,0 +1,48 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -O2" } + */ + + +struct foo { int x; }; + +int test_foo(struct foo* a, void* b) +{ + a->x = 1; + + struct foo { int x; }* p = b; + p->x = 2; + + return a->x; +} + + +enum bar { A = 1, B = 3 }; + +int test_bar(enum bar* a, void* b) +{ + *a = A; + + enum bar { A = 1, B = 3 }* p = b; + *p = B; + + return *a; +} + + +int main() +{ + struct foo y; + + if (2 != test_foo(&y, &y)) + __builtin_abort(); + + enum bar z; + + if (A == test_bar(&z, &z)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-2.c b/gcc/testsuite/gcc.dg/c23-tag-alias-2.c new file mode 100644 index 00000000000..555c30a8501 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-2.c @@ -0,0 +1,73 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -O2" } + */ + + +struct foo { int x; }; + +int test_foo1(struct foo* a, void* b) +{ + a->x = 1; + + struct foo { int x; int y; }* p = b; + p->x = 2; + + return a->x; +} + +int test_foo2(struct foo* a, void* b) +{ + a->x = 1; + + struct fox { int x; }* p = b; + p->x = 2; + + return a->x; +} + +enum bar { A = 1, B = 3, C = 5, D = 9 }; + +int test_bar1(enum bar* a, void* b) +{ + *a = A; + + enum bar { A = 1, B = 3, C = 6, D = 9 }* p = b; + *p = B; + + return *a; +} + +int test_bar2(enum bar* a, void* b) +{ + *a = A; + + enum baX { A = 1, B = 3, C = 5, D = 9 }* p = b; + *p = B; + + return *a; +} + + +int main() +{ + struct foo y; + + if (1 != test_foo1(&y, &y)) + __builtin_abort(); + + if (1 != test_foo2(&y, &y)) + __builtin_abort(); + + enum bar z; + + if (A == test_bar1(&z, &z)) + __builtin_abort(); + + if (A == test_bar2(&z, &z)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-3.c b/gcc/testsuite/gcc.dg/c23-tag-alias-3.c new file mode 100644 index 00000000000..122e8806af8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-3.c @@ -0,0 +1,48 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -flto -O2" } + */ + + +struct foo { int x; }; + +int test_foo(struct foo* a, void* b) +{ + a->x = 1; + + struct foo { int x; }* p = b; + p->x = 2; + + return a->x; +} + + +enum bar { A = 1, B = 3 }; + +int test_bar(enum bar* a, void* b) +{ + *a = A; + + enum bar { A = 1, B = 3 }* p = b; + *p = B; + + return *a; +} + + +int main() +{ + struct foo y; + + if (2 != test_foo(&y, &y)) + __builtin_abort(); + + enum bar z; + + if (A == test_bar(&z, &z)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-4.c b/gcc/testsuite/gcc.dg/c23-tag-alias-4.c new file mode 100644 index 00000000000..d86a174f4a2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-4.c @@ -0,0 +1,73 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -flto -O2" } + */ + + +struct foo { int x; }; + +int test_foo1(struct foo* a, void* b) +{ + a->x = 1; + + struct foo { int x; int y; }* p = b; + p->x = 2; + + return a->x; +} + +int test_foo2(struct foo* a, void* b) +{ + a->x = 1; + + struct fox { int x; }* p = b; + p->x = 2; + + return a->x; +} + +enum bar { A = 1, B = 3, C = 5, D = 9 }; + +int test_bar1(enum bar* a, void* b) +{ + *a = A; + + enum bar { A = 1, B = 3, C = 6, D = 9 }* p = b; + *p = B; + + return *a; +} + +int test_bar2(enum bar* a, void* b) +{ + *a = A; + + enum baX { A = 1, B = 3, C = 5, D = 9 }* p = b; + *p = B; + + return *a; +} + + +int main() +{ + struct foo y; + + if (1 != test_foo1(&y, &y)) + __builtin_abort(); + + if (1 != test_foo2(&y, &y)) + __builtin_abort(); + + enum bar z; + + if (A == test_bar1(&z, &z)) + __builtin_abort(); + + if (A == test_bar2(&z, &z)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-5.c b/gcc/testsuite/gcc.dg/c23-tag-alias-5.c new file mode 100644 index 00000000000..4e956720143 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-5.c @@ -0,0 +1,30 @@ +/* { dg-do run } + * { dg-options "-std=c23 -O2" } + */ + +// not sure this is wise, but this was already like thi sbefore + +typedef struct { int x; } foo_t; + +int test_foo(foo_t* a, void* b) +{ + a->x = 1; + + struct { int x; }* p = b; + p->x = 2; + + return a->x; +} + + +int main() +{ + foo_t y; + + if (1 != test_foo(&y, &y)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-6.c b/gcc/testsuite/gcc.dg/c23-tag-alias-6.c new file mode 100644 index 00000000000..3f3e5f01473 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-6.c @@ -0,0 +1,77 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -O2" } + */ + + +/* We check that we tolerate differences for + * optimization. + */ + + +struct bar0 { int x; int f[3]; int y; }; + +int test_bar0(struct bar0* a, void* b) +{ + a->x = 1; + + struct bar0 { int x; int f[4]; int y; }* p = b; + p->x = 2; + + return a->x; +} + + + +struct bar1 { int x; int (*f)[3]; }; + +int test_bar1(struct bar1* a, void* b) +{ + a->x = 1; + + struct bar1 { int x; int (*f)[3]; }* p = b; + p->x = 2; + + return a->x; +} + + +struct bar2 { int x; int (*f)[3]; }; + +int test_bar2(struct bar2* a, void* b) +{ + a->x = 1; + + struct bar2 { int x; int (*f)[4]; }* p = b; + p->x = 2; + + return a->x; +} + + + +int main() +{ + // control + + struct bar0 z0; + + if (1 != test_bar0(&z0, &z0)) + __builtin_abort(); + + // this could be different + struct bar1 z1; + + if (2 != test_bar1(&z1, &z1)) + __builtin_abort(); + + struct bar2 z2; + + if (2 != test_bar2(&z2, &z2)) + __builtin_abort(); + + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-7.c b/gcc/testsuite/gcc.dg/c23-tag-alias-7.c new file mode 100644 index 00000000000..74cf5f212b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-7.c @@ -0,0 +1,86 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -O2" } + */ + + + +struct bar { int x; int f[]; }; + +int test_bar1(struct bar* a, void* b) +{ + a->x = 1; + + struct bar { int x; int f[]; }* p = b; + struct bar* q = a; + p->x = 2; + + return a->x; +} + + +int test_bar3(struct bar* a, void* b) +{ + a->x = 1; + + struct bar { int x; int f[1]; }* p = b; + struct bar* q = a; /* { dg-warning "incompatible" } */ + p->x = 2; + + return a->x; +} + + +int test_bar4(struct bar* a, void* b) +{ + a->x = 1; + + int n = 3; + struct bar { int x; int f[n]; }* p = b; + struct bar* q = a; + p->x = 2; + + return a->x; +} + + +struct foo { int x; int f[3]; }; + + +int test_foo1(struct foo* a, void* b) +{ + a->x = 1; + + int n = 3; + struct foo { int x; int f[n]; }* p = b; + struct foo* q = a; + p->x = 2; + + return a->x; +} + + + +int main() +{ + struct bar z; + + if (2 != test_bar1(&z, &z)) + __builtin_abort(); + +#if 0 + if (1 != test_bar3(&z, &z)) + __builtin_abort(); +#endif + if (2 != test_bar4(&z, &z)) + __builtin_abort(); + + struct foo y; + + if (2 != test_foo1(&y, &y)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-8.c b/gcc/testsuite/gcc.dg/c23-tag-alias-8.c new file mode 100644 index 00000000000..7c2ced4de51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-8.c @@ -0,0 +1,90 @@ +/* + * { dg-do run } + * { dg-options "-std=c23 -O2" } + */ + + +/* We check that we tolerate differences for + * optimization. + */ + +struct bar1 { int x; enum A1 { X1 = 1 } f; }; + +int test_bar1(struct bar1* a, void* b) +{ + a->x = 1; + + struct bar1 { int x; enum A1 { X1 = 2 } f; }* p = b; + p->x = 2; + + return a->x; +} + + +struct bar2 { int x; enum A2 { X2 = 1 } f; }; + +int test_bar2(struct bar2* a, void* b) +{ + a->x = 1; + + struct bar2 { int x; enum B2 { X2 = 1 } f; }* p = b; + p->x = 2; + + return a->x; +} + + + +struct bar3 { int x; enum A3 { X3 = 1 } f; }; + +int test_bar3(struct bar3* a, void* b) +{ + a->x = 1; + + struct bar3 { int x; enum A3 { Y3 = 1 } f; }* p = b; + p->x = 2; + + return a->x; +} + + +struct bar4 { int x; enum { Z4 = 1 } f; }; + +int test_bar4(struct bar4* a, void* b) +{ + a->x = 1; + + struct bar4 { int x; enum { Z4 = 1 } f; }* p = b; + p->x = 2; + + return a->x; +} + + + +int main() +{ + struct bar1 z1; + + if (1 != test_bar1(&z1, &z1)) + __builtin_abort(); + + struct bar2 z2; + + if (1 != test_bar2(&z2, &z2)) + __builtin_abort(); + + struct bar3 z3; + + if (1 != test_bar3(&z3, &z3)) + __builtin_abort(); + + struct bar4 z4; + + if (1 != test_bar4(&z4, &z4)) + __builtin_abort(); + + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-alias-1.c b/gcc/testsuite/gcc.dg/gnu23-tag-alias-1.c new file mode 100644 index 00000000000..9bccc651afb --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu23-tag-alias-1.c @@ -0,0 +1,33 @@ +/* + * { dg-do run } + * { dg-options "-std=gnu23 -O2" } + */ + + + +struct bar { int x; int f[]; }; + +int test_bar2(struct bar* a, void* b) +{ + a->x = 1; + + struct bar { int x; int f[0]; }* p = b; + struct bar* q = a; + p->x = 2; + + return a->x; +} + + + +int main() +{ + struct bar z; + + if (2 != test_bar2(&z, &z)) + __builtin_abort(); + + return 0; +} + +