Re: [PATCH] C++11, implement delegating constructors

2011-12-05 Thread Ville Voutilainen
On 5 December 2011 17:51, Jason Merrill  wrote:
> While applying it I noticed that we were sharing the argument trees between
> the two calls in a way that might be problematic, and I went ahead and fixed
> that.

Ouch. Thanks.

> I noticed that template/meminit1.C is ill-formed in C++11 as well, due to
> "If a constructor delegates to itself directly or indirectly, the program is
> ill-formed; no diagnostic is required."  For this simple case of direct
> delegation to itself, it should be pretty easy to give an error.  I'll open
> a PR for this.

I suppose that for complete checking of such things, we need to have a complete
class (all ctors defined), and then we'll have interesting times
instantiating whatever
dependent constructor templates. I personally think that bit should be undefined
behavior rather than ill-formed, but I guess that's for a different
forum to discuss.

> Tested x86_64-pc-linux-gnu, applying to trunk.

Thanks!


Re: [PATCH] C++11, implement delegating constructors

2011-12-05 Thread Jason Merrill
OK, I finally got permission from the FSF to put this patch in, and 
since it was posted before the end of stage 1 it can still go in.


While applying it I noticed that we were sharing the argument trees 
between the two calls in a way that might be problematic, and I went 
ahead and fixed that.


I noticed that template/meminit1.C is ill-formed in C++11 as well, due 
to "If a constructor delegates to itself directly or indirectly, the 
program is ill-formed; no diagnostic is required."  For this simple case 
of direct delegation to itself, it should be pretty easy to give an 
error.  I'll open a PR for this.


Tested x86_64-pc-linux-gnu, applying to trunk.

commit fed2dfc89a458003cdfb401d98c21deeefcdf9cb
Author: Ville Voutilainen 
Date:   Mon Oct 3 01:28:04 2011 +0300

	Implement C++11 delegating constructors.
	* cp-tree.h (enum cpp0x_warn_str): Add CPP0X_DELEGATING_CTORS.
	* error.c (maybe_warn_cpp0x): Adjust.
	* parser.c (cp_parser_mem_initializer_list): Use it.  Diagnose
	multiple initializers if a delegating initializer is present.
	* call.c (build_special_member_call): Convert an assert into an if.
	* init.c (perform_target_ctor): New.
	(emit_mem_initializers): Use it.
	(expand_member_init, expand_default_init): Adjust.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 93d14be..d8fc4f1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6978,8 +6978,10 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
 			current_in_charge_parm, integer_zero_node),
 		current_vtt_parm,
 		vtt);
-  gcc_assert (BINFO_SUBVTT_INDEX (binfo));
-  sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+  if (BINFO_SUBVTT_INDEX (binfo))
+	sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+  else
+	sub_vtt = vtt;
 
   if (args == NULL)
 	{
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3f4f408..dccf485 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -404,7 +404,9 @@ typedef enum cpp0x_warn_str
   /* non-static data member initializers */
   CPP0X_NSDMI,
   /* user defined literals */
-  CPP0X_USER_DEFINED_LITERALS
+  CPP0X_USER_DEFINED_LITERALS,
+  /* delegating constructors */
+  CPP0X_DELEGATING_CTORS
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4940a78..21d6781 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3304,6 +3304,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
 		 "user-defined literals "
 		 "only available with -std=c++11 or -std=gnu++11");
 	break;
+  case CPP0X_DELEGATING_CTORS:
+	pedwarn (input_location, 0,
+		 "delegating constructors "
+		 "only available with -std=c++11 or -std=gnu++11");
+break;
   default:
 	gcc_unreachable ();
   }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 7e9ad54..94bd34a 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -485,6 +485,30 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
   return build_zero_init (type, NULL_TREE, /*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;
+
+  finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
+ tf_warning_or_error));
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+{
+  tree expr = build_delete (type, decl, sfk_complete_destructor,
+LOOKUP_NORMAL
+|LOOKUP_NONVIRTUAL
+|LOOKUP_DESTRUCTOR,
+0, tf_warning_or_error);
+  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.  */
@@ -988,6 +1012,16 @@ emit_mem_initializers (tree mem_inits)
   if (!COMPLETE_TYPE_P (current_class_type))
 return;
 
+  if (mem_inits
+  && TYPE_P (TREE_PURPOSE (mem_inits))
+  && same_type_p (TREE_PURPOSE (mem_inits), current_class_type))
+{
+  /* Delegating constructor. */
+  gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE);
+  perform_target_ctor (TREE_VALUE (mem_inits));
+  return;
+}
+
   if (DECL_DEFAULTED_FN (current_function_decl))
 flags |= LOOKUP_DEFAULTED;
 
