From patchwork Sun Oct 23 16:52:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keegan Saunders X-Patchwork-Id: 8060 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp64950wru; Sun, 23 Oct 2022 09:54:22 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6dvTs9PZpQoRH2LB1UuOF16hD4UhclHi1KA3qNzJESVrp+/BYgxd47NEP5BTZenDNMHn/d X-Received: by 2002:a17:907:628f:b0:72f:57da:c33d with SMTP id nd15-20020a170907628f00b0072f57dac33dmr23848564ejc.374.1666544062312; Sun, 23 Oct 2022 09:54:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666544062; cv=none; d=google.com; s=arc-20160816; b=VaF2MktjdpxIk4olHjqACVVY6ADP1PSJfa0xiI5jnsn82TXN9XDuORYR8IDb8yG3gP T4PxgyZHv0CF4m21wCKFacmqpUlbDMooyjoYhG3QAOSJjPaILvDsZ5tjfeVG+1oOBgjK tHNQMPvAG7KP7IxdM/RpgdJYyo/nfzyl9v5VpnUK2WO0ochko1vHXl9rFdvSbW+O9mQy BqGm+OP3Hysm0lMOe9umIUgBEwvAc/n+ayWmZ7HL6c+GwBvI+d/d9/v0mtanlw0GVOZ5 Wm5W5vIEcbckpGJh+fdv1Xp/UEmVnbj7UmC3NWz4pX5yfzyv9QhFOGtC5YrT3x1xeI58 JlaQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:from:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=vbsKIohllBeXlLj3uuVu2WRG2smjh9w32+nJRBW5nP0=; b=Tv54kr3xLoeZdgHlPRLLqNKvYC+Nh+pWuPaakSiokfogHLwfLzHYssfkLFpJmCd/I2 blrtS8rcK7dvuRehwr500qBJebpHjSQYzLmJxVzWsGmf8u0roroMsTfpntIjGO+Uq1xG cu8phVvBOHmBcrY5LJZL2QQKUHkoUWQzT4YTvISC9h3ezceYC0UMluPs2LLYL2BaUcI1 CCOAFtMv2UCPkPGONUzrA/GRtxMXzIaVB+mIV62PaVLlxzbNxEZyqhrUKMVPHLCiOYxR cZ3cRyHDVtYJg0NDNVmN/vRjsMsj3OYXMCX+G81J8btjEfZjRhr/IQTxBWmzFYgVGEAA eu4Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=yxU47cF1; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id sh40-20020a1709076ea800b0078d288c1047si25395297ejc.841.2022.10.23.09.54.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Oct 2022 09:54:22 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=yxU47cF1; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 072EB3853837 for ; Sun, 23 Oct 2022 16:54:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 072EB3853837 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1666544061; bh=vbsKIohllBeXlLj3uuVu2WRG2smjh9w32+nJRBW5nP0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=yxU47cF1+JFmVL1GgkQ6Y6EdQDVAFVWsHM3gj4Ot1XPBTK+MinqEBfun4nG84Yi3F ujaZ/BZTMY6mI7tAaZQdkqnS61z0zF7PiXGGLSWNTgGbZrMMtXpzEHDq7mVF8o7lWB 6VgDrNVsyeRsjwthdb4U+6/knNvv0J1OtTXZGslg= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from hognose1.porkbun.com (hognose1.porkbun.com [35.82.102.206]) by sourceware.org (Postfix) with ESMTPS id F376E3857030 for ; Sun, 23 Oct 2022 16:53:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F376E3857030 Received: by hognose1.porkbun.com (Postfix, from userid 497) id DA7AA421D8; Sun, 23 Oct 2022 16:53:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost.localdomain (unknown [67.69.69.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) (Authenticated sender: keegan@undefinedbehaviour.org) by hognose1.porkbun.com (Postfix) with ESMTPSA id 36A0041EE1; Sun, 23 Oct 2022 16:53:31 +0000 (UTC) To: gcc-patches@gcc.gnu.org Subject: [PATCH] c: If -fplan9-extensions, allow duplicate field declarations Date: Sun, 23 Oct 2022 12:52:24 -0400 Message-Id: <20221023165224.97237-1-keegan@undefinedbehaviour.org> X-Mailer: git-send-email 2.37.1 MIME-Version: 1.0 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: Keegan Saunders via Gcc-patches From: Keegan Saunders Reply-To: Keegan Saunders Cc: Keegan Saunders Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747498106535695053?= X-GMAIL-MSGID: =?utf-8?q?1747498106535695053?= The Plan 9 compilers defer duplicate declaration checks until field resolution time. Further, there is a priority order of resolution such that field lookups first match the name, then typedef'd names before recursing into substructures. This enables large portions of the Plan 9 userspace and kernel to be compiled with GCC without modification. gcc/c/ChangeLog: * c-decl.cc (is_duplicate_field): Remove unused Plan 9 logic. (detect_field_duplicates_hash): Likewise. (detect_field_duplicates): If -fplan9-extensions, disable duplicate field detection. * c-typeck.cc (lookup_field_plan9): Implement the Plan 9 look up scheme. (lookup_field): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/anon-struct-13.c: Add duplicate fields. Signed-off-by: Keegan Saunders --- gcc/c/c-decl.cc | 63 ++-------------- gcc/c/c-typeck.cc | 101 ++++++++++++++++++++------ gcc/testsuite/gcc.dg/anon-struct-13.c | 9 +++ 3 files changed, 96 insertions(+), 77 deletions(-) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 193e268f04e..539ad407f49 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -8538,41 +8538,7 @@ grokfield (location_t loc, static bool is_duplicate_field (tree x, tree y) { - if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y)) - return true; - - /* When using -fplan9-extensions, an anonymous field whose name is a - typedef can duplicate a field name. */ - if (flag_plan9_extensions - && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE)) - { - tree xt, xn, yt, yn; - - xt = TREE_TYPE (x); - if (DECL_NAME (x) != NULL_TREE) - xn = DECL_NAME (x); - else if (RECORD_OR_UNION_TYPE_P (xt) - && TYPE_NAME (xt) != NULL_TREE - && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL) - xn = DECL_NAME (TYPE_NAME (xt)); - else - xn = NULL_TREE; - - yt = TREE_TYPE (y); - if (DECL_NAME (y) != NULL_TREE) - yn = DECL_NAME (y); - else if (RECORD_OR_UNION_TYPE_P (yt) - && TYPE_NAME (yt) != NULL_TREE - && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL) - yn = DECL_NAME (TYPE_NAME (yt)); - else - yn = NULL_TREE; - - if (xn != NULL_TREE && xn == yn) - return true; - } - - return false; + return DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y); } /* Subroutine of detect_field_duplicates: add the fields of FIELDLIST @@ -8599,19 +8565,6 @@ detect_field_duplicates_hash (tree fieldlist, else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) { detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab); - - /* When using -fplan9-extensions, an anonymous field whose - name is a typedef can duplicate a field name. */ - if (flag_plan9_extensions - && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE - && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL) - { - tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x))); - slot = htab->find_slot (xn, INSERT); - if (*slot) - error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x))); - *slot = xn; - } } } @@ -8639,6 +8592,11 @@ detect_field_duplicates (tree fieldlist) if (objc_detect_field_duplicates (false)) return; + /* When using -fplan9-extensions, do not perform duplicate field + checks until a field look up is performed. */ + if (flag_plan9_extensions) + return; + /* First, see if there are more than "a few" fields. This is trivially true if there are zero or one fields. */ if (!fieldlist || !DECL_CHAIN (fieldlist)) @@ -8658,14 +8616,7 @@ detect_field_duplicates (tree fieldlist) if (timeout > 0) { for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x)) - /* When using -fplan9-extensions, we can have duplicates - between typedef names and fields. */ - if (DECL_NAME (x) - || (flag_plan9_extensions - && DECL_NAME (x) == NULL_TREE - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)) - && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE - && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)) + if (DECL_NAME (x)) { for (y = fieldlist; y != x; y = TREE_CHAIN (y)) if (is_duplicate_field (y, x)) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index f9190680a3c..97ffa329ba7 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -95,6 +95,7 @@ static int comp_target_types (location_t, tree, tree); static int function_types_compatible_p (const_tree, const_tree, bool *, bool *); static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *); +static tree lookup_field_plan9 (tree, tree); static tree lookup_field (tree, tree); static int convert_arguments (location_t, vec, tree, vec *, vec *, tree, @@ -2280,6 +2281,81 @@ default_conversion (tree exp) return exp; } +/* Look up COMPONENT in a structure or union TYPE like a Plan 9 C compiler. + + Look up is performed in 3 passes: + 1. Look for field names that match the look up name. + 2. Look for anonymous records who's typedef name matches the look up name. + 3. Look for fields in embedded anonymous records. + + If the component name is not found, returns NULL_TREE. If the component + name references multiple fields, issue an error. */ + +static tree +lookup_field_plan9 (tree type, tree component) +{ + tree field; + tree found = NULL_TREE; + + /* Passes 1 & 2 are fused: conflicts are an error. */ + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + /* Pass 1. */ + if (DECL_NAME (field) == component) + { + if (found != NULL_TREE) + { + error ("duplicate member %q+D", found); + return NULL_TREE; + } + found = field; + } + + /* Pass 2. */ + if (DECL_NAME (field) == NULL_TREE + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))) + { + if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE + && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL + && (DECL_NAME (TYPE_NAME (TREE_TYPE (field))) + == component)) + { + if (found != NULL_TREE) + { + error ("duplicate member %q+D", found); + return NULL_TREE; + } + found = field; + } + } + } + + if (found != NULL_TREE) + return tree_cons (NULL_TREE, found, NULL_TREE); + + /* Pass 3. */ + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + if (DECL_NAME (field) == NULL_TREE + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))) + { + tree anon = lookup_field_plan9 (TREE_TYPE (field), component); + + if (anon != NULL_TREE) + { + if (found != NULL_TREE) + { + error ("duplicate member %q+D", TREE_VALUE (nreverse (anon))); + return NULL_TREE; + } + found = tree_cons (NULL_TREE, field, anon); + } + } + } + + return found; +} + /* Look up COMPONENT in a structure or union TYPE. If the component name is not found, returns NULL_TREE. Otherwise, @@ -2294,6 +2370,10 @@ lookup_field (tree type, tree component) { tree field; + /* The Plan 9 compiler has a different field resolution scheme. */ + if (flag_plan9_extensions) + return lookup_field_plan9 (type, component); + /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers to the field elements. Use a binary search on this array to quickly find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC @@ -2329,17 +2409,6 @@ lookup_field (tree type, tree component) if (anon) return tree_cons (NULL_TREE, field, anon); - - /* The Plan 9 compiler permits referring - directly to an anonymous struct/union field - using a typedef name. */ - if (flag_plan9_extensions - && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE - && (TREE_CODE (TYPE_NAME (TREE_TYPE (field))) - == TYPE_DECL) - && (DECL_NAME (TYPE_NAME (TREE_TYPE (field))) - == component)) - break; } } @@ -2375,16 +2444,6 @@ lookup_field (tree type, tree component) if (anon) return tree_cons (NULL_TREE, field, anon); - - /* The Plan 9 compiler permits referring directly to an - anonymous struct/union field using a typedef - name. */ - if (flag_plan9_extensions - && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE - && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL - && (DECL_NAME (TYPE_NAME (TREE_TYPE (field))) - == component)) - break; } if (DECL_NAME (field) == component) diff --git a/gcc/testsuite/gcc.dg/anon-struct-13.c b/gcc/testsuite/gcc.dg/anon-struct-13.c index 6a508141bac..c7b7d8cb101 100644 --- a/gcc/testsuite/gcc.dg/anon-struct-13.c +++ b/gcc/testsuite/gcc.dg/anon-struct-13.c @@ -5,6 +5,8 @@ struct A { char a; /* { dg-error "duplicate member" } */ + char b; + char b; }; struct B @@ -46,6 +48,13 @@ struct E struct D; }; +struct F +{ + char a; + char a; + char a; +}; + char f4 (struct E *p) {