aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-04-26 15:28:25 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-04-26 15:28:25 -0400
commit574cfaa47dbcc2e8d9ea68b83d8dc3122832ff9b (patch)
treee83e77854b5490319145c8e64a21bec89b47616f /gcc/cp/init.c
parent5a87ca71c875b5bc34b9b8bc0ef405cec9b51b51 (diff)
downloadgcc-574cfaa47dbcc2e8d9ea68b83d8dc3122832ff9b.zip
gcc-574cfaa47dbcc2e8d9ea68b83d8dc3122832ff9b.tar.gz
gcc-574cfaa47dbcc2e8d9ea68b83d8dc3122832ff9b.tar.bz2
re PR c++/48530 ([C++0x][SFINAE] Hard errors with deleted d'tors)
PR c++/48530 * decl.c (cxx_maybe_build_cleanup): Add complain parm. * tree.c (force_target_expr): Add complain parm. (build_target_expr_with_type): Likewise. (get_target_expr_sfinae): Split out. (build_vec_init_expr, bot_manip): Adjust. * init.c (build_vec_delete, build_vec_delete_1): Add complain parm. (build_delete, build_dtor_call): Likewise. (perform_direct_initialization_if_possible): Adjust. (build_vec_init): Handle error return. * cvt.c (force_rvalue): Add complain parm. Call build_special_member_call directly. * decl2.c (delete_sanity): Add complain parm. (build_cleanup): Adjust. * pt.c (tsubst_copy_and_build, tsubst_expr): Adjust. * semantics.c (finish_stmt_expr_expr): Adjust. (finish_compound_literal): Adjust. * parser.c (cp_parser_delete_expression): Adjust. * typeck2.c (build_functional_cast): Adjust. * cp-tree.h: Adjust. From-SVN: r172985
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c154
1 files changed, 96 insertions, 58 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 04d2bb2..25beba8 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -37,7 +37,6 @@ static tree finish_init_stmts (bool, tree, tree);
static void construct_virtual_base (tree, tree);
static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t);
static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t);
-static tree build_vec_delete_1 (tree, tree, tree, special_function_kind, int);
static void perform_member_init (tree, tree);
static tree build_builtin_delete_call (tree);
static int member_init_ok_or_else (tree, tree, tree);
@@ -46,7 +45,6 @@ static tree sort_mem_initializers (tree, tree);
static tree initializing_context (tree);
static void expand_cleanup_for_base (tree, tree);
static tree dfs_initialize_vtbl_ptrs (tree, void *);
-static tree build_dtor_call (tree, special_function_kind, int);
static tree build_field_list (tree, tree, int *);
static tree build_vtbl_address (tree);
static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool);
@@ -620,7 +618,8 @@ perform_member_init (tree member, tree init)
/*preserve_reference=*/false,
tf_warning_or_error);
expr = build_delete (type, expr, sfk_complete_destructor,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
+ tf_warning_or_error);
if (expr != error_mark_node)
finish_eh_cleanup (expr);
@@ -2720,7 +2719,8 @@ build_java_class_ref (tree type)
static tree
build_vec_delete_1 (tree base, tree maxindex, tree type,
- special_function_kind auto_delete_vec, int use_global_delete)
+ special_function_kind auto_delete_vec,
+ int use_global_delete, tsubst_flags_t complain)
{
tree virtual_size;
tree ptype = build_pointer_type (type = complete_type (type));
@@ -2749,6 +2749,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
/* We should only have 1-D arrays here. */
gcc_assert (TREE_CODE (type) != ARRAY_TYPE);
+ if (base == error_mark_node || maxindex == error_mark_node)
+ return error_mark_node;
+
if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
goto no_destructor;
@@ -2762,7 +2765,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
POINTER_PLUS_EXPR, ptype,
fold_convert (ptype, base),
virtual_size),
- tf_warning_or_error);
+ complain);
+ if (tbase_init == error_mark_node)
+ return error_mark_node;
controller = build3 (BIND_EXPR, void_type_node, tbase,
NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (controller) = 1;
@@ -2771,15 +2776,17 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
build2 (EQ_EXPR, boolean_type_node, tbase,
fold_convert (ptype, base)));
tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
- body = build_compound_expr
- (input_location,
- body, cp_build_modify_expr (tbase, NOP_EXPR,
- build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp),
- tf_warning_or_error));
- body = build_compound_expr
- (input_location,
- body, build_delete (ptype, tbase, sfk_complete_destructor,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
+ tmp = build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp);
+ tmp = cp_build_modify_expr (tbase, NOP_EXPR, tmp, complain);
+ if (tmp == error_mark_node)
+ return error_mark_node;
+ body = build_compound_expr (input_location, body, tmp);
+ tmp = build_delete (ptype, tbase, sfk_complete_destructor,
+ LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
+ complain);
+ if (tmp == error_mark_node)
+ return error_mark_node;
+ body = build_compound_expr (input_location, body, tmp);
loop = build1 (LOOP_EXPR, void_type_node, body);
loop = build_compound_expr (input_location, tbase_init, loop);
@@ -2803,14 +2810,15 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
tree cookie_size;
cookie_size = targetm.cxx.get_cookie_size (type);
- base_tbd
- = cp_convert (ptype,
- cp_build_binary_op (input_location,
- MINUS_EXPR,
- cp_convert (string_type_node,
- base),
- cookie_size,
- tf_warning_or_error));
+ base_tbd = cp_build_binary_op (input_location,
+ MINUS_EXPR,
+ cp_convert (string_type_node,
+ base),
+ cookie_size,
+ complain);
+ if (base_tbd == error_mark_node)
+ return error_mark_node;
+ base_tbd = cp_convert (ptype, base_tbd);
/* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
}
@@ -2853,7 +2861,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
/* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR. */
body = build2 (COMPOUND_EXPR, void_type_node, base, body);
- return convert_to_void (body, ICV_CAST, tf_warning_or_error);
+ return convert_to_void (body, ICV_CAST, complain);
}
/* Create an unnamed variable of the indicated TYPE. */
@@ -2942,6 +2950,7 @@ build_vec_init (tree base, tree maxindex, tree init,
tree const_init = NULL_TREE;
tree obase = base;
bool xvalue = false;
+ bool errors = false;
if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
maxindex = array_type_nelts (atype);
@@ -3087,7 +3096,8 @@ build_vec_init (tree base, tree maxindex, tree init,
else
one_init = cp_build_modify_expr (baseref, NOP_EXPR,
elt, complain);
-
+ if (one_init == error_mark_node)
+ errors = true;
if (try_const)
{
tree e = one_init;
@@ -3120,10 +3130,18 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_expr_stmt (one_init);
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
- finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0,
- complain));
- finish_expr_stmt (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
- complain));
+ one_init = cp_build_unary_op (PREINCREMENT_EXPR, base, 0, complain);
+ if (one_init == error_mark_node)
+ errors = true;
+ else
+ finish_expr_stmt (one_init);
+
+ one_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
+ complain);
+ if (one_init == error_mark_node)
+ errors = true;
+ else
+ finish_expr_stmt (one_init);
}
if (try_const)
@@ -3149,7 +3167,7 @@ build_vec_init (tree base, tree maxindex, tree init,
{
if (complain & tf_error)
error ("initializer ends prematurely");
- return error_mark_node;
+ errors = true;
}
}
@@ -3176,9 +3194,11 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
build_int_cst (TREE_TYPE (iterator), -1)),
for_stmt);
- finish_for_expr (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
- complain),
- for_stmt);
+ elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
+ complain);
+ if (elt_init == error_mark_node)
+ errors = true;
+ finish_for_expr (elt_init, for_stmt);
to = build1 (INDIRECT_REF, type, base);
@@ -3219,9 +3239,7 @@ build_vec_init (tree base, tree maxindex, tree init,
else if (explicit_value_init_p)
{
elt_init = build_value_init (type, complain);
- if (elt_init == error_mark_node)
- return error_mark_node;
- else
+ if (elt_init != error_mark_node)
elt_init = build2 (INIT_EXPR, type, to, elt_init);
}
else
@@ -3230,6 +3248,9 @@ build_vec_init (tree base, tree maxindex, tree init,
elt_init = build_aggr_init (to, init, 0, complain);
}
+ if (elt_init == error_mark_node)
+ errors = true;
+
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init);
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
@@ -3263,7 +3284,9 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_cleanup_try_block (try_block);
e = build_vec_delete_1 (rval, m,
inner_elt_type, sfk_base_destructor,
- /*use_global_delete=*/0);
+ /*use_global_delete=*/0, complain);
+ if (e == error_mark_node)
+ errors = true;
finish_cleanup (e, try_block);
}
@@ -3286,6 +3309,8 @@ build_vec_init (tree base, tree maxindex, tree init,
if (const_init)
return build2 (INIT_EXPR, atype, obase, const_init);
+ if (errors)
+ return error_mark_node;
return stmt_expr;
}
@@ -3293,7 +3318,8 @@ build_vec_init (tree base, tree maxindex, tree init,
build_delete. */
static tree
-build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
+build_dtor_call (tree exp, special_function_kind dtor_kind, int flags,
+ tsubst_flags_t complain)
{
tree name;
tree fn;
@@ -3320,7 +3346,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
/*conversion_path=*/NULL_TREE,
flags,
/*fn_p=*/NULL,
- tf_warning_or_error);
+ complain);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -3334,7 +3360,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
tree
build_delete (tree type, tree addr, special_function_kind auto_delete,
- int flags, int use_global_delete)
+ int flags, int use_global_delete, tsubst_flags_t complain)
{
tree expr;
@@ -3369,8 +3395,9 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
complete_type (type);
if (!COMPLETE_TYPE_P (type))
{
- if (warning (0, "possible problem detected in invocation of "
- "delete operator:"))
+ if ((complain & tf_warning)
+ && warning (0, "possible problem detected in invocation of "
+ "delete operator:"))
{
cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
inform (input_location, "neither the destructor nor the class-specific "
@@ -3395,18 +3422,21 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
if (TYPE_DOMAIN (type) == NULL_TREE)
{
- error ("unknown array size in delete");
+ if (complain & tf_error)
+ error ("unknown array size in delete");
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
- auto_delete, use_global_delete);
+ auto_delete, use_global_delete, complain);
}
else
{
/* Don't check PROTECT here; leave that decision to the
destructor. If the destructor is accessible, call it,
else report error. */
- addr = cp_build_addr_expr (addr, tf_warning_or_error);
+ addr = cp_build_addr_expr (addr, complain);
+ if (addr == error_mark_node)
+ return error_mark_node;
if (TREE_SIDE_EFFECTS (addr))
addr = save_expr (addr);
@@ -3478,9 +3508,10 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
/*alloc_fn=*/NULL_TREE);
}
- expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
- tf_warning_or_error),
- auto_delete, flags);
+ expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain),
+ auto_delete, flags, complain);
+ if (expr == error_mark_node)
+ return error_mark_node;
if (do_delete)
expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete);
@@ -3492,10 +3523,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
/* Explicit destructor call; don't check for null pointer. */
ifexp = integer_one_node;
else
- /* Handle deleting a null pointer. */
- ifexp = fold (cp_build_binary_op (input_location,
- NE_EXPR, addr, integer_zero_node,
- tf_warning_or_error));
+ {
+ /* Handle deleting a null pointer. */
+ ifexp = fold (cp_build_binary_op (input_location,
+ NE_EXPR, addr, integer_zero_node,
+ complain));
+ if (ifexp == error_mark_node)
+ return error_mark_node;
+ }
if (ifexp != integer_one_node)
expr = build3 (COND_EXPR, void_type_node,
@@ -3588,7 +3623,7 @@ push_base_cleanups (void)
expr = build_delete (this_type, this_member,
sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
- 0);
+ 0, tf_warning_or_error);
finish_decl_cleanup (NULL_TREE, expr);
}
}
@@ -3612,7 +3647,8 @@ push_base_cleanups (void)
tree
build_vec_delete (tree base, tree maxindex,
- special_function_kind auto_delete_vec, int use_global_delete)
+ special_function_kind auto_delete_vec,
+ int use_global_delete, tsubst_flags_t complain)
{
tree type;
tree rval;
@@ -3638,7 +3674,7 @@ build_vec_delete (tree base, tree maxindex,
size_ptr_type,
fold_convert (size_ptr_type, base),
cookie_addr);
- maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
+ maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, complain);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
@@ -3646,7 +3682,9 @@ build_vec_delete (tree base, tree maxindex,
bad name. */
maxindex = array_type_nelts_total (type);
type = strip_array_types (type);
- base = cp_build_addr_expr (base, tf_warning_or_error);
+ base = cp_build_addr_expr (base, complain);
+ if (base == error_mark_node)
+ return error_mark_node;
if (TREE_SIDE_EFFECTS (base))
{
base_init = get_target_expr (base);
@@ -3655,14 +3693,14 @@ build_vec_delete (tree base, tree maxindex,
}
else
{
- if (base != error_mark_node)
+ if (base != error_mark_node && !(complain & tf_error))
error ("type to vector delete is neither pointer or array type");
return error_mark_node;
}
rval = build_vec_delete_1 (base, maxindex, type, auto_delete_vec,
- use_global_delete);
- if (base_init)
+ use_global_delete, complain);
+ if (base_init && rval != error_mark_node)
rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), base_init, rval);
return rval;