From patchwork Tue Dec 10 20:10:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 1207258 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=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-515641-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="hsUqhBIS"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="evPiXDTT"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47XWR16z07z9sP6 for ; Wed, 11 Dec 2019 07:11:09 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:content-type :content-transfer-encoding; q=dns; s=default; b=QUI/jw7yNL3Mmtlu UNXcyUIzUUH77JqsVpXxim4EglBe1sjGdUwow7eW2e+2fY4Fpaco4p56886g68Ke TGUJwVnOSkBGPMO7dYRT0MMLrJnKNgfPCD1xu8JUyuNgiaZauMtfMcMWyE+Pa0UO 8u0N55JveMN4M69/cfHvvkF8MLM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:content-type :content-transfer-encoding; s=default; bh=Ctob1othmWJVoFnq+M7JsH VTihs=; b=hsUqhBIStKRMW5eXamjfc/Vmxd2ITdQCgcqFML4xlDUmZARaTlxiI8 xbKbZu0mzYw9IJxVbzXFLChjAjtaDviNLgNlIGqNj3UUGazabt9LUT4PUyFOlcht r1ERRNtbHIcd240Wnh1I0sLp8u4N2e5rMLh8L9NeeKeTuhw4jIaXw= Received: (qmail 93185 invoked by alias); 10 Dec 2019 20:11:00 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 93125 invoked by uid 89); 10 Dec 2019 20:11:00 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=artificial, HX-Languages-Length:6926, structural X-HELO: us-smtp-delivery-1.mimecast.com Received: from us-smtp-2.mimecast.com (HELO us-smtp-delivery-1.mimecast.com) (205.139.110.61) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 10 Dec 2019 20:10:58 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1576008657; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=vyYDZvbJlI0Sg24X2lWPdOTZmoGaC2TwN7ofP0Z10xQ=; b=evPiXDTTBsQQ6R7qO8M8xs4kiRY2rpWk8s0WPj43MTMJ8GseBD0zt1GjKQypRc4wUqfG8Z foV0asujBMub9W5esclIwvlKiKLPWEDvwMPUyRsJ2eDREF2aQr/ELNMO+VQruriC4lRba9 lF97XdO1QCZ8IDXtgiOUkBzcNE8FtUI= Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-434-I-hBcm_AMzG1x8HylbIi1A-1; Tue, 10 Dec 2019 15:10:55 -0500 Received: by mail-qt1-f199.google.com with SMTP id p12so2756020qtu.6 for ; Tue, 10 Dec 2019 12:10:55 -0800 (PST) Received: from barrymore.redhat.com (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id u16sm1241787qku.19.2019.12.10.12.10.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Dec 2019 12:10:53 -0800 (PST) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] Fix C++20 structural type vs. private base. Date: Tue, 10 Dec 2019 15:10:52 -0500 Message-Id: <20191210201052.27486-1-jason@redhat.com> X-Mimecast-Spam-Score: 0 X-IsSubscribed: yes In my patch to implement C++20 "structural type" I tried to set the access flags on the artificial base fields appropriately, but failed. I was copying TREE_PRIVATE from the binfo, but TREE_PRIVATE on binfo is just a temporary cache for dfs_access_in_type; we really need to get the inheritance access information from BINFO_BASE_ACCESSES. Tested x86_64-pc-linux-gnu, applying to trunk. * class.c (build_base_field_1): Take access parameter. (build_base_field): Likewise. (build_base_fields, layout_virtual_bases): Pass it. * tree.c (structural_type_p): Improve private base diagnostic. --- gcc/cp/class.c | 54 +++++++++++++------- gcc/cp/tree.c | 8 ++- gcc/testsuite/g++.dg/cpp2a/nontype-class25.C | 6 +++ 3 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class25.C base-commit: fca3fc600c0a9cdb1325455f7364ca646a0f20ea diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d8bb44990b7..a8c6b1cb01c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -134,7 +134,6 @@ static void build_vtbl_initializer (tree, tree, tree, tree, int *, static bool check_bitfield_decl (tree); static bool check_field_decl (tree, tree, int *, int *); static void check_field_decls (tree, tree *, int *, int *); -static tree *build_base_field (record_layout_info, tree, splay_tree, tree *); static void build_base_fields (record_layout_info, splay_tree, tree *); static void check_methods (tree); static void remove_zero_width_bit_fields (tree); @@ -4407,7 +4406,7 @@ layout_empty_base_or_field (record_layout_info rli, tree binfo_or_decl, fields at NEXT_FIELD, and return it. */ static tree -build_base_field_1 (tree t, tree binfo, tree *&next_field) +build_base_field_1 (tree t, tree binfo, tree access, tree *&next_field) { /* Create the FIELD_DECL. */ tree basetype = BINFO_TYPE (binfo); @@ -4417,8 +4416,6 @@ build_base_field_1 (tree t, tree binfo, tree *&next_field) DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_FIELD_CONTEXT (decl) = t; - TREE_PRIVATE (decl) = TREE_PRIVATE (binfo); - TREE_PROTECTED (decl) = TREE_PROTECTED (binfo); if (is_empty_class (basetype)) /* CLASSTYPE_SIZE is one byte, but the field needs to have size zero. */ DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = size_zero_node; @@ -4432,6 +4429,11 @@ build_base_field_1 (tree t, tree binfo, tree *&next_field) SET_DECL_MODE (decl, TYPE_MODE (basetype)); DECL_FIELD_IS_BASE (decl) = 1; + if (access == access_private_node) + TREE_PRIVATE (decl) = true; + else if (access == access_protected_node) + TREE_PROTECTED (decl) = true; + /* Add the new FIELD_DECL to the list of fields for T. */ DECL_CHAIN (decl) = *next_field; *next_field = decl; @@ -4450,7 +4452,7 @@ build_base_field_1 (tree t, tree binfo, tree *&next_field) Returns the location at which the next field should be inserted. */ static tree * -build_base_field (record_layout_info rli, tree binfo, +build_base_field (record_layout_info rli, tree binfo, tree access, splay_tree offsets, tree *next_field) { tree t = rli->t; @@ -4471,7 +4473,7 @@ build_base_field (record_layout_info rli, tree binfo, CLASSTYPE_EMPTY_P (t) = 0; /* Create the FIELD_DECL. */ - decl = build_base_field_1 (t, binfo, next_field); + decl = build_base_field_1 (t, binfo, access, next_field); /* Try to place the field. It may take more than one try if we have a hard time placing the field without putting two @@ -4505,7 +4507,7 @@ build_base_field (record_layout_info rli, tree binfo, aggregate bases. */ if (cxx_dialect >= cxx17 && !BINFO_VIRTUAL_P (binfo)) { - tree decl = build_base_field_1 (t, binfo, next_field); + tree decl = build_base_field_1 (t, binfo, access, next_field); DECL_FIELD_OFFSET (decl) = BINFO_OFFSET (binfo); DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT); @@ -4536,25 +4538,39 @@ build_base_fields (record_layout_info rli, /* Chain to hold all the new FIELD_DECLs which stand in for base class subobjects. */ tree t = rli->t; - int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t)); - int i; + tree binfo = TYPE_BINFO (t); + int n_baseclasses = BINFO_N_BASE_BINFOS (binfo); /* The primary base class is always allocated first. */ - if (CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t), - offsets, next_field); + const tree primary_binfo = CLASSTYPE_PRIMARY_BINFO (t); + if (primary_binfo) + { + /* We need to walk BINFO_BASE_BINFO to find the access of the primary + base, if it is direct. Indirect base fields are private. */ + tree primary_access = access_private_node; + for (int i = 0; i < n_baseclasses; ++i) + { + tree base_binfo = BINFO_BASE_BINFO (binfo, i); + if (base_binfo == primary_binfo) + { + primary_access = BINFO_BASE_ACCESS (binfo, i); + break; + } + } + next_field = build_base_field (rli, primary_binfo, + primary_access, + offsets, next_field); + } /* Now allocate the rest of the bases. */ - for (i = 0; i < n_baseclasses; ++i) + for (int i = 0; i < n_baseclasses; ++i) { - tree base_binfo; - - base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (t), i); + tree base_binfo = BINFO_BASE_BINFO (binfo, i); /* The primary base was already allocated above, so we don't need to allocate it again here. */ - if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t)) - continue; + if (base_binfo == primary_binfo) + continue; /* Virtual bases are added at the end (a primary virtual base will have already been added). */ @@ -4562,6 +4578,7 @@ build_base_fields (record_layout_info rli, continue; next_field = build_base_field (rli, base_binfo, + BINFO_BASE_ACCESS (binfo, i), offsets, next_field); } } @@ -6141,6 +6158,7 @@ layout_virtual_bases (record_layout_info rli, splay_tree offsets) /* This virtual base is not a primary base of any class in the hierarchy, so we have to add space for it. */ next_field = build_base_field (rli, vbase, + access_private_node, offsets, next_field); } } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c7c063f6df7..7b5a3e423f9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -4447,7 +4447,13 @@ structural_type_p (tree t, bool explain) if (TREE_PRIVATE (m) || TREE_PROTECTED (m)) { if (explain) - inform (location_of (m), "%qD is not public", m); + { + if (DECL_FIELD_IS_BASE (m)) + inform (location_of (m), "base class %qT is not public", + TREE_TYPE (m)); + else + inform (location_of (m), "%qD is not public", m); + } return false; } if (!structural_type_p (TREE_TYPE (m))) diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class25.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class25.C new file mode 100644 index 00000000000..67d6f094968 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class25.C @@ -0,0 +1,6 @@ +// { dg-do compile { target c++2a } } + +struct base { int i{}; }; +struct derived : private base {}; +template struct has_nttp_param{}; // { dg-error "non-type" } +has_nttp_param<{}> v;