Re: [PATCH] C++11, implement delegating constructors
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
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
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
Looks good, thanks. Jason
Re: [PATCH] C++11, implement delegating constructors
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
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
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
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
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
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;