aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorVille Voutilainen <ville.voutilainen@gmail.com>2011-12-05 17:49:25 +0200
committerJason Merrill <jason@gcc.gnu.org>2011-12-05 10:49:25 -0500
commit238e471cadfb1c2995e6bc4c995328eacc39d0da (patch)
tree34698b82ecd5ca13de0629ef51d816a609fbb6ea /gcc/cp
parent12c574caf6f0766266813fef7be8a2367a9d0700 (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--gcc/cp/call.c6
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/error.c5
-rw-r--r--gcc/cp/init.c73
-rw-r--r--gcc/cp/parser.c22
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)
{