commit ae7159a0bd2822557c503cd85d911e0390aaf55d Author: Jason Merrill Date: Thu Oct 13 12:59:31 2011 -0400 PR c++/50618 * init.c (expand_aggr_init_1): Don't zero-initialize virtual bases of a base subobject. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7897fff..8a5bece 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1588,27 +1588,26 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, that's value-initialization. */ if (init == void_type_node) { - /* If there's a user-provided constructor, we just call that. */ - if (type_has_user_provided_constructor (type)) - /* Fall through. */; - /* If there isn't, but we still need to call the constructor, - zero out the object first. */ - else if (type_build_ctor_call (type)) + /* If no user-provided ctor, we need to zero out the object. */ + if (!type_has_user_provided_constructor (type)) { - init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); + tree field_size = NULL_TREE; + if (exp != true_exp + && CLASSTYPE_AS_BASE (type) != type) + /* Don't clobber already initialized virtual bases. */ + field_size = TYPE_SIZE (CLASSTYPE_AS_BASE (type)); + init = build_zero_init_1 (type, NULL_TREE, /*static_storage_p=*/false, + field_size); init = build2 (INIT_EXPR, type, exp, init); finish_expr_stmt (init); - /* And then call the constructor. */ } + /* If we don't need to mess with the constructor at all, - then just zero out the object and we're done. */ - else - { - init = build2 (INIT_EXPR, type, exp, - build_value_init_noctor (type, complain)); - finish_expr_stmt (init); - return; - } + then we're done. */ + if (! type_build_ctor_call (type)) + return; + + /* Otherwise fall through and call the constructor. */ init = NULL_TREE; } diff --git a/gcc/testsuite/g++.dg/init/vbase1.C b/gcc/testsuite/g++.dg/init/vbase1.C new file mode 100644 index 0000000..bbfd58f --- /dev/null +++ b/gcc/testsuite/g++.dg/init/vbase1.C @@ -0,0 +1,39 @@ +// PR c++/50618 +// { dg-do run } + +struct Base +{ + const int text; + Base():text(1) {} + Base(int aText) + : text(aText) {} +}; +struct SubA : public virtual Base +{ +protected: + int x; +public: + SubA(int aX) + : x(aX) {} +}; +class SubB : public virtual Base +{}; +struct Diamond : public SubA, public SubB +{ + Diamond(int text) + : Base(text), SubA(5), SubB() {} + + void printText() + { + if(text != 2) + __builtin_abort(); + if(x!=5) + __builtin_abort(); + } +}; + +int main(int, char**) +{ + Diamond x(2); + x.printText(); +}