aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-12-10 15:10:59 -0500
committerJason Merrill <jason@gcc.gnu.org>2019-12-10 15:10:59 -0500
commit09b661cea17a144e68009ecdf61a92a05bf852dd (patch)
tree1b9cad92725bcc9fdcbf79f2494fde214906af93 /gcc/cp
parent1fb81d83a8857770be56df19c8a3b4e0ca87c71c (diff)
downloadgcc-09b661cea17a144e68009ecdf61a92a05bf852dd.zip
gcc-09b661cea17a144e68009ecdf61a92a05bf852dd.tar.gz
gcc-09b661cea17a144e68009ecdf61a92a05bf852dd.tar.bz2
Fix C++20 structural type vs. private base.
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. * 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. From-SVN: r279184
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/class.c54
-rw-r--r--gcc/cp/tree.c8
3 files changed, 49 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b640e15..6b15fc3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2019-12-10 Jason Merrill <jason@redhat.com>
+ Fix C++20 structural type vs. private base.
+ * 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.
+
PR c++/92560 - ICE with decltype and rewritten operator.
* call.c (build_new_op_1): Clear tf_decltype on inner call.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d8bb449..a8c6b1c 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 c7c063f..7b5a3e4 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)))