@@ -1318,8 +1352,9 @@ expand_member_init (tree name)
   tree virtual_binfo;
   int i;
 
-  if (current_template_parms)
-	return basetype;
+  if (same_type_p (basetype, current_class_type)
+	  || current_template_parms)
+	  return basetype;
 
   class_binfo = TYPE_BINFO (current_class_type);
   direct_binfo = NULL_TREE;
@@ -1578,13 +1613,33 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
   els

Re: [PATCH] C++11, implement delegating constructors

2011-10-02 Thread Ville Voutilainen
At Wed, 21 Sep 2011 02:34:22 +0300,
Ville Voutilainen wrote:
> 
> On 21 September 2011 02:18, Ville Voutilainen
>  wrote:
> > Ok, a new patch:
> I just noticed that I have tabs disabled. You may want to tabify the patch.

Tabified and rebased on top of the nsdmi changes. Changelog
unchanged.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a52ec29..9ab957b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6952,8 +6952,10 @@ build_special_member_call (tree instance, tree name, 
VEC(tree,gc) **args,
current_in_charge_parm, integer_zero_node),
current_vtt_parm,
vtt);
-  gcc_assert (BINFO_SUBVTT_INDEX (binfo));
-  sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+  if (BINFO_SUBVTT_INDEX (binfo))
+   sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+  else
+   sub_vtt = vtt;
 
   if (args == NULL)
{
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0f7deb6..558d433 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -396,7 +396,9 @@ typedef enum cpp0x_warn_str
   /* override controls, override/final */
   CPP0X_OVERRIDE_CONTROLS,
   /* non-static data member initializers */
-  CPP0X_NSDMI
+  CPP0X_NSDMI,
+  /* delegating constructors */
+  CPP0X_DELEGATING_CTORS
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4d12a0d..cc01718 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3242,6 +3242,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
 "non-static data member initializers "
 "only available with -std=c++0x or -std=gnu++0x");
 break;
+  case CPP0X_DELEGATING_CTORS:
+   pedwarn (input_location, 0,
+"delegating constructors "
+"only available with -std=c++0x or -std=gnu++0x");
+break;
   default:
gcc_unreachable();
   }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index f246286..7771a30 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -483,6 +483,30 @@ build_value_init_noctor (tree type, tsubst_flags_t 
complain)
   return build_zero_init (type, NULL_TREE, /*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;
+  
+  finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
+ tf_warning_or_error));
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+{
+  tree expr = build_delete (type, decl, sfk_complete_destructor,
+   LOOKUP_NORMAL
+   |LOOKUP_NONVIRTUAL
+   |LOOKUP_DESTRUCTOR,
+   0, tf_warning_or_error);
+  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.  */
@@ -940,6 +964,16 @@ emit_mem_initializers (tree mem_inits)
   if (!COMPLETE_TYPE_P (current_class_type))
 return;
 
+  if (mem_inits
+  && TYPE_P (TREE_PURPOSE (mem_inits))
+  && same_type_p (TREE_PURPOSE (mem_inits), current_class_type))
+{
+  /* Delegating constructor. */
+  gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE);
+  perform_target_ctor (TREE_VALUE (mem_inits));
+  return;
+}
+
   if (DECL_DEFAULTED_FN (current_function_decl))
 flags |= LOOKUP_DEFAULTED;
 
@@ -1270,8 +1304,9 @@ expand_member_init (tree name)
   tree virtual_binfo;
   int i;
 
-  if (current_template_parms)
-   return basetype;
+  if (same_type_p (basetype, current_class_type)
+ || current_template_parms)
+ return basetype;
 
   class_binfo = TYPE_BINFO (current_class_type);
   direct_binfo = NULL_TREE;
