Index: gcc/testsuite/g++.dg/dg_01.C =================================================================== --- gcc/testsuite/g++.dg/dg_01.C (revisão 0) +++ gcc/testsuite/g++.dg/dg_01.C (revisão 0) @@ -0,0 +1,68 @@ +// { dg-do compile } +// { dg-options --std=gnu++0x } + +struct B { + + int i; + + B (int _i) : i(_i) { } + + ~B () { i = 0; } + +}; + +struct A : public B { + + A () : B(-1) { } + + A (int i) : A() { } + + A (double b) : A(static_cast(b)) { } + + A (double b, double b2) : A(b2) { } + + ~A () { } + +}; + +void f_A () { A a(2.0, 3.0); } + +struct C { + + C () { } + + virtual ~C() { } + + virtual int f () = 0; + +}; + +struct D : public C { + + int i; + + D (int _i) : C(), i(_i) { } + + D () : D(-1) { } + + virtual ~D() { } + + virtual int f () { } + +}; + +void f_D () { C* c = new D(); } + +template +struct E { + + T t; + + E () : E(T()) { } + + E (T _t) : t(_t) { } + +}; + +void f_E () { E e; } + Index: gcc/testsuite/g++.dg/dg_02.C =================================================================== --- gcc/testsuite/g++.dg/dg_02.C (revisão 0) +++ gcc/testsuite/g++.dg/dg_02.C (revisão 0) @@ -0,0 +1,35 @@ +// { dg-do compile } +// { dg-options --std=gnu++0x } + +struct A { + + int i, j; + + A () : A(0), j(0) { } // { dg-error "" "only initializer" } + + A (int _i) : i(_i) { } + +}; + +struct B { + + int i, j; + + B () : i(0), B(0) { } // { dg-error "" "only initializer" } + + B (int _j) : j(_j) { } + +}; + +struct C { }; + +struct D : public C { + + D () : C() { } + + D (float) : D(), C() { } // { dg-error "" "only initializer" } + + D (float, float): C(), D() { } // { dg-error "" "only initializer" } + +}; + Index: gcc/testsuite/g++.dg/template/meminit1.C =================================================================== --- gcc/testsuite/g++.dg/template/meminit1.C (revisão 8) +++ gcc/testsuite/g++.dg/template/meminit1.C (cópia de trabalho) @@ -1,7 +1,7 @@ template struct S { - S() : S() {} // { dg-error "base" } + S() : S() {} // { dg-error "not allowed" } }; -S s; // { dg-error "instantiated" } +S s; Index: gcc/cp/init.c =================================================================== --- gcc/cp/init.c (revisão 8) +++ gcc/cp/init.c (cópia de trabalho) @@ -315,6 +315,30 @@ build_default_init (tree type, tree nelt return build_zero_init (type, nelts, /*static_storage_p=*/false); } +/* Initialize current class with INIT, a TREE_LIST of + arguments for a target constructor. If TREE_LIST is void_type_node, + an empty initializer list was given. */ + +static void +perform_target_ctor (tree init) +{ + tree decl = current_class_ref; + tree type = current_class_type; + + if (init == void_type_node) + init = NULL_TREE; + + finish_expr_stmt (build_aggr_init (decl, init, 0)); + + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + { + tree expr = build_delete (type, decl, sfk_complete_destructor, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); + if (expr != error_mark_node) + finish_eh_cleanup (expr); + } +} + /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of arguments. If TREE_LIST is void_type_node, an empty initializer list was given; if NULL_TREE no initializer was given. */ @@ -668,6 +692,14 @@ emit_mem_initializers (tree mem_inits) the type is incomplete. */ if (!COMPLETE_TYPE_P (current_class_type)) return; + + /* If the initializer is a target constructor, delegate. */ + if (mem_inits && TREE_PURPOSE (mem_inits) == current_class_type) + { + gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE); + perform_target_ctor (TREE_VALUE (mem_inits)); + return; + } /* Sort the mem-initializers into the order in which the initializations should be performed. */ @@ -681,6 +713,8 @@ emit_mem_initializers (tree mem_inits) { tree subobject = TREE_PURPOSE (mem_inits); tree arguments = TREE_VALUE (mem_inits); + + gcc_assert (subobject != current_class_type); /* If these initializations are taking place in a copy constructor, the base class should probably be explicitly @@ -994,6 +1028,16 @@ expand_member_init (tree name) tree virtual_binfo; int i; + /* C++0x: look for a target constructor. */ + if (basetype == current_class_type) + { + if (flag_cpp0x) + return basetype; + else + error ("%qT invalid in this context: delegating construction is " + "not allowed", basetype); + } + if (current_template_parms) return basetype; Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revisão 8) +++ gcc/cp/parser.c (cópia de trabalho) @@ -8014,11 +8014,23 @@ cp_parser_mem_initializer_list (cp_parse TREE_CHAIN (mem_initializer) = mem_initializer_list; mem_initializer_list = mem_initializer; } - /* If the next token is not a `,', we're done. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) - break; - /* Consume the `,' token. */ - cp_lexer_consume_token (parser->lexer); + + if (mem_initializer != error_mark_node + && TREE_PURPOSE (mem_initializer) == current_class_type) + { + if (TREE_CHAIN (mem_initializer) + || cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + error ("target constructor must be the only initializer"); + return; + } + else + { + /* If the next token is not a `,', we're done. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + /* Consume the `,' token. */ + cp_lexer_consume_token (parser->lexer); + } } /* Perform semantic analysis. */