public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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)
 	{

             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).