diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c9ce9ce44b6..1c53d89ffc8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2008-11-28 Jason Merrill + PR c++/38233 + * init.c (perform_member_init): Fix value-initialization. + (build_value_init_1): Add assert to catch cases that will break + in the gimplifier. + (build_default_init): Remove. + * cp-tree.h: Remove its prototype. + * pt.c (tsubst_expr) [DECL_EXPR]: Use build_value_init for + value-initialization. + PR c++/38278 * parser.c (cp_parser_class_name): Only call maybe_note_name_used_in_class if we actually found a class name. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9f10ed17c34..a03fe9bfae5 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4468,7 +4468,6 @@ extern tree build_new (tree, tree, tree, tree, int, tsubst_flags_t); extern tree build_vec_init (tree, tree, tree, bool, int, tsubst_flags_t); -extern tree build_default_init (tree, tree); extern tree build_delete (tree, tree, special_function_kind, int, int); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 61c78e11f62..39d87e3669f 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -266,52 +266,6 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) return init; } -/* Build an expression for the default-initialization of an object of - the indicated TYPE. If NELTS is non-NULL, and TYPE is an - ARRAY_TYPE, NELTS is the number of elements in the array. If - initialization of TYPE requires calling constructors, this function - returns NULL_TREE; the caller is responsible for arranging for the - constructors to be called. */ - -tree -build_default_init (tree type, tree nelts) -{ - /* [dcl.init]: - - To default-initialize an object of type T means: - - --if T is a non-POD class type (clause _class_), the default construc- - tor for T is called (and the initialization is ill-formed if T has - no accessible default constructor); - - --if T is an array type, each element is default-initialized; - - --otherwise, the storage for the object is zero-initialized. - - A program that calls for default-initialization of an entity of refer- - ence type is ill-formed. */ - - /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for - performing the initialization. This is confusing in that some - non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example, - a class with a pointer-to-data member as a non-static data member - does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up - passing non-PODs to build_zero_init below, which is contrary to - the semantics quoted above from [dcl.init]. - - It happens, however, that the behavior of the constructor the - standard says we should have generated would be precisely the - same as that obtained by calling build_zero_init below, so things - work out OK. */ - if (TYPE_NEEDS_CONSTRUCTING (type) - || (nelts && TREE_CODE (nelts) != INTEGER_CST)) - return NULL_TREE; - - /* At this point, TYPE is either a POD class type, an array of POD - classes, or something even more innocuous. */ - return build_zero_init (type, nelts, /*static_storage_p=*/false); -} - /* Return a suitable initializer for value-initializing an object of type TYPE, as described in [dcl.init]. If HAVE_CTOR is true, the initializer for an enclosing object is already calling the constructor for this @@ -442,6 +396,10 @@ build_value_init_1 (tree type, bool have_ctor) max_index); ce->value = build_value_init_1 (TREE_TYPE (type), have_ctor); + + /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */ + gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR + && TREE_CODE (ce->value) != AGGR_INIT_EXPR); } /* Build a constructor to contain the initializations. */ @@ -469,19 +427,13 @@ perform_member_init (tree member, tree init) { tree decl; tree type = TREE_TYPE (member); - bool is_explicit; - - is_explicit = (init != NULL_TREE); /* Effective C++ rule 12 requires that all data members be initialized. */ - if (warn_ecpp && !is_explicit && TREE_CODE (type) != ARRAY_TYPE) + if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE) warning (OPT_Weffc__, "%J%qD should be initialized in the member initialization " "list", current_function_decl, member); - if (init == void_type_node) - init = NULL_TREE; - /* Get an lvalue for the data member. */ decl = build_class_member_access_expr (current_class_ref, member, /*access_path=*/NULL_TREE, @@ -490,10 +442,28 @@ perform_member_init (tree member, tree init) if (decl == error_mark_node) return; + if (init == void_type_node) + { + /* mem() means value-initialization. */ + if (TREE_CODE (type) == ARRAY_TYPE) + init = build_vec_init (decl, NULL_TREE, NULL_TREE, + /*explicit_value_init_p=*/true, + /* from_array=*/0, + tf_warning_or_error); + else + { + if (TREE_CODE (type) == REFERENCE_TYPE) + warning (0, "%Jdefault-initialization of %q#D, " + "which has reference type", + current_function_decl, member); + init = build2 (INIT_EXPR, type, decl, build_value_init (type)); + } + finish_expr_stmt (init); + } /* Deal with this here, as we will get confused if we try to call the assignment op for an anonymous union. This can happen in a synthesized copy constructor. */ - if (ANON_AGGR_TYPE_P (type)) + else if (ANON_AGGR_TYPE_P (type)) { if (init) { @@ -503,9 +473,8 @@ perform_member_init (tree member, tree init) } else if (TYPE_NEEDS_CONSTRUCTING (type)) { - if (is_explicit + if (init != NULL_TREE && TREE_CODE (type) == ARRAY_TYPE - && init != NULL_TREE && TREE_CHAIN (init) == NULL_TREE && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) { @@ -532,16 +501,8 @@ perform_member_init (tree member, tree init) { if (init == NULL_TREE) { - if (is_explicit) - { - init = build_default_init (type, /*nelts=*/NULL_TREE); - if (TREE_CODE (type) == REFERENCE_TYPE) - warning (0, "%Jdefault-initialization of %q#D, " - "which has reference type", - current_function_decl, member); - } /* member traversal: note it leaves init NULL */ - else if (TREE_CODE (type) == REFERENCE_TYPE) + if (TREE_CODE (type) == REFERENCE_TYPE) permerror (input_location, "%Juninitialized reference member %qD", current_function_decl, member); else if (CP_TYPE_CONST_P (type)) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 127d37c833d..241cea6423a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10560,8 +10560,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, pack expansion where the parameter packs used in that expansion were of length zero. */ - init = build_default_init (TREE_TYPE (decl), - NULL_TREE); + init = build_value_init (TREE_TYPE (decl)); else init = t; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 30d4445abcf..7f8786bb3ea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2008-11-28 Jason Merrill + PR c++/38233 + * g++.dg/init/array25.C: New test. + * g++.dg/init/value4.C: New test. + PR c++/38278 * g++.dg/lookup/name-clash8.C: New test. diff --git a/gcc/testsuite/g++.dg/init/array25.C b/gcc/testsuite/g++.dg/init/array25.C new file mode 100644 index 00000000000..1ab2725d7cf --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array25.C @@ -0,0 +1,49 @@ +// related to PR c++/38233 +// test for value-init of a member array +// { dg-do run } + +struct elt +{ + virtual void f(); + char c; +}; + +void elt::f() { } + +struct foo { + elt buffer[500]; + foo() ; + bool check () const; +}; + +foo::foo () + : buffer() +{} + +bool foo::check () const +{ + for (unsigned ix = sizeof (buffer)/ sizeof (buffer[0]); ix--;) + if (buffer[ix].c) + return false; + return true; +} + +inline void *operator new (__SIZE_TYPE__ size, void *p) +{ + return p; +} + +char heap[sizeof(elt[500])]; + +int main () +{ + for (unsigned ix = sizeof (heap); ix--;) + heap[ix] = ix; + + foo *f = new (heap) foo (); + if (!f->check ()) + return 3; + return 0; +} + + diff --git a/gcc/testsuite/g++.dg/init/value4.C b/gcc/testsuite/g++.dg/init/value4.C new file mode 100644 index 00000000000..fa7a02cc7c6 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/value4.C @@ -0,0 +1,35 @@ +// PR c++/38233 + +template + struct pair + { + _T1 first; + _T2 second; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 265. std::pair::pair() effects overly restrictive + /** The default constructor creates @c first and @c second using their + * respective default constructors. */ + pair() + : first(), second() { } +}; + +class a { + public: + a(); +}; + +class b { + public: + // implicit default ctor + bool operator<(const b& rhs) const; + + private: + a a_val; +}; + +typedef pair my_pair; + +void func() { + my_pair x; +}