diff options
author | Ville Voutilainen <ville.voutilainen@gmail.com> | 2011-12-05 17:49:25 +0200 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-12-05 10:49:25 -0500 |
commit | 238e471cadfb1c2995e6bc4c995328eacc39d0da (patch) | |
tree | 34698b82ecd5ca13de0629ef51d816a609fbb6ea /gcc/cp | |
parent | 12c574caf6f0766266813fef7be8a2367a9d0700 (diff) | |
download | gcc-238e471cadfb1c2995e6bc4c995328eacc39d0da.zip gcc-238e471cadfb1c2995e6bc4c995328eacc39d0da.tar.gz gcc-238e471cadfb1c2995e6bc4c995328eacc39d0da.tar.bz2 |
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.
Co-Authored-By: Pedro LamarĂ£o <pedro.lamarao@gmail.com>
From-SVN: r182012
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/call.c | 6 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/error.c | 5 | ||||
-rw-r--r-- | gcc/cp/init.c | 73 | ||||
-rw-r--r-- | gcc/cp/parser.c | 22 |
6 files changed, 111 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fcd44f0..be5ebea 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2011-12-05 Ville Voutilainen <ville.voutilainen@gmail.com> + Pedro LamarĂ£o <pedro.lamarao@gmail.com> + + 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. + 2011-12-05 Paolo Carlini <paolo.carlini@oracle.com> PR c++/51404 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, 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_call (exp, base_ctor_identifier, + &parms, binfo, flags, + complain); + rval = build3 (COND_EXPR, TREE_TYPE (complete), + build2 (EQ_EXPR, boolean_type_node, + current_in_charge_parm, integer_zero_node), + base, + complete); + } + else + { + 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 (parms != NULL) release_tree_vector (parms); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 69f1eab..9e7a398 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11321,6 +11321,7 @@ static void cp_parser_mem_initializer_list (cp_parser* parser) { tree mem_initializer_list = NULL_TREE; + tree target_ctor = error_mark_node; cp_token *token = cp_lexer_peek_token (parser->lexer); /* Let the semantic analysis code know that we are starting the @@ -11358,6 +11359,27 @@ cp_parser_mem_initializer_list (cp_parser* parser) 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 ("mem-initializer for %qD follows constructor delegation", + TREE_PURPOSE (mem_initializer)); + mem_initializer = error_mark_node; + } + /* Look for a target constructor. */ + if (mem_initializer != error_mark_node + && TYPE_P (TREE_PURPOSE (mem_initializer)) + && same_type_p (TREE_PURPOSE (mem_initializer), current_class_type)) + { + maybe_warn_cpp0x (CPP0X_DELEGATING_CTORS); + if (mem_initializer_list) + { + error ("constructor delegation follows mem-initializer for %qD", + 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) { |