diff options
author | Jason Merrill <jason@redhat.com> | 2011-04-26 15:28:25 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-04-26 15:28:25 -0400 |
commit | 574cfaa47dbcc2e8d9ea68b83d8dc3122832ff9b (patch) | |
tree | e83e77854b5490319145c8e64a21bec89b47616f /gcc/cp/init.c | |
parent | 5a87ca71c875b5bc34b9b8bc0ef405cec9b51b51 (diff) | |
download | gcc-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.c | 154 |
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; |