diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 562d08356f9..de9cd1f06dd 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -189,15 +189,21 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p, init = build_zero_cst (type); else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type))) { - tree field; + tree field, next; vec *v = NULL; /* Iterate over the fields, building initializations. */ - for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = next) { + next = DECL_CHAIN (field); + if (TREE_CODE (field) != FIELD_DECL) continue; + /* For unions, only the first field is initialized. */ + if (TREE_CODE (type) == UNION_TYPE) + next = NULL_TREE; + if (TREE_TYPE (field) == error_mark_node) continue; @@ -212,6 +218,11 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p, continue; } + /* Don't add zero width bitfields. */ + if (DECL_C_BIT_FIELD (field) + && integer_zerop (DECL_SIZE (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 @@ -230,10 +241,6 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p, if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); } - - /* For unions, only the first field is initialized. */ - if (TREE_CODE (type) == UNION_TYPE) - break; } /* Build a constructor to contain the initializations. */ diff --git a/gcc/testsuite/g++.dg/init/pr109868.C b/gcc/testsuite/g++.dg/init/pr109868.C new file mode 100644 index 00000000000..0926f406e4f --- /dev/null +++ b/gcc/testsuite/g++.dg/init/pr109868.C @@ -0,0 +1,13 @@ +// PR c++/109868 +// { dg-do compile } +// { dg-options "-O2" } + +struct A { virtual void foo (); }; +struct B { long b; int : 0; }; +struct C : A { B c; }; + +void +bar (C *p) +{ + *p = C (); +}