From patchwork Tue Apr 28 20:02:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1278689 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: 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@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: 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=Fh09ul32; 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49BXcV5fFYz9sSG for ; Wed, 29 Apr 2020 06:02:33 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 30FB7385DC23; Tue, 28 Apr 2020 20:02:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 30FB7385DC23 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1588104151; bh=5Sosu+QAKdI+Wdmm2CylS1Hn4rrEYmbi7hGIOL2j9ME=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Fh09ul32rx3gUFmk4bi9w32N7dH6PiFEMYpWuYvnqCxqrjX7ysKXfWNh9VfWhCQGh Wc9QT8arHaAAtQRY5oxa1TmdX/sci9Rr8VfQBY+hYrlPHaZT7LDlkDrDt8W9Y3rivK CPA6lFQ67EyCa6hX1TDtmYk8zOi5udryaNdLuDQQ= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by sourceware.org (Postfix) with ESMTP id 65986385DC23 for ; Tue, 28 Apr 2020 20:02:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 65986385DC23 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-100-aJdKBOskPnC0NPONMr_aYg-1; Tue, 28 Apr 2020 16:02:24 -0400 X-MC-Unique: aJdKBOskPnC0NPONMr_aYg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E5DD1462; Tue, 28 Apr 2020 20:02:22 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-112-104.ams2.redhat.com [10.36.112.104]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A977B600D2; Tue, 28 Apr 2020 20:02:21 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id 03SK2I8H004401; Tue, 28 Apr 2020 22:02:19 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id 03SK2GMp004400; Tue, 28 Apr 2020 22:02:16 +0200 Date: Tue, 28 Apr 2020 22:02:16 +0200 To: Segher Boessenkool , wschmidt@linux.ibm.com Subject: [PATCH v3] c++, middle-end, rs6000: Fix C++17 ABI incompatibilities during class layout and [[no_unique_address]] handling [PR94707] Message-ID: <20200428200216.GH2375@tucnak> References: <20200427194725.GF2424@tucnak> <20200427195335.GL71320@redhat.com> <2db598c2-8b3e-233a-1e3b-ae002119b5a9@redhat.com> <20200427212301.GG2424@tucnak> <9fbb6d66-e5a7-2f69-c254-bde69f5886f5@redhat.com> <20200428115408.GL2424@tucnak> <1052d598-6d20-cc6e-33ee-03f25396afe8@redhat.com> <20200428140458.GP2424@tucnak> <20200428154200.GT2424@tucnak> MIME-Version: 1.0 In-Reply-To: <20200428154200.GT2424@tucnak> User-Agent: Mutt/1.11.3 (2019-02-01) X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-19.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: Iain Sandoe , Jonathan Wakely , gcc-patches@gcc.gnu.org, David Edelsohn Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" On Tue, Apr 28, 2020 at 05:42:00PM +0200, Jakub Jelinek wrote: > Ok, below in the updated patch: This is what I've successfully bootstrapped/regtested on powerpc64le-linux (last posted patch with the lto-common.c addition included). Jason has already approved the non-rs6000 parts, so are those ok for trunk too? 2020-04-28 Jakub Jelinek PR target/94707 * tree-core.h (tree_decl_common): Note decl_flag_0 used for DECL_FIELD_ABI_IGNORED. * tree.h (DECL_FIELD_ABI_IGNORED): Define. * calls.h (cxx17_empty_base_field_p): Change into a temporary macro, check DECL_FIELD_ABI_IGNORED flag with no "no_unique_address" attribute. * calls.c (cxx17_empty_base_field_p): Remove. * tree-streamer-out.c (pack_ts_decl_common_value_fields): Handle DECL_FIELD_ABI_IGNORED. * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Likewise. * lto-streamer-out.c (hash_tree): Likewise. * config/rs6000/rs6000-call.c (rs6000_aggregate_candidate): Rename cxx17_empty_base_seen to empty_base_seen, change type to int *, adjust recursive calls, use DECL_FIELD_ABI_IGNORED instead of cxx17_empty_base_field_p, if "no_unique_address" attribute is present, propagate that to the caller too. (rs6000_discover_homogeneous_aggregate): Adjust rs6000_aggregate_candidate caller, emit different diagnostics when c++17 empty base fields are present and when empty [[no_unique_address]] fields are present. * config/rs6000/rs6000.c (rs6000_special_round_type_align, darwin_rs6000_special_round_type_align): Skip DECL_FIELD_ABI_IGNORED fields. * class.c (build_base_field): Set DECL_FIELD_ABI_IGNORED on C++17 empty base artificial FIELD_DECLs. (layout_class_type): Set DECL_FIELD_ABI_IGNORED on empty class field_poverlapping_p FIELD_DECLs. * lto-common.c (compare_tree_sccs_1): Handle DECL_FIELD_ABI_IGNORED. * g++.target/powerpc/pr94707-1.C: New test. * g++.target/powerpc/pr94707-2.C: New test. * g++.target/powerpc/pr94707-3.C: New test. * g++.target/powerpc/pr94707-4.C: New test. * g++.target/powerpc/pr94707-5.C: New test. * g++.target/powerpc/pr94707-4.C: New test. Jakub --- gcc/tree-core.h.jj 2020-04-08 18:15:36.936946772 +0200 +++ gcc/tree-core.h 2020-04-28 15:14:06.598814022 +0200 @@ -1709,7 +1709,8 @@ struct GTY(()) tree_decl_common { unsigned lang_flag_8 : 1; /* In VAR_DECL and PARM_DECL, this is DECL_REGISTER - IN TRANSLATION_UNIT_DECL, this is TRANSLATION_UNIT_WARN_EMPTY_P. */ + In TRANSLATION_UNIT_DECL, this is TRANSLATION_UNIT_WARN_EMPTY_P. + In FIELD_DECL, this is DECL_FIELD_ABI_IGNORED. */ unsigned decl_flag_0 : 1; /* In FIELD_DECL, this is DECL_BIT_FIELD In VAR_DECL and FUNCTION_DECL, this is DECL_EXTERNAL. --- gcc/tree.h.jj 2020-04-08 18:15:36.939946727 +0200 +++ gcc/tree.h 2020-04-28 15:13:07.579695258 +0200 @@ -2750,6 +2750,13 @@ extern void decl_value_expr_insert (tree /* In a FIELD_DECL, indicates this field should be bit-packed. */ #define DECL_PACKED(NODE) (FIELD_DECL_CHECK (NODE)->base.u.bits.packed_flag) +/* In a FIELD_DECL, indicates this field should be ignored for ABI decisions + like passing/returning containing struct by value. + Set for C++17 empty base artificial FIELD_DECLs as well as + empty [[no_unique_address]] non-static data members. */ +#define DECL_FIELD_ABI_IGNORED(NODE) \ + (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0) + /* Nonzero in a FIELD_DECL means it is a bit field, and must be accessed specially. */ #define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_1) --- gcc/calls.h.jj 2020-04-27 14:31:09.123020831 +0200 +++ gcc/calls.h 2020-04-28 15:26:29.221724466 +0200 @@ -135,6 +135,9 @@ extern tree get_attr_nonstring_decl (tre extern void maybe_warn_nonstring_arg (tree, tree); extern bool get_size_range (tree, tree[2], bool = false); extern rtx rtx_for_static_chain (const_tree, bool); -extern bool cxx17_empty_base_field_p (const_tree); +/* FIXME: Remove after all backends are converted. */ +#define cxx17_empty_base_field_p(t) \ + (DECL_FIELD_ABI_IGNORED (t) \ + && !lookup_attribute ("no_unique_address", DECL_ATTRIBUTES (t))) #endif // GCC_CALLS_H --- gcc/calls.c.jj 2020-04-27 14:31:09.117020922 +0200 +++ gcc/calls.c 2020-04-28 15:26:42.276529517 +0200 @@ -6261,23 +6261,5 @@ must_pass_va_arg_in_stack (tree type) return targetm.calls.must_pass_in_stack (arg); } -/* Return true if FIELD is the C++17 empty base field that should - be ignored for ABI calling convention decisions in order to - maintain ABI compatibility between C++14 and earlier, which doesn't - add this FIELD to classes with empty bases, and C++17 and later - which does. */ - -bool -cxx17_empty_base_field_p (const_tree field) -{ - return (TREE_CODE (field) == FIELD_DECL - && DECL_ARTIFICIAL (field) - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) - && DECL_SIZE (field) - && integer_zerop (DECL_SIZE (field)) - && TYPE_SIZE (TREE_TYPE (field)) - && !integer_zerop (TYPE_SIZE (TREE_TYPE (field)))); -} - /* Tell the garbage collector about GTY markers in this source file. */ #include "gt-calls.h" --- gcc/tree-streamer-out.c.jj 2020-04-08 18:15:36.937946757 +0200 +++ gcc/tree-streamer-out.c 2020-04-28 15:24:40.062354539 +0200 @@ -217,6 +217,7 @@ pack_ts_decl_common_value_fields (struct bp_pack_value (bp, DECL_PACKED (expr), 1); bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1); bp_pack_value (bp, DECL_PADDING_P (expr), 1); + bp_pack_value (bp, DECL_FIELD_ABI_IGNORED (expr), 1); bp_pack_value (bp, expr->decl_common.off_align, 8); } --- gcc/tree-streamer-in.c.jj 2020-04-08 18:15:36.937946757 +0200 +++ gcc/tree-streamer-in.c 2020-04-28 15:24:22.511616625 +0200 @@ -256,6 +256,7 @@ unpack_ts_decl_common_value_fields (stru DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1); DECL_PADDING_P (expr) = (unsigned) bp_unpack_value (bp, 1); + DECL_FIELD_ABI_IGNORED (expr) = (unsigned) bp_unpack_value (bp, 1); expr->decl_common.off_align = bp_unpack_value (bp, 8); } --- gcc/lto-streamer-out.c.jj 2020-04-03 10:04:44.775971053 +0200 +++ gcc/lto-streamer-out.c 2020-04-28 15:23:51.361081794 +0200 @@ -1080,6 +1080,7 @@ hash_tree (struct streamer_tree_cache_d hstate.add_flag (DECL_PACKED (t)); hstate.add_flag (DECL_NONADDRESSABLE_P (t)); hstate.add_flag (DECL_PADDING_P (t)); + hstate.add_flag (DECL_FIELD_ABI_IGNORED (t)); hstate.add_int (DECL_OFFSET_ALIGN (t)); } else if (code == VAR_DECL) --- gcc/config/rs6000/rs6000-call.c.jj 2020-04-23 14:42:26.323839084 +0200 +++ gcc/config/rs6000/rs6000-call.c 2020-04-28 15:28:11.353199343 +0200 @@ -5529,7 +5529,7 @@ const struct altivec_builtin_types altiv static int rs6000_aggregate_candidate (const_tree type, machine_mode *modep, - bool *cxx17_empty_base_seen) + int *empty_base_seen) { machine_mode mode; HOST_WIDE_INT size; @@ -5600,7 +5600,7 @@ rs6000_aggregate_candidate (const_tree t return -1; count = rs6000_aggregate_candidate (TREE_TYPE (type), modep, - cxx17_empty_base_seen); + empty_base_seen); if (count == -1 || !index || !TYPE_MAX_VALUE (index) @@ -5638,14 +5638,18 @@ rs6000_aggregate_candidate (const_tree t if (TREE_CODE (field) != FIELD_DECL) continue; - if (cxx17_empty_base_field_p (field)) + if (DECL_FIELD_ABI_IGNORED (field)) { - *cxx17_empty_base_seen = true; + if (lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field))) + *empty_base_seen |= 2; + else + *empty_base_seen |= 1; continue; } sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep, - cxx17_empty_base_seen); + empty_base_seen); if (sub_count < 0) return -1; count += sub_count; @@ -5679,7 +5683,7 @@ rs6000_aggregate_candidate (const_tree t continue; sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep, - cxx17_empty_base_seen); + empty_base_seen); if (sub_count < 0) return -1; count = count > sub_count ? count : sub_count; @@ -5720,9 +5724,9 @@ rs6000_discover_homogeneous_aggregate (m && AGGREGATE_TYPE_P (type)) { machine_mode field_mode = VOIDmode; - bool cxx17_empty_base_seen = false; + int empty_base_seen = 0; int field_count = rs6000_aggregate_candidate (type, &field_mode, - &cxx17_empty_base_seen); + &empty_base_seen); if (field_count > 0) { @@ -5737,16 +5741,22 @@ rs6000_discover_homogeneous_aggregate (m *elt_mode = field_mode; if (n_elts) *n_elts = field_count; - if (cxx17_empty_base_seen && warn_psabi) + if (empty_base_seen && warn_psabi) { static unsigned last_reported_type_uid; unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); if (uid != last_reported_type_uid) { - inform (input_location, - "parameter passing for argument of type %qT " - "when C++17 is enabled changed to match C++14 " - "in GCC 10.1", type); + if (empty_base_seen & 1) + inform (input_location, + "parameter passing for argument of type %qT " + "when C++17 is enabled changed to match C++14 " + "in GCC 10.1", type); + else + inform (input_location, + "parameter passing for argument of type %qT " + "with %<[[no_unique_address]]%> members " + "changed in GCC 10.1", type); last_reported_type_uid = uid; } } --- gcc/config/rs6000/rs6000.c.jj 2020-04-27 09:11:14.090608782 +0200 +++ gcc/config/rs6000/rs6000.c 2020-04-28 15:29:25.166097098 +0200 @@ -7204,7 +7204,9 @@ rs6000_special_round_type_align (tree ty tree field = TYPE_FIELDS (type); /* Skip all non field decls */ - while (field != NULL && TREE_CODE (field) != FIELD_DECL) + while (field != NULL + && (TREE_CODE (field) != FIELD_DECL + || DECL_FIELD_ABI_IGNORED (field))) field = DECL_CHAIN (field); if (field != NULL && field != type) @@ -7236,7 +7238,9 @@ darwin_rs6000_special_round_type_align ( do { tree field = TYPE_FIELDS (type); /* Skip all non field decls */ - while (field != NULL && TREE_CODE (field) != FIELD_DECL) + while (field != NULL + && (TREE_CODE (field) != FIELD_DECL + || DECL_FIELD_ABI_IGNORED (field))) field = DECL_CHAIN (field); if (! field) break; --- gcc/cp/class.c.jj 2020-04-28 16:15:39.570540960 +0200 +++ gcc/cp/class.c 2020-04-28 16:35:18.423859735 +0200 @@ -4515,6 +4515,7 @@ build_base_field (record_layout_info rli DECL_FIELD_OFFSET (decl) = BINFO_OFFSET (binfo); DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT); + DECL_FIELD_ABI_IGNORED (decl) = 1; } /* An empty virtual base causes a class to be non-empty @@ -6522,7 +6523,10 @@ layout_class_type (tree t, tree *virtual SET_DECL_MODE (field, TYPE_MODE (type)); } else if (might_overlap && is_empty_class (type)) - layout_empty_base_or_field (rli, field, empty_base_offsets); + { + DECL_FIELD_ABI_IGNORED (field) = 1; + layout_empty_base_or_field (rli, field, empty_base_offsets); + } else layout_nonempty_base_or_field (rli, field, NULL_TREE, empty_base_offsets); --- gcc/lto/lto-common.c.jj 2020-04-17 14:18:44.357438048 +0200 +++ gcc/lto/lto-common.c 2020-04-28 17:53:04.809821198 +0200 @@ -1179,6 +1179,7 @@ compare_tree_sccs_1 (tree t1, tree t2, t compare_values (DECL_PACKED); compare_values (DECL_NONADDRESSABLE_P); compare_values (DECL_PADDING_P); + compare_values (DECL_FIELD_ABI_IGNORED); compare_values (DECL_OFFSET_ALIGN); } else if (code == VAR_DECL) --- gcc/testsuite/g++.target/powerpc/pr94707-1.C.jj 2020-04-28 13:26:01.417418105 +0200 +++ gcc/testsuite/g++.target/powerpc/pr94707-1.C 2020-04-28 13:25:19.555046878 +0200 @@ -0,0 +1,38 @@ +// PR target/94707 +// { dg-do compile { target powerpc_elfv2 } } +// { dg-options "-O2 -std=c++14" } +// Test that for all the calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision about passing homogeneous +// arguments. +// { dg-final { scan-assembler-times {(?n)^\s+lfs\s+(?:%f)?4,} 7 } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { float a, b, c, d; }; +struct B : public X { float a, b, c, d; }; +struct C : public Y { float a, b, c, d; }; +struct D : public Z { float a, b, c, d; }; +struct E : public U { float a, b, c, d; }; +struct F { [[no_unique_address]] X x; float a, b, c, d; }; +struct G { [[no_unique_address]] Y y; float a, b, c, d; }; +struct H { [[no_unique_address]] Z z; float a, b, c, d; }; +struct I { [[no_unique_address]] U u; float a, b, c, d; }; +struct J { float a, b; [[no_unique_address]] X x; float c, d; }; +struct K { float a, b; [[no_unique_address]] Y y; float c, d; }; +struct L { float a, b; [[no_unique_address]] Z z; float c, d; }; +struct M { float a, b; [[no_unique_address]] U u; float c, d; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-message "parameter passing for argument of type 'F' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-1 } +// { dg-message "parameter passing for argument of type 'G' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-2 } +// { dg-message "parameter passing for argument of type 'J' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-3 } +// { dg-message "parameter passing for argument of type 'K' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-4 } +T (A, a) +T (B, b) +T (C, c) +T (F, f) +T (G, g) +T (J, j) +T (K, k) --- gcc/testsuite/g++.target/powerpc/pr94707-2.C.jj 2020-04-28 13:26:04.782367567 +0200 +++ gcc/testsuite/g++.target/powerpc/pr94707-2.C 2020-04-28 13:25:29.240901395 +0200 @@ -0,0 +1,34 @@ +// PR target/94707 +// { dg-do compile { target powerpc_elfv2 } } +// { dg-options "-O2 -std=c++14" } +// Test that for no calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision about passing homogeneous +// arguments. +// { dg-final { scan-assembler-not {(?n)^\s+lfs\s+(?:%f)?4,} } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { float a, b, c, d; }; +struct B : public X { float a, b, c, d; }; +struct C : public Y { float a, b, c, d; }; +struct D : public Z { float a, b, c, d; }; +struct E : public U { float a, b, c, d; }; +struct F { [[no_unique_address]] X x; float a, b, c, d; }; +struct G { [[no_unique_address]] Y y; float a, b, c, d; }; +struct H { [[no_unique_address]] Z z; float a, b, c, d; }; +struct I { [[no_unique_address]] U u; float a, b, c, d; }; +struct J { float a, b; [[no_unique_address]] X x; float c, d; }; +struct K { float a, b; [[no_unique_address]] Y y; float c, d; }; +struct L { float a, b; [[no_unique_address]] Z z; float c, d; }; +struct M { float a, b; [[no_unique_address]] U u; float c, d; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-bogus "parameter passing for argument of type" } +T (D, d) +T (E, e) +T (H, h) +T (I, i) +T (L, l) +T (M, m) --- gcc/testsuite/g++.target/powerpc/pr94707-3.C.jj 2020-04-28 13:26:07.485326967 +0200 +++ gcc/testsuite/g++.target/powerpc/pr94707-3.C 2020-04-28 13:25:40.206736691 +0200 @@ -0,0 +1,40 @@ +// PR target/94707 +// { dg-do compile { target powerpc_elfv2 } } +// { dg-options "-O2 -std=c++17" } +// Test that for all the calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision about passing homogeneous +// arguments. +// { dg-final { scan-assembler-times {(?n)^\s+lfs\s+(?:%f)?4,} 7 } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { float a, b, c, d; }; +struct B : public X { float a, b, c, d; }; +struct C : public Y { float a, b, c, d; }; +struct D : public Z { float a, b, c, d; }; +struct E : public U { float a, b, c, d; }; +struct F { [[no_unique_address]] X x; float a, b, c, d; }; +struct G { [[no_unique_address]] Y y; float a, b, c, d; }; +struct H { [[no_unique_address]] Z z; float a, b, c, d; }; +struct I { [[no_unique_address]] U u; float a, b, c, d; }; +struct J { float a, b; [[no_unique_address]] X x; float c, d; }; +struct K { float a, b; [[no_unique_address]] Y y; float c, d; }; +struct L { float a, b; [[no_unique_address]] Z z; float c, d; }; +struct M { float a, b; [[no_unique_address]] U u; float c, d; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-message "parameter passing for argument of type 'B' when C\\+\\+17 is enabled changed to match C\\+\\+14 in GCC 10.1" "" { target *-*-* } .-1 } +// { dg-message "parameter passing for argument of type 'C' when C\\+\\+17 is enabled changed to match C\\+\\+14 in GCC 10.1" "" { target *-*-* } .-2 } +// { dg-message "parameter passing for argument of type 'F' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-3 } +// { dg-message "parameter passing for argument of type 'G' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-4 } +// { dg-message "parameter passing for argument of type 'J' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-5 } +// { dg-message "parameter passing for argument of type 'K' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-6 } +T (A, a) +T (B, b) +T (C, c) +T (F, f) +T (G, g) +T (J, j) +T (K, k) --- gcc/testsuite/g++.target/powerpc/pr94707-4.C.jj 2020-04-28 13:26:10.257285341 +0200 +++ gcc/testsuite/g++.target/powerpc/pr94707-4.C 2020-04-28 13:25:56.925485580 +0200 @@ -0,0 +1,34 @@ +// PR target/94707 +// { dg-do compile { target powerpc_elfv2 } } +// { dg-options "-O2 -std=c++17" } +// Test that for no calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision about passing homogeneous +// arguments. +// { dg-final { scan-assembler-not {(?n)^\s+lfs\s+(?:%f)?4,} } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { float a, b, c, d; }; +struct B : public X { float a, b, c, d; }; +struct C : public Y { float a, b, c, d; }; +struct D : public Z { float a, b, c, d; }; +struct E : public U { float a, b, c, d; }; +struct F { [[no_unique_address]] X x; float a, b, c, d; }; +struct G { [[no_unique_address]] Y y; float a, b, c, d; }; +struct H { [[no_unique_address]] Z z; float a, b, c, d; }; +struct I { [[no_unique_address]] U u; float a, b, c, d; }; +struct J { float a, b; [[no_unique_address]] X x; float c, d; }; +struct K { float a, b; [[no_unique_address]] Y y; float c, d; }; +struct L { float a, b; [[no_unique_address]] Z z; float c, d; }; +struct M { float a, b; [[no_unique_address]] U u; float c, d; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-bogus "parameter passing for argument of type" } +T (D, d) +T (E, e) +T (H, h) +T (I, i) +T (L, l) +T (M, m) --- gcc/testsuite/g++.target/powerpc/pr94707-5.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/powerpc/pr94707-5.C 2020-04-28 16:47:31.488901028 +0200 @@ -0,0 +1,35 @@ +// PR target/94707 +// { dg-do compile { target powerpc*-*-darwin* } } +// { dg-require-effective-target ilp32 } +// { dg-options "-std=c++14" } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +static_assert (__alignof__ (A) == 8, ""); +static_assert (__alignof__ (B) == 8, ""); +static_assert (__alignof__ (C) == 8, ""); +static_assert (__alignof__ (D) == 4, ""); +static_assert (__alignof__ (E) == 4, ""); +static_assert (__alignof__ (F) == 8, ""); +static_assert (__alignof__ (G) == 8, ""); +static_assert (__alignof__ (H) == 4, ""); +static_assert (__alignof__ (I) == 4, ""); +static_assert (__alignof__ (J) == 8, ""); +static_assert (__alignof__ (K) == 8, ""); +static_assert (__alignof__ (L) == 8, ""); +static_assert (__alignof__ (M) == 8, ""); --- gcc/testsuite/g++.target/powerpc/pr94707-6.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/powerpc/pr94707-6.C 2020-04-28 16:47:54.056563731 +0200 @@ -0,0 +1,6 @@ +// PR target/94707 +// { dg-do compile { target powerpc*-*-darwin* } } +// { dg-require-effective-target ilp32 } +// { dg-options "-O2 -std=c++17" } + +#include "pr94707-5.C"