From patchwork Tue Dec 7 17:59:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Li, Pan2 via Gcc-patches" X-Patchwork-Id: 48592 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 536AC3858428 for ; Tue, 7 Dec 2021 18:00:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 536AC3858428 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638900024; bh=VG6Nu0xaZFFFy+q0tHCEgawwl60xclIWah52TJ6bvh4=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=JBaAuvV3qjjnJOWTquXOVvz9MCkNeRQm4T5bwekbiJEWj86hzip2bkWvp9XC6kL8g vnheMo+OCIW2m7ooIp0i5Rr9+5YvF2dme6oTZ8Gv8teKVZ+M0QL9Nj0hI0AGyLR2Ce K7BgY7QLU6WQb2Zux4JNwT/5WoyPD7hZTl3xpec8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by sourceware.org (Postfix) with ESMTPS id 5FF1D3858D28 for ; Tue, 7 Dec 2021 17:59:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5FF1D3858D28 Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.16.1.2/8.16.1.2) with ESMTP id 1B7A4QrW023720 for ; Tue, 7 Dec 2021 09:59:52 -0800 Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3ct5hfhu8y-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 07 Dec 2021 09:59:52 -0800 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Tue, 7 Dec 2021 09:59:50 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 7 Dec 2021 09:59:50 -0800 Received: from linux.wrightpinski.org.com (unknown [10.69.242.198]) by maili.marvell.com (Postfix) with ESMTP id 4F3723F704D; Tue, 7 Dec 2021 09:59:50 -0800 (PST) To: Subject: [PATCH] Fix C++/93809 and C++/83469: typenames and unions Date: Tue, 7 Dec 2021 09:59:42 -0800 Message-ID: <1638899982-24312-1-git-send-email-apinski@marvell.com> X-Mailer: git-send-email 1.8.3.1 MIME-Version: 1.0 X-Proofpoint-GUID: j1knnFtcrWbICGp6Niu-VwTICAoYpjDo X-Proofpoint-ORIG-GUID: j1knnFtcrWbICGp6Niu-VwTICAoYpjDo X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-07_07,2021-12-06_02,2021-12-02_01 X-Spam-Status: No, score=-14.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: apinski--- via Gcc-patches From: "Li, Pan2 via Gcc-patches" Reply-To: apinski@marvell.com Cc: Andrew Pinski Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: Andrew Pinski There are a few issues here with typenames and unions (and even struct keywords with unions). First in cp_parser_check_class_key, we need to allow typenames to name union types and union key to be able to use with typenames. The next issue is we need to record if we had a union key, right now we just record it was a struct/class/typename one which is wrong. OK? Boostrapped and tested on x86_64-linux-gnu with no regressions. PR c++/83469 PR c++/93809 gcc/cp/ChangeLog: * cp-tree.h (UNION_CLASS_TYPE_P): New define. (TYPENAME_IS_UNION_P): New Define. * decl.c (struct typename_info): Add union_p field. (struct typename_hasher::equal): Compare union_p field. (build_typename_type): Move union_type to union_p/TYPENAME_IS_UNION_P. * error.c (dump_type) : Handle TYPENAME_IS_UNION_P as "union" * module.cc (trees_out::type_node): Handle TYPENAME_IS_UNION_P. * parser.c (cp_parser_check_class_key): Allow typename key for union types and allow union keyword for typename types. * pt.c (tsubst) : For TYPENAME_IS_CLASS_P, check NON_UNION_CLASS_TYPE_P rather than CLASS_TYPE_P. Add TYPENAME_IS_UNION_P handling. gcc/testsuite/ChangeLog: * g++.dg/warn/Wredundant-tags-3.C: Remove xfail. * g++.dg/pr83469-1.C: New test. * g++.dg/pr83469-2.C: New test. * g++.dg/pr83469-3.C: New test. * g++.dg/pr93809-1.C: New test. * g++.dg/pr93809-2.C: New test. * g++.dg/pr93809-3.C: New test. --- gcc/cp/cp-tree.h | 11 +++++++++-- gcc/cp/decl.c | 9 ++++++--- gcc/cp/error.c | 1 + gcc/cp/module.cc | 2 ++ gcc/cp/parser.c | 4 +++- gcc/cp/pt.c | 10 +++++++++- gcc/testsuite/g++.dg/pr83469-1.C | 15 +++++++++++++++ gcc/testsuite/g++.dg/pr83469-2.C | 13 +++++++++++++ gcc/testsuite/g++.dg/pr83469-3.C | 13 +++++++++++++ gcc/testsuite/g++.dg/pr93809-1.C | 11 +++++++++++ gcc/testsuite/g++.dg/pr93809-2.C | 5 +++++ gcc/testsuite/g++.dg/pr93809-3.C | 4 ++++ gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C | 2 +- 13 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr83469-1.C create mode 100644 gcc/testsuite/g++.dg/pr83469-2.C create mode 100644 gcc/testsuite/g++.dg/pr83469-3.C create mode 100644 gcc/testsuite/g++.dg/pr93809-1.C create mode 100644 gcc/testsuite/g++.dg/pr93809-2.C create mode 100644 gcc/testsuite/g++.dg/pr93809-3.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3510512d751..ea9cbb775e6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2206,6 +2206,10 @@ enum languages { lang_c, lang_cplusplus }; #define NON_UNION_CLASS_TYPE_P(T) \ (TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T)) +/* Nonzero if T is a class type and is a union. */ +#define UNION_CLASS_TYPE_P(T) \ + (TREE_CODE (T) == UNION_TYPE && TYPE_LANG_FLAG_5 (T)) + /* Keep these checks in ascending code order. */ #define RECORD_OR_UNION_CODE_P(T) \ ((T) == RECORD_TYPE || (T) == UNION_TYPE) @@ -4184,11 +4188,14 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define TYPENAME_IS_ENUM_P(NODE) \ (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE))) -/* True if a TYPENAME_TYPE was declared as a "class", "struct", or - "union". */ +/* True if a TYPENAME_TYPE was declared as a "class", "struct". */ #define TYPENAME_IS_CLASS_P(NODE) \ (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE))) +/* True if a TYPENAME_TYPE was declared as an "union". */ +#define TYPENAME_IS_UNION_P(NODE) \ + (TREE_LANG_FLAG_3 (TYPENAME_TYPE_CHECK (NODE))) + /* True if a TYPENAME_TYPE is in the process of being resolved. */ #define TYPENAME_IS_RESOLVING_P(NODE) \ (TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE))) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 56f80775ca0..8fa07e30d69 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3930,6 +3930,7 @@ struct typename_info { tree template_id; bool enum_p; bool class_p; + bool union_p; }; struct typename_hasher : ggc_ptr_hash @@ -3958,7 +3959,8 @@ struct typename_hasher : ggc_ptr_hash && TYPE_CONTEXT (t1) == t2->scope && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id && TYPENAME_IS_ENUM_P (t1) == t2->enum_p - && TYPENAME_IS_CLASS_P (t1) == t2->class_p); + && TYPENAME_IS_CLASS_P (t1) == t2->class_p + && TYPENAME_IS_UNION_P (t1) == t2->union_p); } }; @@ -3983,8 +3985,8 @@ build_typename_type (tree context, tree name, tree fullname, ti.template_id = fullname; ti.enum_p = tag_type == enum_type; ti.class_p = (tag_type == class_type - || tag_type == record_type - || tag_type == union_type); + || tag_type == record_type); + ti.union_p = tag_type == union_type; hashval_t hash = (htab_hash_pointer (ti.scope) ^ htab_hash_pointer (ti.name)); @@ -4001,6 +4003,7 @@ build_typename_type (tree context, tree name, tree fullname, TYPENAME_TYPE_FULLNAME (t) = ti.template_id; TYPENAME_IS_ENUM_P (t) = ti.enum_p; TYPENAME_IS_CLASS_P (t) = ti.class_p; + TYPENAME_IS_UNION_P (t) = ti.union_p; /* Build the corresponding TYPE_DECL. */ tree d = build_decl (input_location, TYPE_DECL, name, t); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index daea3b39a15..49b509eef14 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -671,6 +671,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_ws_string (pp, TYPENAME_IS_ENUM_P (t) ? "enum" : TYPENAME_IS_CLASS_P (t) ? "class" + : TYPENAME_IS_UNION_P (t) ? "union" : "typename"); dump_typename (pp, t, flags); break; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 71d0fab411f..f956d1d90cb 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8819,6 +8819,8 @@ trees_out::type_node (tree type) tag_type = enum_type; else if (TYPENAME_IS_CLASS_P (type)) tag_type = class_type; + else if (TYPENAME_IS_UNION_P (type)) + tag_type = union_type; u (int (tag_type)); } } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 55e6a1a8b3a..bbb1a52e381 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -33304,7 +33304,9 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc, return; bool seen_as_union = TREE_CODE (type) == UNION_TYPE; - if (seen_as_union != (class_key == union_type)) + if (class_key != typename_type + && TREE_CODE (type) != TYPENAME_TYPE + && seen_as_union != (class_key == union_type)) { if (permerror (input_location, "%qs tag used in naming %q#T", class_key == union_type ? "union" diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d3efc6ea238..3d7539f62c1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16113,7 +16113,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return error_mark_node; } - else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f)) + else if (TYPENAME_IS_CLASS_P (t) && !NON_UNION_CLASS_TYPE_P (f)) { if (complain & tf_error) error ("%qT resolves to %qT, which is not a class type", @@ -16121,6 +16121,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return error_mark_node; } + else if (TYPENAME_IS_UNION_P (t) && !UNION_CLASS_TYPE_P (f)) + { + if (complain & tf_error) + error ("%qT resolves to %qT, which is not an union type", + t, f); + else + return error_mark_node; + } } return cp_build_qualified_type_real diff --git a/gcc/testsuite/g++.dg/pr83469-1.C b/gcc/testsuite/g++.dg/pr83469-1.C new file mode 100644 index 00000000000..94a21fbbb98 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr83469-1.C @@ -0,0 +1,15 @@ +// { dg-do compile } +// PR C++/83469 + struct S { + union U { int m; }; + }; + + template + void f() + { union T::U u; } + + int + main() + { + f(); + } diff --git a/gcc/testsuite/g++.dg/pr83469-2.C b/gcc/testsuite/g++.dg/pr83469-2.C new file mode 100644 index 00000000000..c202e36b03b --- /dev/null +++ b/gcc/testsuite/g++.dg/pr83469-2.C @@ -0,0 +1,13 @@ +// { dg-do compile } +// PR C++/83469 + struct S { + union U { int m; }; + }; + template + void f() + { struct T::U u; } // { dg-error "" } + int + main() + { + f(); + } diff --git a/gcc/testsuite/g++.dg/pr83469-3.C b/gcc/testsuite/g++.dg/pr83469-3.C new file mode 100644 index 00000000000..1ffff0af3c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr83469-3.C @@ -0,0 +1,13 @@ +// { dg-do compile } +// PR C++/83469 + struct S { + struct C { int m; }; + }; + template + void f() + { union T::C u; } // { dg-error "" } + int + main() + { + f(); + } diff --git a/gcc/testsuite/g++.dg/pr93809-1.C b/gcc/testsuite/g++.dg/pr93809-1.C new file mode 100644 index 00000000000..321ea517cbf --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93809-1.C @@ -0,0 +1,11 @@ +// { dg-do compile } +// PR C++/93809 +class C { }; +enum E { }; +struct S { }; +union U { }; + +typedef typename ::C C2; +typedef typename ::E E2; +typedef typename ::S S2; +typedef typename ::U U2; // error diff --git a/gcc/testsuite/g++.dg/pr93809-2.C b/gcc/testsuite/g++.dg/pr93809-2.C new file mode 100644 index 00000000000..a98dada30ee --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93809-2.C @@ -0,0 +1,5 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// PR C++/93809 +union a{}; +auto var = new (typename :: a ); diff --git a/gcc/testsuite/g++.dg/pr93809-3.C b/gcc/testsuite/g++.dg/pr93809-3.C new file mode 100644 index 00000000000..f544b1f059f --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93809-3.C @@ -0,0 +1,4 @@ +// { dg-do compile } +// PR C++/93809 +typedef union{} typedef_union; +typename :: typedef_union foo1 () { return typedef_union(); } diff --git a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C index 0eeee34dae7..dcccdcad22d 100644 --- a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C +++ b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C @@ -28,7 +28,7 @@ struct N::S s3; // { dg-warning "-Wredundant-tags" } N::U u1; typename N::U u2; // { dg-bogus "-Wredundant-tags" } - // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { xfail *-*-*} .-1 } + // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { target *-*-*} .-1 } union N::U u3; // { dg-warning "-Wredundant-tags" }