From fd97a96a1049407b248f9e6927f6021ba0e02115 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 11 Feb 2009 17:38:37 -0500 Subject: [PATCH] re PR c++/30111 (Value-initialization of POD base class doesn't initialize members) PR c++/30111 * init.c (build_value_init_noctor): Split out from... (build_value_init): ...here. (expand_aggr_init_1): Handle value-initialization. * cp-tree.h: Add declaration. * class.c (type_has_user_provided_constructor): Handle non-class arguments. From-SVN: r144112 --- gcc/cp/ChangeLog | 10 +++++++ gcc/cp/class.c | 3 ++ gcc/cp/cp-tree.h | 1 + gcc/cp/init.c | 48 ++++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/init/value7.C | 17 +++++++++++ 6 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/init/value7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 513465d82be..58bffd77e25 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2009-02-11 Jason Merrill + + PR c++/30111 + * init.c (build_value_init_noctor): Split out from... + (build_value_init): ...here. + (expand_aggr_init_1): Handle value-initialization. + * cp-tree.h: Add declaration. + * class.c (type_has_user_provided_constructor): + Handle non-class arguments. + 2009-02-10 Jason Merrill PR c++/38649 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d852acd9065..cef23719637 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4090,6 +4090,9 @@ type_has_user_provided_constructor (tree t) { tree fns; + if (!CLASS_TYPE_P (t)) + return false; + if (!TYPE_HAS_USER_CONSTRUCTOR (t)) return false; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5bf8595a026..5a9b891668f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4476,6 +4476,7 @@ extern int is_class_type (tree, int); extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); extern tree build_value_init (tree); +extern tree build_value_init_noctor (tree); extern tree build_offset_ref (tree, tree, bool); extern tree build_new (tree, tree, tree, tree, int, tsubst_flags_t); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index d4dafedd54f..d583e3b799c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -318,7 +318,21 @@ build_value_init (tree type) AGGR_INIT_ZERO_FIRST (ctor) = 1; return ctor; } - else if (TREE_CODE (type) != UNION_TYPE) + } + return build_value_init_noctor (type); +} + +/* Like build_value_init, but don't call the constructor for TYPE. Used + for base initializers. */ + +tree +build_value_init_noctor (tree type) +{ + if (CLASS_TYPE_P (type)) + { + gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type)); + + if (TREE_CODE (type) != UNION_TYPE) { tree field; VEC(constructor_elt,gc) *v = NULL; @@ -800,11 +814,6 @@ emit_mem_initializers (tree mem_inits) "copy constructor", current_function_decl, BINFO_TYPE (subobject)); - /* If an explicit -- but empty -- initializer list was present, - treat it just like default initialization at this point. */ - if (arguments == void_type_node) - arguments = NULL_TREE; - /* Initialize the base. */ if (BINFO_VIRTUAL_P (subobject)) construct_virtual_base (subobject, arguments); @@ -1385,6 +1394,33 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, return; } + /* If an explicit -- but empty -- initializer list was present, + 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_NEEDS_CONSTRUCTING (type)) + { + init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); + 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)); + finish_expr_stmt (init); + return; + } + init = NULL_TREE; + } + /* We know that expand_default_init can handle everything we want at this point. */ expand_default_init (binfo, true_exp, exp, init, flags, complain); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9b64184478a..7c088650e97 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-02-11 Jason Merrill + + PR c++/30111 + * g++.dg/init/value7.C: New test. + 2009-02-11 Paolo Bonzini * gcc.target/i386/pr38824.c: New testcase. diff --git a/gcc/testsuite/g++.dg/init/value7.C b/gcc/testsuite/g++.dg/init/value7.C new file mode 100644 index 00000000000..c79de4a6864 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/value7.C @@ -0,0 +1,17 @@ +// PR c++/30111 +// { dg-do run } + +struct pod { + int i; +}; + +struct inherit : pod { + inherit() : pod() {} +}; + +int main() +{ + inherit i; + return i.i != 0; +} +