@@ -1510,13 +1545,33 @@ expand_default_init (tree binfo, tree true_exp, tree 
exp, tree init, int flags,
   else
 parms = make_tree_vector_single (init);
 
-  if (true_exp == exp)
-ctor_name = complete_ctor_identifier;
-  else
-ctor_name = base_ctor_identifier;
-
-  rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
-complain);
+  if (exp == current_class_ref && current_function_decl
+  && DECL_HAS_IN_CHARGE_PARM_P (current_function_decl))
+{
+  /* Delegating constructor. */
+  tree complete;
+  tree base;
+  complete = build_special_member_call (exp, complete_ctor_identifier,
+   &parms, binfo, flags,
+   complain);
+  base = build_special_member_

Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Jason Merrill

Looks good, thanks.

Jason


Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Ville Voutilainen
On 21 September 2011 02:18, Ville Voutilainen
 wrote:
> Ok, a new patch:

I just noticed that I have tabs disabled. You may want to tabify the patch.


Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Ville Voutilainen
At Tue, 20 Sep 2011 19:05:32 -0400,
Jason Merrill wrote:
> We don't need a new variable, just use basetype.  TYPE_MAIN_VARIANT 
> shouldn't affect the comparison to current_class_type.
> 
> > + error ("mem-initializer for %qD follows constructor delegation; "
> > +"previous target constructor for %T must be sole initializer",
> > + error ("target constructor for %T must be sole initializer; "
> > +"constructor delegation follows mem-initializer for %qD",
> 
> I was thinking that my suggested wording would be the whole message, not 
> just part of it.

Ok, a new patch:

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c707d66..7027b64 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7048,18 +7048,19 @@ build_special_member_call (tree instance, tree name, 
VEC(tree,gc) **args,
   vtt = DECL_CHAIN (CLASSTYPE_VTABLES (current_class_type));
   vtt = decay_conversion (vtt);
   vtt = build3 (COND_EXPR, TREE_TYPE (vtt),
-   build2 (EQ_EXPR, boolean_type_node,
-   current_in_charge_parm, integer_zero_node),
-   current_vtt_parm,
-   vtt);
-  gcc_assert (BINFO_SUBVTT_INDEX (binfo));
-  sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
-
+build2 (EQ_EXPR, boolean_type_node,
+current_in_charge_parm, integer_zero_node),
+current_vtt_parm,
+vtt);
+  if (BINFO_SUBVTT_INDEX (binfo))
+sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+  else
+sub_vtt = vtt;
   if (args == NULL)
-   {
- allocated = make_tree_vector ();
- args = &allocated;
-   }
+{
+  allocated = make_tree_vector ();
+  args = &allocated;
+}
 
   VEC_safe_insert (tree, gc, *args, 0, sub_vtt);
 }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ae4cd07..31c600e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -394,7 +394,9 @@ typedef enum cpp0x_warn_str
   /* inline namespaces */
   CPP0X_INLINE_NAMESPACES,
   /* override controls, override/final */
-  CPP0X_OVERRIDE_CONTROLS
+  CPP0X_OVERRIDE_CONTROLS,
+  /* delegating constructors */
+  CPP0X_DELEGATING_CTORS
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 598ddf1..82f3175 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3236,6 +3236,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
 "override controls (override/final) "
 "only available with -std=c++0x or -std=gnu++0x");
 break;
+  case CPP0X_DELEGATING_CTORS:
+   pedwarn (input_location, 0,
+"delegating constructors "
+"only available with -std=c++0x or -std=gnu++0x");
+break;
   default:
gcc_unreachable();
   }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ff1884b..d60dc18 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -482,6 +482,31 @@ build_value_init_noctor (tree type, tsubst_flags_t 
complain)
   return build_zero_init (type, NULL_TREE, /*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;
+
+  finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
+ tf_warning_or_error));
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+{
+  tree expr = build_delete (type, decl, sfk_complete_destructor,
+LOOKUP_NORMAL
+|LOOKUP_NONVIRTUAL
+|LOOKUP_DESTRUCTOR,
+0, tf_warning_or_error);
+  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.  */
@@ -924,6 +949,16 @@ emit_mem_initializers (tree mem_inits)
   if (!COMPLETE_TYPE_P (current_class_type))
 return;
 
+  if (mem_inits
+  && TYPE_P (TREE_PURPOSE (mem_inits))
+  && same_type_p (TREE_PURPOSE (mem_inits), current_class_type))
+{
+  /* Delegating constructor. */
+  gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE);
+  perform_target_ctor (TREE_VALUE (mem_inits));
+  return;
+}
+
   if (DECL_DEFAULTED_FN (current_function_decl))
 flags |= LOOKUP_DEFAULTED;
 
