From: "Pedro Lamarão" <pedro.lamarao@mndfck.org>
To: gcc-patches@gcc.gnu.org
Subject: C++0x Constructor Delegation take 2
Date: Thu, 12 Apr 2007 04:53:00 -0000 [thread overview]
Message-ID: <461DBB2D.4010309@mndfck.org> (raw)
[-- 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)
{
next reply other threads:[~2007-04-12 4:53 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-12 4:53 Pedro Lamarão [this message]
2007-04-24 15:42 ` Doug Gregor
2007-06-29 22:05 ` Doug Gregor
-- strict thread matches above, loose matches on Subject: below --
2009-08-28 0:38 Jason Merrill
2007-03-03 19:04 C++0x Constructor Delegation Pedro Lamarão
2007-08-17 20:44 ` C++0x Constructor Delegation take 2 Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=461DBB2D.4010309@mndfck.org \
--to=pedro.lamarao@mndfck.org \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).