* C++0x Constructor Delegation
@ 2007-03-03 19:04 Pedro Lamarão
2007-03-03 19:27 ` Andrew Pinski
2007-08-17 20:44 ` C++0x Constructor Delegation take 2 Jason Merrill
0 siblings, 2 replies; 9+ messages in thread
From: Pedro Lamarão @ 2007-03-03 19:04 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 772 bytes --]
This patch implements the "Delegating Constructor" feature in C++0x.
mode. The feature is included in the current working draft.
With constructor delegation one is allowed to try code such as:
struct A {
int handle;
A (int i) : handle(i) { }
A () : A(-1) { } // Delegate construction.
};
Tested on i686-pc-linux-gnu with no regressions.
2007-03-03 Pedro Lamarão <pedro.lamarao@mndfck.org>
* init.c(expand_member_init): accept constructor delegation
in C++0x mode.
(emit_mem_initializers): check for a target constructor
and delegate.
(perform_target_ctor): new function.
2007-03-03 Pedro Lamarão <pedro.lamarao@mndfck.org>
* g++.dg/cpp0x/dc_01.C: new file.
* g++.dg/cpp0x/dc_02.C: new file.
* g++.dg/cpp0x/dc_03.C: new file.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dc.patch --]
[-- Type: text/x-patch; name="dc.patch", Size: 2578 bytes --]
Index: init.c
===================================================================
--- init.c (revisão 36)
+++ 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. */
@@ -664,11 +688,41 @@ sort_mem_initializers (tree t, tree mem_
void
emit_mem_initializers (tree mem_inits)
{
+ tree init;
+ tree target_ctor = NULL_TREE;
+
/* We will already have issued an error message about the fact that
the type is incomplete. */
if (!COMPLETE_TYPE_P (current_class_type))
return;
+ /* Search for target constructors. */
+ for (init = mem_inits; init; init = TREE_CHAIN (init))
+ {
+ if ((TYPE_P (TREE_PURPOSE (init))
+ || TREE_CODE (TREE_PURPOSE (init)) == TYPE_DECL)
+ && same_type_p(TREE_PURPOSE (init), current_class_type))
+ {
+ target_ctor = TREE_VALUE (init);
+ break;
+ }
+ }
+
+ /* If we have a target constructor, validate it and delegate. */
+ if (target_ctor != NULL_TREE)
+ {
+ if (TREE_CHAIN (mem_inits) != NULL_TREE)
+ {
+ error ("target constructor must be the only initializer");
+ return;
+ }
+ else
+ {
+ perform_target_ctor (target_ctor);
+ return;
+ }
+ }
+
/* Sort the mem-initializers into the order in which the
initializations should be performed. */
mem_inits = sort_mem_initializers (current_class_type, mem_inits);
@@ -994,6 +1048,10 @@ expand_member_init (tree name)
tree virtual_binfo;
int i;
+ /* In C++0x we accept constructor delegation. */
+ if (flag_cpp0x && same_type_p (basetype, current_class_type))
+ return basetype;
+
if (current_template_parms)
return basetype;
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: dc_testsuite.patch --]
[-- Type: text/x-patch; name="dc_testsuite.patch", Size: 2845 bytes --]
Index: g++.dg/cpp0x/dc_01.C
===================================================================
--- g++.dg/cpp0x/dc_01.C (revisão 0)
+++ g++.dg/cpp0x/dc_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<int>(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 <typename T>
+struct E {
+
+ T t;
+
+ E () : E(T()) { }
+
+ E (T _t) : t(_t) { }
+
+};
+
+void f_E () { E<int> e; }
+
Index: g++.dg/cpp0x/dc_02.C
===================================================================
--- g++.dg/cpp0x/dc_02.C (revisão 0)
+++ g++.dg/cpp0x/dc_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: g++.dg/cpp0x/dc_03.C
===================================================================
--- g++.dg/cpp0x/dc_03.C (revisão 0)
+++ g++.dg/cpp0x/dc_03.C (revisão 0)
@@ -0,0 +1,93 @@
+// { dg-do compile }
+// { dg-options --std=gnu++0x }
+
+struct x { };
+
+struct B {
+
+ int i;
+
+ B (int _i) : i(_i) { }
+
+ ~B () { i = 0; }
+
+};
+
+template <typename T>
+struct A : public B {
+
+ A () : B(-1) { }
+
+ ~A () { }
+
+};
+
+template <typename T>
+struct A<T*> : public B {
+
+ A () : B(-1) { }
+
+ A (int i) : A() { }
+
+ A (double b) : A(static_cast<int>(b)) { }
+
+ A (double b, double b2) : A(b2) { }
+
+ ~A () { }
+
+};
+
+void f_A () { A<x*> a(2.0, 3.0); }
+
+struct C {
+
+ C () { }
+
+ virtual ~C() { }
+
+ virtual int f () = 0;
+
+};
+
+template <typename T>
+struct D : public C {
+
+ int i;
+
+ D (int _i) : C(), i(_i) { }
+
+};
+
+template <>
+struct D<x> : public C {
+
+ int i;
+
+ D (int _i) : C(), i(_i) { }
+
+ D () : D(-1) { }
+
+ virtual ~D() { }
+
+ virtual int f () { }
+
+};
+
+void f_D () { D<x>* d = new D<x>(); }
+
+template <typename T>
+struct E {
+};
+
+template <>
+struct E<int> {
+
+ int i;
+
+ E () : E(0) { }
+
+ E (int _i) : i(_i) { }
+
+};
+
+void f_E () { E<int> e; }
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation
2007-03-03 19:04 C++0x Constructor Delegation Pedro Lamarão
@ 2007-03-03 19:27 ` Andrew Pinski
2007-03-04 18:11 ` Mark Mitchell
2007-08-17 20:44 ` C++0x Constructor Delegation take 2 Jason Merrill
1 sibling, 1 reply; 9+ messages in thread
From: Andrew Pinski @ 2007-03-03 19:27 UTC (permalink / raw)
To: Pedro Lamarão; +Cc: gcc-patches
On 3/3/07, Pedro Lamarão <pedro.lamarao@mndfck.org> wrote:
> This patch implements the "Delegating Constructor" feature in C++0x.
> mode. The feature is included in the current working draft.
>
> With constructor delegation one is allowed to try code such as:
>
> struct A {
>
> int handle;
>
> A (int i) : handle(i) { }
>
> A () : A(-1) { } // Delegate construction.
>
> };
>
> Tested on i686-pc-linux-gnu with no regressions.
>
>
> 2007-03-03 Pedro Lamarão <pedro.lamarao@mndfck.org>
>
> * init.c(expand_member_init): accept constructor delegation
> in C++0x mode.
> (emit_mem_initializers): check for a target constructor
> and delegate.
> (perform_target_ctor): new function.
I think emit_mem_initializers check could be improved, and only have a
loop in the case of the error and also only in C++0x mode because it
might slow down the compiler too much.
Something like:
#define CTOR_DELAGE_P(type) (TYPE_P (TREE_PURPOSE (init)) \
|| TREE_CODE (TREE_PURPOSE (init)) == TYPE_DECL) \
&& same_type_p(TREE_PURPOSE (init), current_class_type))
if (flag_cpp0x)
{
if (!CTOR_DELAGE_P (TREE_PURPOSE (mem_inits))
|| TREE_CHAIN (mem_inits))
{
for (init = mem_inits; init; init = TREE_CHAIN (init))
{
if (CTOR_DELAGE_P (TREE_PURPOSE (mem_inits)))
{
error ("target constructor must be the only initializer");
return;
}
}
}
else
{
perform_target_ctor (TREE_VALUE (mem_inits));
return;
}
}
Note I wrote this in the email editor so I could have mistakes,
Even though the common case in C++0x will be slower, the C++98/03 case
is not going to be much slower.
Thanks,
Andrew Pinski
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation
2007-03-03 19:27 ` Andrew Pinski
@ 2007-03-04 18:11 ` Mark Mitchell
2007-03-04 20:50 ` Pedro Lamarão
0 siblings, 1 reply; 9+ messages in thread
From: Mark Mitchell @ 2007-03-04 18:11 UTC (permalink / raw)
To: Andrew Pinski; +Cc: Pedro Lamarão, gcc-patches
Andrew Pinski wrote:
> I think emit_mem_initializers check could be improved, and only have a
> loop in the case of the error and also only in C++0x mode because it
> might slow down the compiler too much.
Rather, this check should just be done in the parser, as it can know
what names indicate a base/member and which name a constructor. It just
has to maintain a seen-delegate bit. That follows the principle of
keeping invalid representations contained as tightly as possible within
the C++ front end.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation
2007-03-04 18:11 ` Mark Mitchell
@ 2007-03-04 20:50 ` Pedro Lamarão
0 siblings, 0 replies; 9+ messages in thread
From: Pedro Lamarão @ 2007-03-04 20:50 UTC (permalink / raw)
To: Mark Mitchell; +Cc: Andrew Pinski, gcc-patches
Mark Mitchell escreveu:
> Andrew Pinski wrote:
>
>
>> I think emit_mem_initializers check could be improved, and only have a
>> loop in the case of the error and also only in C++0x mode because it
>> might slow down the compiler too much.
>>
>
> Rather, this check should just be done in the parser, as it can know
> what names indicate a base/member and which name a constructor. It just
> has to maintain a seen-delegate bit. That follows the principle of
> keeping invalid representations contained as tightly as possible within
> the C++ front end.
>
I do have a different version of the patch with checks in
cp_parser_mem_initializer_list.
I'll polish it a little and send it for review.
--
Pedro Lamarão
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation take 2
2007-03-03 19:04 C++0x Constructor Delegation Pedro Lamarão
2007-03-03 19:27 ` Andrew Pinski
@ 2007-08-17 20:44 ` Jason Merrill
1 sibling, 0 replies; 9+ messages in thread
From: Jason Merrill @ 2007-08-17 20:44 UTC (permalink / raw)
To: pedro.lamarao, gcc-patches List, Douglas Gregor
Sorry about the delay in reviewing this. Just to make sure, do you have
a copyright assignment on file with the FSF?
It seems to me that we could move the new code in
cp_parser_mem_initializer_list inside the existing "if (mem_initializer
!= error_mark_node)" block rather than testing that same condition
repeatedly.
More significantly, in cases like this where the C++0x syntax is
ill-formed in C++98, please give a useful diagnostic ("you need to use
-std=gnu++0x") rather than fall back on the old error.
Jason
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation take 2
@ 2009-08-28 0:38 Jason Merrill
0 siblings, 0 replies; 9+ messages in thread
From: Jason Merrill @ 2009-08-28 0:38 UTC (permalink / raw)
To: Pedro Lamarão, gcc-patches List
> http://gcc.gnu.org/ml/gcc-patches/2007-04/msg00620.html
Thanks a lot for the submission, and I'm sorry it has taken this long to
review the patch. Please do CC me on C++ patches, and ping me if a week
goes by without a review.
I agree with Doug's comments.
The tests for flag_cpp0x now need to be "cxx_dialect != cxx98".
> +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);
> + }
> +}
This assumes that we'll only do delegation for the complete constructor,
which is not the case. For instance, this testcase breaks:
int c;
struct A
{
A() { ++c; }
};
struct B: virtual A
{
B(): B (1) {}
B(int) {}
};
struct C: public B
{
C(): A(), B() { }
};
int main()
{
C cee;
if (c > 1)
return c;
else if (c == 0)
return 1;
}
We end up constructing the A subobject twice, because the B()
not-in-charge constructor calls the B(int) in-charge constructor, which
wrongly calls the A constructor.
Jason
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation take 2
2007-04-24 15:42 ` Doug Gregor
@ 2007-06-29 22:05 ` Doug Gregor
0 siblings, 0 replies; 9+ messages in thread
From: Doug Gregor @ 2007-06-29 22:05 UTC (permalink / raw)
To: Pedro Lamarão; +Cc: gcc-patches
Hi Pedro,
With your patch, I'm starting to see a new failure in C++0x mode. I'm
not sure if this is a change from C++98 to C++0x, or whether it's
revealing a bug in the delegating constructors code:
The test case is gcc/testsuite/g++.dg/init/brace6.C in Subversion,
also shown below. In C++0x mode, we don't emit the error for the
second dg-error and we emit something different for the third
dg-error.
- Doug
/* PR c++/30759 */
/* { dg-do "compile" } */
struct A {
A(int) { }
};
struct B {
B(const B&);
int b;
};
struct C {};
struct D { int c; };
int main()
{
int i = { 1 };
int j = { 1, 2 }; /* { dg-error "requires one element" } */
A a = { 6 }; /* { dg-error "initializer for non" } */
B b = { 6 }; /* { dg-error "initializer for non" } */
C c = { 6 }; /* { dg-error "too many initializers" } */
D d = { 6 };
}
On 4/24/07, Doug Gregor <doug.gregor@gmail.com> wrote:
> Hi Pedro,
>
> I have a few small comments to make about this version of the patch.
> Otherwise, it looks good to me. However, I don't have the ability to
> approve it. Nathan, could you take a look?
>
> Index: gcc/testsuite/g++.dg/cpp0x/dc_02.C
> ===================================================================
> --- gcc/testsuite/g++.dg/cpp0x/dc_02.C (revisão 0)
> +++ gcc/testsuite/g++.dg/cpp0x/dc_02.C (revisão 0)
> @@ -0,0 +1,35 @@
> +// { dg-do compile }
> +// { dg-options --std=gnu++0x }
>
> I suggest using "-std=c++0x", since delegating constructors are in the
> C++0x Working Paper (we're not relying on extensions at all).
>
> +/* 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)
>
> I suggest adding a comment stating that this routine implements the
> delegating constructors feature of C++0x.
>
> - Doug
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: C++0x Constructor Delegation take 2
2007-04-12 4:53 Pedro Lamarão
@ 2007-04-24 15:42 ` Doug Gregor
2007-06-29 22:05 ` Doug Gregor
0 siblings, 1 reply; 9+ messages in thread
From: Doug Gregor @ 2007-04-24 15:42 UTC (permalink / raw)
To: Pedro Lamarão, Nathan Sidwell; +Cc: gcc-patches
Hi Pedro,
I have a few small comments to make about this version of the patch.
Otherwise, it looks good to me. However, I don't have the ability to
approve it. Nathan, could you take a look?
Index: gcc/testsuite/g++.dg/cpp0x/dc_02.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/dc_02.C (revisão 0)
+++ gcc/testsuite/g++.dg/cpp0x/dc_02.C (revisão 0)
@@ -0,0 +1,35 @@
+// { dg-do compile }
+// { dg-options --std=gnu++0x }
I suggest using "-std=c++0x", since delegating constructors are in the
C++0x Working Paper (we're not relying on extensions at all).
+/* 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)
I suggest adding a comment stating that this routine implements the
delegating constructors feature of C++0x.
- Doug
^ permalink raw reply [flat|nested] 9+ messages in thread
* C++0x Constructor Delegation take 2
@ 2007-04-12 4:53 Pedro Lamarão
2007-04-24 15:42 ` Doug Gregor
0 siblings, 1 reply; 9+ messages in thread
From: Pedro Lamarão @ 2007-04-12 4:53 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 630 bytes --]
It took me a while but here goes.
Tested the c++ front-end and libstdc++, no regressions.
--
Pedro Lamarão
2007-04-11 Pedro Lamarão <pedro.lamarao@mndfck.org>
* parser.c(cp_parser_mem_initializer_list): make sure the rules
constructor delegation are followed.
* init.c(expand_member_init): return properly if name is a
target constructor.
(emit_mem_initializers): if initializer is a target constructor,
delegate.
(perform_target_ctor): new function.
2007-04-11 Pedro Lamarão <pedro.lamarao@mndfck.org>
* g++.dg/cpp0x/dc_01.C: new test.
* g++.dg/cpp0x/dc_02.C: new test.
* g++.dg/cpp0x/dc_03.C: new test.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dc.patch --]
[-- Type: text/x-patch; name="dc.patch", Size: 6911 bytes --]
Index: gcc/testsuite/g++.dg/cpp0x/dc_02.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/dc_02.C (revisão 0)
+++ gcc/testsuite/g++.dg/cpp0x/dc_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/cpp0x/dc_01.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/dc_01.C (revisão 0)
+++ gcc/testsuite/g++.dg/cpp0x/dc_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<int>(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 <typename T>
+struct E {
+
+ T t;
+
+ E () : E(T()) { }
+
+ E (T _t) : t(_t) { }
+
+};
+
+void f_E () { E<int> e; }
+
Index: gcc/testsuite/g++.dg/cpp0x/dc_03.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/dc_03.C (revisão 0)
+++ gcc/testsuite/g++.dg/cpp0x/dc_03.C (revisão 0)
@@ -0,0 +1,93 @@
+// { dg-do compile }
+// { dg-options --std=gnu++0x }
+
+struct x { };
+
+struct B {
+
+ int i;
+
+ B (int _i) : i(_i) { }
+
+ ~B () { i = 0; }
+
+};
+
+template <typename T>
+struct A : public B {
+
+ A () : B(-1) { }
+
+ ~A () { }
+
+};
+
+template <typename T>
+struct A<T*> : public B {
+
+ A () : B(-1) { }
+
+ A (int i) : A() { }
+
+ A (double b) : A(static_cast<int>(b)) { }
+
+ A (double b, double b2) : A(b2) { }
+
+ ~A () { }
+
+};
+
+void f_A () { A<x*> a(2.0, 3.0); }
+
+struct C {
+
+ C () { }
+
+ virtual ~C() { }
+
+ virtual int f () = 0;
+
+};
+
+template <typename T>
+struct D : public C {
+
+ int i;
+
+ D (int _i) : C(), i(_i) { }
+
+};
+
+template <>
+struct D<x> : public C {
+
+ int i;
+
+ D (int _i) : C(), i(_i) { }
+
+ D () : D(-1) { }
+
+ virtual ~D() { }
+
+ virtual int f () { }
+
+};
+
+void f_D () { D<x>* d = new D<x>(); }
+
+template <typename T>
+struct E {
+};
+
+template <>
+struct E<int> {
+
+ int i;
+
+ E () : E(0) { }
+
+ E (int _i) : i(_i) { }
+
+};
+
+void f_E () { E<int> e; }
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c (revisão 123734)
+++ 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. */
@@ -669,6 +693,16 @@ emit_mem_initializers (tree mem_inits)
if (!COMPLETE_TYPE_P (current_class_type))
return;
+ if (flag_cpp0x
+ && mem_inits
+ && TYPE_P (TREE_PURPOSE (mem_inits))
+ && same_type_p (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. */
mem_inits = sort_mem_initializers (current_class_type, mem_inits);
@@ -979,11 +1013,18 @@ expand_member_init (tree name)
}
else if (TYPE_P (name))
{
+ if (flag_cpp0x && same_type_p (name, current_class_type))
+ return name;
basetype = TYPE_MAIN_VARIANT (name);
name = TYPE_NAME (name);
}
else if (TREE_CODE (name) == TYPE_DECL)
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
+ {
+ if (flag_cpp0x
+ && same_type_p (TREE_TYPE (name), current_class_type))
+ return TREE_TYPE (name);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
+ }
else
basetype = NULL_TREE;
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revisão 123734)
+++ gcc/cp/parser.c (cópia de trabalho)
@@ -8466,6 +8466,7 @@ static void
cp_parser_mem_initializer_list (cp_parser* parser)
{
tree mem_initializer_list = NULL_TREE;
+ tree target_ctor = error_mark_node;
/* Let the semantic analysis code know that we are starting the
mem-initializer-list. */
@@ -8499,6 +8500,31 @@ cp_parser_mem_initializer_list (cp_parse
if (mem_initializer != error_mark_node)
mem_initializer = make_pack_expansion (mem_initializer);
}
+ if (target_ctor != error_mark_node
+ && mem_initializer != error_mark_node)
+ {
+ error ("seeing initializer for member %<%D%>; "
+ "previous target constructor for %T must be sole initializer",
+ TREE_PURPOSE (mem_initializer),
+ TREE_PURPOSE (target_ctor));
+ mem_initializer = error_mark_node;
+ }
+ /* Look for a target constructor. */
+ if (flag_cpp0x
+ && mem_initializer != error_mark_node
+ && TYPE_P (TREE_PURPOSE (mem_initializer))
+ && same_type_p (TREE_PURPOSE (mem_initializer), current_class_type))
+ {
+ if (mem_initializer_list)
+ {
+ error ("target constructor for %T must be sole initializer; "
+ "saw previous initializer for member %<%D%>",
+ TREE_PURPOSE (mem_initializer),
+ TREE_PURPOSE (mem_initializer_list));
+ mem_initializer = error_mark_node;
+ }
+ target_ctor = mem_initializer;
+ }
/* Add it to the list, unless it was erroneous. */
if (mem_initializer != error_mark_node)
{
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-08-27 21:39 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-03 19:04 C++0x Constructor Delegation Pedro Lamarão
2007-03-03 19:27 ` Andrew Pinski
2007-03-04 18:11 ` Mark Mitchell
2007-03-04 20:50 ` Pedro Lamarão
2007-08-17 20:44 ` C++0x Constructor Delegation take 2 Jason Merrill
2007-04-12 4:53 Pedro Lamarão
2007-04-24 15:42 ` Doug Gregor
2007-06-29 22:05 ` Doug Gregor
2009-08-28 0:38 Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).