@@ -7008,6 +7008,27 @@ get_primary_binfo (tree binfo)
return copied_binfo (primary_base, binfo);
}
+/* Returns TRUE if BASE is a direct virtual base of TYPE, FALSE
+ otherwise. */
+
+bool
+is_virtual_base_of (tree base, tree type)
+{
+ tree binfo;
+
+ for (binfo = TREE_CHAIN (TYPE_BINFO (type));
+ binfo;
+ binfo = TREE_CHAIN (binfo))
+ {
+ if (!BINFO_VIRTUAL_P (binfo))
+ continue;
+
+ if (same_type_p (BINFO_TYPE (binfo), base))
+ return binfo;
+ }
+ return NULL_TREE;
+}
+
/* If INDENTED_P is zero, indent to INDENT. Return nonzero. */
static int
@@ -4727,6 +4727,7 @@ extern void fixup_attribute_variants (tree);
extern tree* decl_cloned_function_p (const_tree, bool);
extern void clone_function_decl (tree, int);
extern void adjust_clone_args (tree);
+extern bool is_virtual_base_of (tree, tree);
/* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree);
@@ -130,20 +130,17 @@ initialize_vtbl_ptrs (tree addr)
dfs_walk_once (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, NULL, list);
}
-/* Return an expression for the zero-initialization of an object with
- type T. This expression will either be a constant (in the case
- that T is a scalar), or a CONSTRUCTOR (in the case that T is an
- aggregate), or NULL (in the case that T does not require
- initialization). In either case, the value can be used as
- DECL_INITIAL for a decl of the indicated TYPE; it is a valid static
- initializer. If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS
- is the number of elements in the array. If STATIC_STORAGE_P is
- TRUE, initializers are only generated for entities for which
- zero-initialization does not simply mean filling the storage with
- zero bytes. */
+/* A subroutine of build_zero_init.
+
+ The parameters are the same as for build_zero_init. If
+ IN_SUBOBJECT is TRUE, that means we are currently initializing a
+ subobject. In that case, we don't initialize virtual bases unless
+ the virtual base is a primary base of TYPE. */
-tree
-build_zero_init (tree type, tree nelts, bool static_storage_p)
+static tree
+build_zero_init_1 (tree type, tree nelts,
+ bool static_storage_p,
+ bool in_subjobject)
{
tree init = NULL_TREE;
@@ -188,15 +185,25 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ /* If we are initializing a subobject then skip non-primary
+ virtual bases. */
+ if (in_subjobject
+ && is_virtual_base_of (TREE_TYPE (field), type)
+ && CLASSTYPE_PRIMARY_BINFO (type)
+ && !same_type_p (BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (type)),
+ TREE_TYPE (field)))
+ continue;
+
/* Note that for class types there will be FIELD_DECLs
corresponding to base classes as well. Thus, iterating
over TYPE_FIELDs will result in correct initialization of
all of the subobjects. */
if (!static_storage_p || !zero_init_p (TREE_TYPE (field)))
{
- tree value = build_zero_init (TREE_TYPE (field),
- /*nelts=*/NULL_TREE,
- static_storage_p);
+ tree value = build_zero_init_1 (TREE_TYPE (field),
+ /*nelts=*/NULL_TREE,
+ static_storage_p,
+ /*in_subobject=*/true);
if (value)
CONSTRUCTOR_APPEND_ELT(v, field, value);
}
@@ -244,9 +251,10 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
max_index);
- ce->value = build_zero_init (TREE_TYPE (type),
- /*nelts=*/NULL_TREE,
- static_storage_p);
+ ce->value = build_zero_init_1 (TREE_TYPE (type),
+ /*nelts=*/NULL_TREE,
+ static_storage_p,
+ false);
}
/* Build a constructor to contain the initializations. */
@@ -264,6 +272,26 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
return init;
}
+/* Return an expression for the zero-initialization of an object with
+ type T. This expression will either be a constant (in the case
+ that T is a scalar), or a CONSTRUCTOR (in the case that T is an
+ aggregate), or NULL (in the case that T does not require
+ initialization). In either case, the value can be used as
+ DECL_INITIAL for a decl of the indicated TYPE; it is a valid static
+ initializer. If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS
+ is the number of elements in the array. If STATIC_STORAGE_P is
+ TRUE, initializers are only generated for entities for which
+ zero-initialization does not simply mean filling the storage with
+ zero bytes. */
+
+tree
+build_zero_init (tree type, tree nelts, bool static_storage_p)
+{
+ return build_zero_init_1 (type, nelts,
+ static_storage_p,
+ /*in_subobject=*/false);
+}
+
/* Return a suitable initializer for value-initializing an object of type
TYPE, as described in [dcl.init]. */
new file mode 100644
@@ -0,0 +1,52 @@
+// Origin PR c++/PR48035
+// { dg-do run }
+
+#include <new>
+#include <cstring>
+#include <cstdlib>
+
+struct A
+{
+ virtual void foo (void) {}
+ virtual ~A () {}
+};
+
+struct B : public A
+{
+ virtual ~B () {}
+};
+
+struct C
+{
+ virtual ~C ()
+ {
+ }
+ int c;
+};
+
+struct D : public virtual B, public C
+{
+ virtual ~D () {}
+};
+
+struct E : public virtual D
+{
+ virtual ~E ()
+ {
+ }
+};
+
+int
+main ()
+{
+ char *v = new char[sizeof (E) + 16];
+ memset (v, 0x55, sizeof (E) + 16);
+ E *e = new (v) E ();
+ e->~E ();
+
+ for (unsigned i = sizeof (E); i < sizeof (E) + 16; ++i)
+ if (v[i] != 0x55)
+ abort();
+ delete[] v;
+}
+