@@ -1254,8 +1289,9 @@ expand_member_init (tree name)
   tree virtual_binfo;
   int i;
 
-  if (current_template_parms)
-   return basetype;
+  if (same_type_p (basetype, current_class_type)

Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Jason Merrill

On 09/20/2011 06:17 PM, Ville Voutilainen wrote:

I find it hard to see what exactly changes there. Even if I
restore the indentation level, git still shows a diff. Perhaps
there were tabs in it...


Yes, the change is probably tabs vs. spaces.


else if (TYPE_P (name))
  {
basetype = TYPE_MAIN_VARIANT (name);
+  delegate_target = name;
name = TYPE_NAME (name);
  }
else if (TREE_CODE (name) == TYPE_DECL)
-basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
+{
+  basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
+  delegate_target = TREE_TYPE (name);
+}


We don't need a new variable, just use basetype.  TYPE_MAIN_VARIANT 
shouldn't affect the comparison to current_class_type.



+ error ("mem-initializer for %qD follows constructor delegation; "
+"previous target constructor for %T must be sole initializer",
+ error ("target constructor for %T must be sole initializer; "
+"constructor delegation follows mem-initializer for %qD",


I was thinking that my suggested wording would be the whole message, not 
just part of it.


Jason


Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Ville Voutilainen
At Tue, 20 Sep 2011 17:05:55 -0400,
Jason Merrill wrote:
> Try to avoid reformatting lines that you don't actually change.

I find it hard to see what exactly changes there. Even if I
restore the indentation level, git still shows a diff. Perhaps
there were tabs in it...

> > +  if (init == void_type_node)
> > +init = NULL_TREE;
> This is changing value-initialization to default-initialization, which 
> isn't the same thing.  What happens if you just remove these two lines?

Seems to work even without them. Here's a new patch:

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c707d66..7027b64 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7048,18 +7048,19 @@ build_special_member_call (tree instance, tree name, 
VEC(tree,gc) **args,
   vtt = DECL_CHAIN (CLASSTYPE_VTABLES (current_class_type));
   vtt = decay_conversion (vtt);
   vtt = build3 (COND_EXPR, TREE_TYPE (vtt),
-   build2 (EQ_EXPR, boolean_type_node,
-   current_in_charge_parm, integer_zero_node),
-   current_vtt_parm,
-   vtt);
-  gcc_assert (BINFO_SUBVTT_INDEX (binfo));
-  sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
-
+build2 (EQ_EXPR, boolean_type_node,
+current_in_charge_parm, integer_zero_node),
+current_vtt_parm,
+vtt);
+  if (BINFO_SUBVTT_INDEX (binfo))
+sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
+  else
+sub_vtt = vtt;
   if (args == NULL)
-   {
- allocated = make_tree_vector ();
- args = &allocated;
-   }
+{
+  allocated = make_tree_vector ();
+  args = &allocated;
+}
 
   VEC_safe_insert (tree, gc, *args, 0, sub_vtt);
 }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ae4cd07..31c600e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -394,7 +394,9 @@ typedef enum cpp0x_warn_str
   /* inline namespaces */
   CPP0X_INLINE_NAMESPACES,
   /* override controls, override/final */
-  CPP0X_OVERRIDE_CONTROLS
+  CPP0X_OVERRIDE_CONTROLS,
+  /* delegating constructors */
+  CPP0X_DELEGATING_CTORS
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 598ddf1..82f3175 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3236,6 +3236,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
 "override controls (override/final) "
 "only available with -std=c++0x or -std=gnu++0x");
 break;
+  case CPP0X_DELEGATING_CTORS:
+   pedwarn (input_location, 0,
+"delegating constructors "
+"only available with -std=c++0x or -std=gnu++0x");
+break;
   default:
gcc_unreachable();
   }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ff1884b..bef38e9 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -482,6 +482,31 @@ build_value_init_noctor (tree type, tsubst_flags_t 
complain)
   return build_zero_init (type, NULL_TREE, /*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;
+
+  finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
+ tf_warning_or_error));
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+{
+  tree expr = build_delete (type, decl, sfk_complete_destructor,
+LOOKUP_NORMAL
+|LOOKUP_NONVIRTUAL
+|LOOKUP_DESTRUCTOR,
+0, tf_warning_or_error);
+  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.  */
@@ -924,6 +949,16 @@ emit_mem_initializers (tree mem_inits)
   if (!COMPLETE_TYPE_P (current_class_type))
 return;
 
+  if (mem_inits
+  && TYPE_P (TREE_PURPOSE (mem_inits))
+  && same_type_p (TREE_PURPOSE (mem_inits), current_class_type))
+{
+  /* Delegating constructor. */
+  gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE);
+  perform_target_ctor (TREE_VALUE (mem_inits));
+  return;
+}
+
   if (DECL_DEFAULTED_FN (current_function_decl))
 flags |= LOOKUP_DEFAULTED;
 
@@ -1213,10 +1248,13 @@ expand_member_init (tree name)
 {
   tree basetype;
   tree field;
+  tree delegate_target;
 
   if (!current_class_ref)
 return NULL_TREE;
 
+  delegate_target = NULL_TREE;
+
   if (!name)
 {
   /* This is an obsolete unnamed base class initializer. 

Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Jason Merrill

On 09/20/2011 01:29 PM, Ville Voutilainen wrote:

2011-09-20 Ville Voutilainen 
   Implement delegating constructors. Based on an
   original patch by Pedro Lamarao.


Looks good, just a few minor comments:


-   build2 (EQ_EXPR, boolean_type_node,
-   current_in_charge_parm, integer_zero_node),
-   current_vtt_parm,
-   vtt);
+build2 (EQ_EXPR, boolean_type_node,
+current_in_charge_parm, integer_zero_node),
+current_vtt_parm,
+vtt);


Try to avoid reformatting lines that you don't actually change.


+  if (init == void_type_node)
+init = NULL_TREE;


This is changing value-initialization to default-initialization, which 
isn't the same thing.  What happens if you just remove these two lines?



+  finish_expr_stmt (build_aggr_init (decl, init, 0, tf_warning_or_error));


Let's pass LOOKUP_NORMAL instead of 0 here.


+LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,


And add LOOKUP_NORMAL| to LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR here.


+  if (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;
+}
+
+


Let's add a comment pointing out that this is constructor delegation. 
And remove the extra blank line.



+  if (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 (same_type_p (TREE_TYPE (name), current_class_type))
+   return TREE_TYPE (name);
+  basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
+}


Instead of comparing to current_class_type in two places, let's compare 
once in the if (basetype) block.



+  /* delegating constructor */


Generally comments in GCC should start with a capitalized word and end 
with a period even if they aren't full sentences.



+ error ("seeing initializer for member %<%D%>; "
+"previous target constructor for %T must be sole initializer",


Let's word this "mem-initializer for %qD follows constructor delegation"


+ error ("target constructor for %T must be sole initializer; "
+"saw previous initializer for member %<%D%>",


and "constructor delegation follows mem-initializer for %qD"

We don't need to name the type again, I think.

Jason


Re: [PATCH] C++11, implement delegating constructors

2011-09-20 Thread Ville Voutilainen
At Tue, 20 Sep 2011 20:29:27 +0300,
Ville Voutilainen wrote:
> --- a/gcc/testsuite/g++.dg/template/meminit1.C
> +++ b/gcc/testsuite/g++.dg/template/meminit1.C
> @@ -2,7 +2,7 @@
>  template 
>  struct S
>  {
> -  S() : S() {} // { dg-error "base" }
> +  S() : S() {}
>  };
>  
> -S s; // { dg-message "required" }
> +S s; // { dg-warning "delegating constructors" }

Duh. That dg-warning should be on line 5, not 8.
Incremental patch follows. Pardon the haste.

diff --git a/gcc/testsuite/g++.dg/template/meminit1.C 
b/gcc/testsuite/g++.dg/template/meminit1.C
index fc31828..efdbe80 100644
--- a/gcc/testsuite/g++.dg/template/meminit1.C
+++ b/gcc/testsuite/g++.dg/template/meminit1.C
@@ -2,7 +2,7 @@
 template 
 struct S
 {
-  S() : S() {}
+  S() : S() {} // { dg-warning "delegating constructors" }
 };
 
-S s; // { dg-warning "delegating constructors" }
+S s;