From patchwork Tue May 21 12:18:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Uecker X-Patchwork-Id: 1937388 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=jurkkoxc; 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 4VkD5805QYz1ydW for ; Tue, 21 May 2024 22:19:23 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D3E623857C4F for ; Tue, 21 May 2024 12:19:21 +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 E6C2E3858D1E for ; Tue, 21 May 2024 12:18:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E6C2E3858D1E 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 E6C2E3858D1E 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=1716293936; cv=none; b=l39ND9w4U86/BIsBDeXCOpof4atXM/b+TiP4FCt9+wnFmkMDWCnUwZFoLU/n/CKVI/osy/NJV02HD456j81QDjOhXg8TWzx6PXfmsF5X9XenMI0vix+l7HvP9FroMwPJLMOKSDH8dZuqvu55IX02bBsS1JQoc53EHCL+BRpa3s4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716293936; c=relaxed/simple; bh=nG3/R2hp1TnvGlPc+Huqzs9N0aAjeJ5NoFqoThyD4Z0=; h=DKIM-Signature:Message-ID:Subject:From:To:Date:MIME-Version; b=YK38uNc0i6pO9r1wkIgor2fdyqSSque1GgAMPgXDddBkFDnTnXLIXSvs3/dENnt4BDWdOhq0yR9dYMeH0b/G2pV0ngQ7QeeKeNwDF1+1jsuaE3SlgWwf1eNjStZc0nDiU6U1c6Rz2OsL+RDGXPXuZ0ZD7Hdw8jERl9fXClDNj/U= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from vra-169-219.tugraz.at (vra-169-219.tugraz.at [129.27.169.219]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4VkD4T5Rdgz1LM0R; Tue, 21 May 2024 14:18:49 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4VkD4T5Rdgz1LM0R DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1716293930; bh=nZNUicP6c6RvWlDO+R3JtbQPp0cMEJQBNRqMe6AQIAs=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=jurkkoxcmT4mRJBpbfc9cyKKYef3bT5qYVX703qD2Eq3w4tqA7y4HIGjOUAohKDpG XgNNNGGl5C7vZEfM9hAXR0vUCB42jRo2WoMIw296wOQ44ahvJW/ZMx3W/jHMOHmpTD rUoOAJ7Klbli7cGkhvaxGIhsrATL5ZYIJEbkdy8k= Message-ID: Subject: [C PATCH]: allow aliasing of compatible types derived from enumeral types [PR115157] From: Martin Uecker To: gcc-patches@gcc.gnu.org Cc: Joseph Myers , Richard Biener , Jakub Jelinek , Ian Lance Taylor Date: Tue, 21 May 2024 14:18:48 +0200 In-Reply-To: <45067a3258e0ec1677ed95f62ac21c1353d66355.camel@tugraz.at> References: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at> <45067a3258e0ec1677ed95f62ac21c1353d66355.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.116 X-Spam-Status: No, score=-11.5 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 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 For enum and integer we allow aliasing by specifically returning via a langhook the aliasing set of the underlying type. But this is not sufficient for derived types, i.e. pointers to enums and pointers to compatible integers also need to have the same aliasing set. We also allow forward declarations of enums which is a GNU extension, but I think this has to work consistently too, so we here have the same issue as in C23 with other tagged types. The solution in this patch is similar to what we do in C23, i.e.  we start out with structural equality and then set TYPE_CANONICAL  to the underlying type. The only way to make the TYPE_CANONICAL  system work with the C rules for type compatility seems to set  TYPE_CANONICAL to the same type for all types in a compatibility equivalence class (as compatibility is not transitive this puts together similar types that are not compatible). This is the underlying type in this case. As all types in such an equivalence class have the same representation, so this should always work  in my opinion (but maybe there is some middle end aspects I am still missing). When testing, I so far only found two minor issues, i.e. when computing the 'aka' type in diagnostics and an issue with godump.cc (not sure I fixed this correctly). Beyond this patch, we need also some change for function types  in general and there are problably also some other issues related to incomplete arrays as well  (I added some checking to 'comptypes' to check that all types ruled compatible by the C FE also have  either structural equality, or have the same TYPE_CANONICAL, and this brings up some more inconsistencies). Thoughts? Bootstrapped and regression tested on x86_64 (only C, C++ so far). C: allow aliasing of compatible types derived from enumeral types [PR115157] Aliasing of enumeral types with the underlying integer is now allowed by setting the aliasing set to zero. But this does not allow aliasing of derived types which are compatible as required by ISO C. Instead, initially set structural equality. Then set TYPE_CANONICAL and update pointers and main variants when the type is completed (as done for structures and unions in C23). PR 115157 gcc/c/ * c-decl.cc (shadow_tag-warned,parse_xref_tag,start_enum, finish_enum): Set SET_TYPE_STRUCTURAL_EQUALITY / TYPE_CANONICAL. * c-obj-common.cc (get_alias_set): Remove special case. (get_aka_type): Add special case. gcc/ * godump.cc (go_output_typedef): use TYPE_MAIN_VARIANT instead of TYPE_CANONICAL. gcc/testsuite/ * gcc.dg/enum-alias-1.c: New test. * gcc.dg/enum-alias-2.c: New test. * gcc.dg/enum-alias-3.c: New test. diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index b691b91b3db..6e6606c9570 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5051,7 +5051,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) if (t == NULL_TREE) { t = make_node (code); - if (flag_isoc23 && code != ENUMERAL_TYPE) + if (flag_isoc23 || code == ENUMERAL_TYPE) SET_TYPE_STRUCTURAL_EQUALITY (t); pushtag (input_location, name, t); } @@ -8828,7 +8828,7 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name, the forward-reference will be altered into a real type. */ ref = make_node (code); - if (flag_isoc23 && code != ENUMERAL_TYPE) + if (flag_isoc23 || code == ENUMERAL_TYPE) SET_TYPE_STRUCTURAL_EQUALITY (ref); if (code == ENUMERAL_TYPE) { @@ -9919,6 +9919,7 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name, { enumtype = make_node (ENUMERAL_TYPE); TYPE_SIZE (enumtype) = NULL_TREE; + SET_TYPE_STRUCTURAL_EQUALITY (enumtype); pushtag (loc, name, enumtype); if (fixed_underlying_type != NULL_TREE) { @@ -9935,6 +9936,8 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name, TYPE_SIZE (enumtype) = NULL_TREE; TYPE_PRECISION (enumtype) = TYPE_PRECISION (fixed_underlying_type); ENUM_UNDERLYING_TYPE (enumtype) = fixed_underlying_type; + TYPE_CANONICAL (enumtype) = TYPE_CANONICAL (fixed_underlying_type); + c_update_type_canonical (enumtype); layout_type (enumtype); } } @@ -10094,6 +10097,10 @@ finish_enum (tree enumtype, tree values, tree attributes) ENUM_UNDERLYING_TYPE (enumtype) = c_common_type_for_size (TYPE_PRECISION (tem), TYPE_UNSIGNED (tem)); + TYPE_CANONICAL (enumtype) = + TYPE_CANONICAL (ENUM_UNDERLYING_TYPE (enumtype)); + c_update_type_canonical (enumtype); + layout_type (enumtype); } diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index b7c72d2609c..551ec6f4b65 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -130,6 +130,8 @@ get_aka_type (tree type) result = get_aka_type (orig_type); } + else if (TREE_CODE (type) == ENUMERAL_TYPE) + return type; else { tree canonical = TYPE_CANONICAL (type); @@ -418,11 +420,6 @@ c_var_mod_p (tree x, tree fn ATTRIBUTE_UNUSED) alias_set_type c_get_alias_set (tree t) { - /* Allow aliasing between enumeral types and the underlying - integer type. This is required since those are compatible types. */ - 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)) diff --git a/gcc/godump.cc b/gcc/godump.cc index 66e73ade7df..372871a59ec 100644 --- a/gcc/godump.cc +++ b/gcc/godump.cc @@ -1121,7 +1121,7 @@ go_output_typedef (class godump_container *container, tree decl) && !container->decls_seen.contains (TREE_TYPE (decl)) && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE || !container->decls_seen.contains - (TYPE_CANONICAL (TREE_TYPE (decl))))) + (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))) { tree element; diff --git a/gcc/testsuite/gcc.dg/enum-alias-1.c b/gcc/testsuite/gcc.dg/enum-alias-1.c new file mode 100644 index 00000000000..8fa30eb7897 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-1.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +enum E { E1 = -1, E2 = 0, E3 = 1 }; + +typedef int A; +typedef enum E B; + +_Static_assert(_Generic((A){ 0 }, B: 1), ""); + +void* foo(void* a, void *b, A *c, B *d) +{ + *(A**)a = c; + *(B**)b = d; + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + diff --git a/gcc/testsuite/gcc.dg/enum-alias-2.c b/gcc/testsuite/gcc.dg/enum-alias-2.c new file mode 100644 index 00000000000..7ca3f3b2db8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-2.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +typedef int A; + +void* foo(void* a, void *b, void *c, void *d) +{ + *(A**)a = c; + + { + typedef enum E B; + enum E { E1 = -1, E2 = 0, E3 = 1 }; + *(B**)b = d; + } + + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + diff --git a/gcc/testsuite/gcc.dg/enum-alias-3.c b/gcc/testsuite/gcc.dg/enum-alias-3.c new file mode 100644 index 00000000000..36a4f02a455 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-3.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -flto" } */ + +typedef int *A; + +void* foo(void* a, void *b, void *c, void *d) +{ + *(A**)a = c; + + typedef enum E *B; + enum E { E1 = -1, E2 = 0, E3 = 1 }; + { + *(B**)b = d; + } + + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + +