This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++0x Constructor Delegation take 2


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]