diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1325260..4c6c9d5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4b49046..558c38b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 56f66fa..440db79 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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].  */
 
diff --git a/gcc/testsuite/g++.dg/inherit/virtual8.C b/gcc/testsuite/g++.dg/inherit/virtual8.C
new file mode 100644
index 0000000..62bdc3b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/virtual8.C
@@ -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;
+}
+
