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
This commit is contained in:
parent
5a87ca71c8
commit
574cfaa47d
14 changed files with 240 additions and 111 deletions
|
@ -1,3 +1,26 @@
|
|||
2011-04-26 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2011-04-26 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
* class.c (cp_fold_obj_type_ref): Remove.
|
||||
|
|
|
@ -4144,7 +4144,11 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
|
|||
&& TREE_CODE (arg3) != THROW_EXPR)
|
||||
{
|
||||
if (!VOID_TYPE_P (arg3_type))
|
||||
arg3 = force_rvalue (arg3);
|
||||
{
|
||||
arg3 = force_rvalue (arg3, complain);
|
||||
if (arg3 == error_mark_node)
|
||||
return error_mark_node;
|
||||
}
|
||||
arg3_type = TREE_TYPE (arg3);
|
||||
result_type = arg3_type;
|
||||
}
|
||||
|
@ -4152,7 +4156,11 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
|
|||
&& TREE_CODE (arg3) == THROW_EXPR)
|
||||
{
|
||||
if (!VOID_TYPE_P (arg2_type))
|
||||
arg2 = force_rvalue (arg2);
|
||||
{
|
||||
arg2 = force_rvalue (arg2, complain);
|
||||
if (arg2 == error_mark_node)
|
||||
return error_mark_node;
|
||||
}
|
||||
arg2_type = TREE_TYPE (arg2);
|
||||
result_type = arg2_type;
|
||||
}
|
||||
|
@ -4359,11 +4367,11 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3,
|
|||
that isn't wrapped with a TARGET_EXPR plays havoc with exception
|
||||
regions. */
|
||||
|
||||
arg2 = force_rvalue (arg2);
|
||||
arg2 = force_rvalue (arg2, complain);
|
||||
if (!CLASS_TYPE_P (arg2_type))
|
||||
arg2_type = TREE_TYPE (arg2);
|
||||
|
||||
arg3 = force_rvalue (arg3);
|
||||
arg3 = force_rvalue (arg3, complain);
|
||||
if (!CLASS_TYPE_P (arg3_type))
|
||||
arg3_type = TREE_TYPE (arg3);
|
||||
|
||||
|
@ -5642,7 +5650,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||
expr = convert_bitfield_to_declared_type (expr);
|
||||
expr = fold_convert (type, expr);
|
||||
}
|
||||
expr = build_target_expr_with_type (expr, type);
|
||||
expr = build_target_expr_with_type (expr, type, complain);
|
||||
}
|
||||
|
||||
/* Take the address of the thing to which we will bind the
|
||||
|
@ -6341,7 +6349,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
if (TREE_CODE (arg) == TARGET_EXPR)
|
||||
return arg;
|
||||
else if (trivial)
|
||||
return force_target_expr (DECL_CONTEXT (fn), arg);
|
||||
return force_target_expr (DECL_CONTEXT (fn), arg, complain);
|
||||
}
|
||||
else if (TREE_CODE (arg) == TARGET_EXPR || trivial)
|
||||
{
|
||||
|
@ -8246,7 +8254,7 @@ set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
|
|||
if (TREE_STATIC (var))
|
||||
init = add_stmt_to_compound (init, register_dtor_fn (var));
|
||||
else
|
||||
*cleanup = cxx_maybe_build_cleanup (var);
|
||||
*cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error);
|
||||
|
||||
/* We must be careful to destroy the temporary only
|
||||
after its initialization has taken place. If the
|
||||
|
|
|
@ -4744,7 +4744,7 @@ extern void adjust_clone_args (tree);
|
|||
/* in cvt.c */
|
||||
extern tree convert_to_reference (tree, tree, int, int, tree);
|
||||
extern tree convert_from_reference (tree);
|
||||
extern tree force_rvalue (tree);
|
||||
extern tree force_rvalue (tree, tsubst_flags_t);
|
||||
extern tree ocp_convert (tree, tree, int, int);
|
||||
extern tree cp_convert (tree, tree);
|
||||
extern tree cp_convert_and_check (tree, tree);
|
||||
|
@ -4858,7 +4858,7 @@ extern tree next_initializable_field (tree);
|
|||
extern bool defer_mark_used_calls;
|
||||
extern GTY(()) VEC(tree, gc) *deferred_mark_used_calls;
|
||||
extern tree finish_case_label (location_t, tree, tree);
|
||||
extern tree cxx_maybe_build_cleanup (tree);
|
||||
extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t);
|
||||
|
||||
/* in decl2.c */
|
||||
extern bool check_java_method (tree);
|
||||
|
@ -4870,7 +4870,7 @@ extern bool vague_linkage_p (tree);
|
|||
extern void grokclassfn (tree, tree,
|
||||
enum overload_flags);
|
||||
extern tree grok_array_decl (tree, tree);
|
||||
extern tree delete_sanity (tree, tree, bool, int);
|
||||
extern tree delete_sanity (tree, tree, bool, int, tsubst_flags_t);
|
||||
extern tree check_classfn (tree, tree, tree);
|
||||
extern void check_member_template (tree);
|
||||
extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
|
||||
|
@ -4977,10 +4977,11 @@ extern tree build_vec_init (tree, tree, tree, bool, int,
|
|||
tsubst_flags_t);
|
||||
extern tree build_delete (tree, tree,
|
||||
special_function_kind,
|
||||
int, int);
|
||||
int, int, tsubst_flags_t);
|
||||
extern void push_base_cleanups (void);
|
||||
extern tree build_vec_delete (tree, tree,
|
||||
special_function_kind, int);
|
||||
special_function_kind, int,
|
||||
tsubst_flags_t);
|
||||
extern tree create_temporary_var (tree);
|
||||
extern void initialize_vtbl_ptrs (tree);
|
||||
extern tree build_java_class_ref (tree);
|
||||
|
@ -5379,8 +5380,8 @@ extern void maybe_add_lambda_conv_op (tree);
|
|||
|
||||
/* in tree.c */
|
||||
void cp_free_lang_data (tree t);
|
||||
extern tree force_target_expr (tree, tree);
|
||||
extern tree build_target_expr_with_type (tree, tree);
|
||||
extern tree force_target_expr (tree, tree, tsubst_flags_t);
|
||||
extern tree build_target_expr_with_type (tree, tree, tsubst_flags_t);
|
||||
extern void lang_check_failed (const char *, int,
|
||||
const char *) ATTRIBUTE_NORETURN;
|
||||
extern tree stabilize_expr (tree, tree *);
|
||||
|
@ -5413,6 +5414,7 @@ extern tree build_min_non_dep_call_vec (tree, tree, VEC(tree,gc) *);
|
|||
extern tree build_cplus_new (tree, tree, tsubst_flags_t);
|
||||
extern tree build_aggr_init_expr (tree, tree, tsubst_flags_t);
|
||||
extern tree get_target_expr (tree);
|
||||
extern tree get_target_expr_sfinae (tree, tsubst_flags_t);
|
||||
extern tree build_cplus_array_type (tree, tree);
|
||||
extern tree build_array_of_n_type (tree, int);
|
||||
extern tree build_array_copy (tree);
|
||||
|
|
14
gcc/cp/cvt.c
14
gcc/cp/cvt.c
|
@ -531,11 +531,17 @@ convert_from_reference (tree val)
|
|||
argument of class type into a temporary. */
|
||||
|
||||
tree
|
||||
force_rvalue (tree expr)
|
||||
force_rvalue (tree expr, tsubst_flags_t complain)
|
||||
{
|
||||
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
|
||||
expr = ocp_convert (TREE_TYPE (expr), expr,
|
||||
CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
|
||||
tree type = TREE_TYPE (expr);
|
||||
if (MAYBE_CLASS_TYPE_P (type) && TREE_CODE (expr) != TARGET_EXPR)
|
||||
{
|
||||
VEC(tree,gc) *args = make_tree_vector_single (expr);
|
||||
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
|
||||
&args, type, LOOKUP_NORMAL, complain);
|
||||
release_tree_vector (args);
|
||||
expr = build_cplus_new (type, expr, complain);
|
||||
}
|
||||
else
|
||||
expr = decay_conversion (expr);
|
||||
|
||||
|
|
|
@ -5640,7 +5640,7 @@ initialize_local_var (tree decl, tree init)
|
|||
DECL_READ_P (decl) = 1;
|
||||
|
||||
/* Generate a cleanup, if necessary. */
|
||||
cleanup = cxx_maybe_build_cleanup (decl);
|
||||
cleanup = cxx_maybe_build_cleanup (decl, tf_warning_or_error);
|
||||
|
||||
/* Perform the initialization. */
|
||||
if (init)
|
||||
|
@ -13309,7 +13309,7 @@ complete_vars (tree type)
|
|||
cleanup need be done. */
|
||||
|
||||
tree
|
||||
cxx_maybe_build_cleanup (tree decl)
|
||||
cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
|
||||
{
|
||||
tree type;
|
||||
tree attr;
|
||||
|
@ -13344,8 +13344,9 @@ cxx_maybe_build_cleanup (tree decl)
|
|||
fn = lookup_name (id);
|
||||
arg = build_address (decl);
|
||||
mark_used (decl);
|
||||
cleanup = cp_build_function_call_nary (fn, tf_warning_or_error,
|
||||
arg, NULL_TREE);
|
||||
cleanup = cp_build_function_call_nary (fn, complain, arg, NULL_TREE);
|
||||
if (cleanup == error_mark_node)
|
||||
return error_mark_node;
|
||||
}
|
||||
/* Handle ordinary C++ destructors. */
|
||||
type = TREE_TYPE (decl);
|
||||
|
@ -13367,9 +13368,11 @@ cxx_maybe_build_cleanup (tree decl)
|
|||
flags |= LOOKUP_NONVIRTUAL;
|
||||
|
||||
call = build_delete (TREE_TYPE (addr), addr,
|
||||
sfk_complete_destructor, flags, 0);
|
||||
if (cleanup)
|
||||
cleanup = build_compound_expr (input_location, cleanup, call);
|
||||
sfk_complete_destructor, flags, 0, complain);
|
||||
if (call == error_mark_node)
|
||||
cleanup = error_mark_node;
|
||||
else if (cleanup)
|
||||
cleanup = cp_build_compound_expr (cleanup, call, complain);
|
||||
else
|
||||
cleanup = call;
|
||||
}
|
||||
|
|
|
@ -419,7 +419,8 @@ grok_array_decl (tree array_expr, tree index_exp)
|
|||
Implements ARM $5.3.4. This is called from the parser. */
|
||||
|
||||
tree
|
||||
delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
|
||||
delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete,
|
||||
tsubst_flags_t complain)
|
||||
{
|
||||
tree t, type;
|
||||
|
||||
|
@ -475,10 +476,11 @@ delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
|
|||
if (doing_vec)
|
||||
return build_vec_delete (t, /*maxindex=*/NULL_TREE,
|
||||
sfk_deleting_destructor,
|
||||
use_global_delete);
|
||||
use_global_delete, complain);
|
||||
else
|
||||
return build_delete (type, t, sfk_deleting_destructor,
|
||||
LOOKUP_NORMAL, use_global_delete);
|
||||
LOOKUP_NORMAL, use_global_delete,
|
||||
complain);
|
||||
}
|
||||
|
||||
/* Report an error if the indicated template declaration is not the
|
||||
|
@ -2594,7 +2596,8 @@ build_cleanup (tree decl)
|
|||
temp = build_address (decl);
|
||||
temp = build_delete (TREE_TYPE (temp), temp,
|
||||
sfk_complete_destructor,
|
||||
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
|
||||
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
|
||||
tf_warning_or_error);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
|
154
gcc/cp/init.c
154
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;
|
||||
|
|
|
@ -6295,7 +6295,8 @@ cp_parser_delete_expression (cp_parser* parser)
|
|||
if (cp_parser_non_integral_constant_expression (parser, NIC_DEL))
|
||||
return error_mark_node;
|
||||
|
||||
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
|
||||
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p,
|
||||
tf_warning_or_error);
|
||||
}
|
||||
|
||||
/* Returns true if TOKEN may start a cast-expression and false
|
||||
|
|
|
@ -12102,7 +12102,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
|
|||
init = build_value_init (TREE_TYPE (decl),
|
||||
complain);
|
||||
if (TREE_CODE (init) == AGGR_INIT_EXPR)
|
||||
init = get_target_expr (init);
|
||||
init = get_target_expr_sfinae (init, complain);
|
||||
}
|
||||
else
|
||||
init = t;
|
||||
|
@ -12846,7 +12846,8 @@ tsubst_copy_and_build (tree t,
|
|||
(RECUR (TREE_OPERAND (t, 0)),
|
||||
RECUR (TREE_OPERAND (t, 1)),
|
||||
DELETE_EXPR_USE_VEC (t),
|
||||
DELETE_EXPR_USE_GLOBAL (t));
|
||||
DELETE_EXPR_USE_GLOBAL (t),
|
||||
complain);
|
||||
|
||||
case COMPOUND_EXPR:
|
||||
return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
|
||||
|
|
|
@ -1835,7 +1835,7 @@ finish_stmt_expr_expr (tree expr, tree stmt_expr)
|
|||
/* It actually has a value we need to deal with. First, force it
|
||||
to be an rvalue so that we won't need to build up a copy
|
||||
constructor call later when we try to assign it to something. */
|
||||
expr = force_rvalue (expr);
|
||||
expr = force_rvalue (expr, tf_warning_or_error);
|
||||
if (error_operand_p (expr))
|
||||
return error_mark_node;
|
||||
|
||||
|
@ -1892,7 +1892,7 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
|
|||
temporary object created by the final expression is destroyed at
|
||||
the end of the full-expression containing the
|
||||
statement-expression. */
|
||||
result = force_target_expr (type, result);
|
||||
result = force_target_expr (type, result, tf_warning_or_error);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2407,7 +2407,7 @@ finish_compound_literal (tree type, tree compound_literal,
|
|||
return decl;
|
||||
}
|
||||
else
|
||||
return get_target_expr (compound_literal);
|
||||
return get_target_expr_sfinae (compound_literal, complain);
|
||||
}
|
||||
|
||||
/* Return the declaration for the function-name variable indicated by
|
||||
|
@ -7995,7 +7995,7 @@ build_lambda_object (tree lambda_expr)
|
|||
There's normally no way to express direct-initialization
|
||||
from an element of a CONSTRUCTOR, so we build up a special
|
||||
TARGET_EXPR to bypass the usual copy-initialization. */
|
||||
val = force_rvalue (val);
|
||||
val = force_rvalue (val, tf_warning_or_error);
|
||||
if (TREE_CODE (val) == TARGET_EXPR)
|
||||
TARGET_EXPR_DIRECT_INIT_P (val) = true;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ static tree bot_replace (tree *, int *, void *);
|
|||
static int list_hash_eq (const void *, const void *);
|
||||
static hashval_t list_hash_pieces (tree, tree, tree);
|
||||
static hashval_t list_hash (const void *);
|
||||
static tree build_target_expr (tree, tree);
|
||||
static tree build_target_expr (tree, tree, tsubst_flags_t);
|
||||
static tree count_trees_r (tree *, int *, void *);
|
||||
static tree verify_stmt_tree_r (tree *, int *, void *);
|
||||
static tree build_local_temp (tree);
|
||||
|
@ -281,7 +281,7 @@ builtin_valid_in_constant_expr_p (const_tree decl)
|
|||
/* Build a TARGET_EXPR, initializing the DECL with the VALUE. */
|
||||
|
||||
static tree
|
||||
build_target_expr (tree decl, tree value)
|
||||
build_target_expr (tree decl, tree value, tsubst_flags_t complain)
|
||||
{
|
||||
tree t;
|
||||
|
||||
|
@ -292,8 +292,10 @@ build_target_expr (tree decl, tree value)
|
|||
TREE_TYPE (value)));
|
||||
#endif
|
||||
|
||||
t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
|
||||
cxx_maybe_build_cleanup (decl), NULL_TREE);
|
||||
t = cxx_maybe_build_cleanup (decl, complain);
|
||||
if (t == error_mark_node)
|
||||
return error_mark_node;
|
||||
t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value, t, NULL_TREE);
|
||||
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
|
||||
ignore the TARGET_EXPR. If there really turn out to be no
|
||||
side-effects, then the optimizer should be able to get rid of
|
||||
|
@ -453,7 +455,7 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain)
|
|||
else
|
||||
return rval;
|
||||
|
||||
rval = build_target_expr (slot, rval);
|
||||
rval = build_target_expr (slot, rval, complain);
|
||||
TARGET_EXPR_IMPLICIT_P (rval) = 1;
|
||||
|
||||
return rval;
|
||||
|
@ -526,7 +528,7 @@ build_vec_init_expr (tree type, tree init)
|
|||
VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
|
||||
VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
|
||||
|
||||
init = build_target_expr (slot, init);
|
||||
init = build_target_expr (slot, init, tf_warning_or_error);
|
||||
TARGET_EXPR_IMPLICIT_P (init) = 1;
|
||||
|
||||
return init;
|
||||
|
@ -559,7 +561,7 @@ build_array_copy (tree init)
|
|||
indicated TYPE. */
|
||||
|
||||
tree
|
||||
build_target_expr_with_type (tree init, tree type)
|
||||
build_target_expr_with_type (tree init, tree type, tsubst_flags_t complain)
|
||||
{
|
||||
gcc_assert (!VOID_TYPE_P (type));
|
||||
|
||||
|
@ -577,9 +579,9 @@ build_target_expr_with_type (tree init, tree type)
|
|||
another one here. A CONSTRUCTOR is aggregate initialization, which
|
||||
is handled separately. A VA_ARG_EXPR is magic creation of an
|
||||
aggregate; there's no additional work to be done. */
|
||||
return force_rvalue (init);
|
||||
return force_rvalue (init, complain);
|
||||
|
||||
return force_target_expr (type, init);
|
||||
return force_target_expr (type, init, complain);
|
||||
}
|
||||
|
||||
/* Like the above function, but without the checking. This function should
|
||||
|
@ -588,27 +590,33 @@ build_target_expr_with_type (tree init, tree type)
|
|||
infinite recursion. */
|
||||
|
||||
tree
|
||||
force_target_expr (tree type, tree init)
|
||||
force_target_expr (tree type, tree init, tsubst_flags_t complain)
|
||||
{
|
||||
tree slot;
|
||||
|
||||
gcc_assert (!VOID_TYPE_P (type));
|
||||
|
||||
slot = build_local_temp (type);
|
||||
return build_target_expr (slot, init);
|
||||
return build_target_expr (slot, init, complain);
|
||||
}
|
||||
|
||||
/* Like build_target_expr_with_type, but use the type of INIT. */
|
||||
|
||||
tree
|
||||
get_target_expr (tree init)
|
||||
get_target_expr_sfinae (tree init, tsubst_flags_t complain)
|
||||
{
|
||||
if (TREE_CODE (init) == AGGR_INIT_EXPR)
|
||||
return build_target_expr (AGGR_INIT_EXPR_SLOT (init), init);
|
||||
return build_target_expr (AGGR_INIT_EXPR_SLOT (init), init, complain);
|
||||
else if (TREE_CODE (init) == VEC_INIT_EXPR)
|
||||
return build_target_expr (VEC_INIT_EXPR_SLOT (init), init);
|
||||
return build_target_expr (VEC_INIT_EXPR_SLOT (init), init, complain);
|
||||
else
|
||||
return build_target_expr_with_type (init, TREE_TYPE (init));
|
||||
return build_target_expr_with_type (init, TREE_TYPE (init), complain);
|
||||
}
|
||||
|
||||
tree
|
||||
get_target_expr (tree init)
|
||||
{
|
||||
return get_target_expr_sfinae (init, tf_warning_or_error);
|
||||
}
|
||||
|
||||
/* If EXPR is a bitfield reference, convert it to the declared type of
|
||||
|
@ -1810,7 +1818,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data)
|
|||
u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
|
||||
tf_warning_or_error);
|
||||
else
|
||||
u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t));
|
||||
u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t),
|
||||
tf_warning_or_error);
|
||||
|
||||
/* Map the old variable to the new one. */
|
||||
splay_tree_insert (target_remap,
|
||||
|
|
|
@ -1610,7 +1610,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
|
|||
&& !TYPE_HAS_USER_CONSTRUCTOR (type))
|
||||
{
|
||||
exp = build_value_init (type, complain);
|
||||
exp = get_target_expr (exp);
|
||||
exp = get_target_expr_sfinae (exp, complain);
|
||||
/* FIXME this is wrong */
|
||||
if (literal_type_p (type))
|
||||
TREE_CONSTANT (exp) = true;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2011-04-25 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/sfinae17.C: New.
|
||||
|
||||
2011-03-23 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
|
||||
PR target/48258
|
||||
|
|
31
gcc/testsuite/g++.dg/cpp0x/sfinae17.C
Normal file
31
gcc/testsuite/g++.dg/cpp0x/sfinae17.C
Normal file
|
@ -0,0 +1,31 @@
|
|||
// PR c++/48530
|
||||
// { dg-options -std=c++0x }
|
||||
|
||||
template<class T,
|
||||
class = decltype(T{})
|
||||
>
|
||||
char f(int);
|
||||
|
||||
template<class>
|
||||
char (&f(...))[2];
|
||||
|
||||
struct DelDtor {
|
||||
~DelDtor() = delete;
|
||||
};
|
||||
|
||||
static_assert(sizeof(f<DelDtor[2]>(0)) != 1, "Error");
|
||||
|
||||
struct A
|
||||
{
|
||||
static DelDtor *p;
|
||||
};
|
||||
|
||||
template<class T,
|
||||
class = decltype(delete T::p, (T*)0)
|
||||
>
|
||||
char g(int);
|
||||
|
||||
template<class>
|
||||
char (&g(...))[2];
|
||||
|
||||
static_assert(sizeof(g<DelDtor>(0)) != 1, "Error");
|
Loading…
Add table
Reference in a new issue