Commit 519ebd1e by Jason Merrill Committed by Jason Merrill

call.c (joust): Fix confusing conversion warning.

	* call.c (joust): Fix confusing conversion warning.
	* call.c (build_op_delete_call): Add placement parm.  Check
	LOOKUP_SPECULATIVELY.
	* cp-tree.h, decl2.c, init.c: Adjust.
	* decl.c (finish_function): Use it.
	* pt.c (tsubst): Diagnose creating void fields or variables.

From-SVN: r20668
parent 5b8e7fa3
1998-06-23 Jason Merrill <jason@yorick.cygnus.com>
* call.c (joust): Fix confusing conversion warning.
* call.c (build_op_delete_call): Add placement parm. Check
LOOKUP_SPECULATIVELY.
* cp-tree.h, decl2.c, init.c: Adjust.
* decl.c (finish_function): Use it.
* pt.c (tsubst): Diagnose creating void fields or variables.
Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* call.c (build_scoped_method_call): Remove unused variable `tmp'. * call.c (build_scoped_method_call): Remove unused variable `tmp'.
......
...@@ -2913,16 +2913,16 @@ build_op_new_call (code, type, args, flags) ...@@ -2913,16 +2913,16 @@ build_op_new_call (code, type, args, flags)
ADDR is the pointer to be deleted. For placement delete, it is also ADDR is the pointer to be deleted. For placement delete, it is also
used to determine what the corresponding new looked like. used to determine what the corresponding new looked like.
SIZE is the size of the memory block to be deleted. SIZE is the size of the memory block to be deleted.
FLAGS are the usual overloading flags. */ FLAGS are the usual overloading flags.
PLACEMENT is the corresponding placement new call, or 0. */
tree tree
build_op_delete_call (code, addr, size, flags) build_op_delete_call (code, addr, size, flags, placement)
enum tree_code code; enum tree_code code;
tree addr, size; tree addr, size, placement;
int flags; int flags;
{ {
tree fn, fns, fnname, fntype, argtypes, args, type; tree fn, fns, fnname, fntype, argtypes, args, type;
int placement;
if (addr == error_mark_node) if (addr == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -2946,42 +2946,20 @@ build_op_delete_call (code, addr, size, flags) ...@@ -2946,42 +2946,20 @@ build_op_delete_call (code, addr, size, flags)
else else
fns = NULL_TREE; fns = NULL_TREE;
if (fns) if (fns == NULL_TREE)
{
#if 0
/* It is unnecessary to wrap another TREE_LIST around it. (MvL) */
/* Build this up like build_offset_ref does. */
fns = build_tree_list (error_mark_node, fns);
TREE_TYPE (fns) = build_offset_type (type, unknown_type_node);
#endif
}
else
fns = lookup_name_nonclass (fnname); fns = lookup_name_nonclass (fnname);
/* We can recognize a placement delete because of LOOKUP_SPECULATIVELY;
if we are doing placement delete we do nothing if we don't find a
matching op delete. */
placement = !!(flags & LOOKUP_SPECULATIVELY);
if (placement) if (placement)
{ {
/* If placement, we are coming from build_new, and we know that addr /* placement is a CALL_EXPR around an ADDR_EXPR around a function. */
is the allocation expression, so extract the info we need from it.
Obviously, if the build_new process changes this may have to /* Extract the function. */
change as well. */ argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
/* Then the second parm type. */
/* The NOP_EXPR. */
tree t = TREE_OPERAND (addr, 1);
/* The CALL_EXPR. */
t = TREE_OPERAND (t, 0);
/* The function. */
argtypes = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
/* The second parm type. */
argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes))); argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes)));
/* The second argument. */
args = TREE_CHAIN (TREE_OPERAND (t, 1));
/* Pull the dummy var out of the TARGET_EXPR for use in our call. */ /* Also the second argument. */
addr = TREE_OPERAND (addr, 0); args = TREE_CHAIN (TREE_OPERAND (placement, 1));
} }
else else
{ {
...@@ -3012,6 +2990,8 @@ build_op_delete_call (code, addr, size, flags) ...@@ -3012,6 +2990,8 @@ build_op_delete_call (code, addr, size, flags)
return build_function_call (fn, expr_tree_cons (NULL_TREE, addr, args)); return build_function_call (fn, expr_tree_cons (NULL_TREE, addr, args));
} }
/* If we are doing placement delete we do nothing if we don't find a
matching op delete. */
if (placement) if (placement)
return NULL_TREE; return NULL_TREE;
...@@ -3023,9 +3003,20 @@ build_op_delete_call (code, addr, size, flags) ...@@ -3023,9 +3003,20 @@ build_op_delete_call (code, addr, size, flags)
fn = instantiate_type (fntype, fns, 0); fn = instantiate_type (fntype, fns, 0);
if (fn != error_mark_node) if (fn != error_mark_node)
return build_function_call {
(fn, expr_tree_cons (NULL_TREE, addr, if (TREE_CODE (fns) == TREE_LIST)
build_expr_list (NULL_TREE, size))); /* Member functions. */
enforce_access (TREE_PURPOSE (fns), fn);
return build_function_call
(fn, expr_tree_cons (NULL_TREE, addr,
build_expr_list (NULL_TREE, size)));
}
/* finish_function passes LOOKUP_SPECULATIVELY if we're in a
destructor, in which case the error should be deferred
until someone actually tries to delete one of these. */
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
cp_error ("no suitable operator delete for `%T'", type); cp_error ("no suitable operator delete for `%T'", type);
return error_mark_node; return error_mark_node;
...@@ -4324,7 +4315,9 @@ joust (cand1, cand2, warn) ...@@ -4324,7 +4315,9 @@ joust (cand1, cand2, warn)
} }
/* warn about confusing overload resolution */ /* warn about confusing overload resolution */
if (winner && cand1->second_conv) if (winner && cand1->second_conv
&& (! DECL_CONSTRUCTOR_P (cand1->fn)
|| ! DECL_CONSTRUCTOR_P (cand2->fn)))
{ {
int comp = compare_ics (cand1->second_conv, cand2->second_conv); int comp = compare_ics (cand1->second_conv, cand2->second_conv);
if (comp != winner) if (comp != winner)
...@@ -4336,10 +4329,12 @@ joust (cand1, cand2, warn) ...@@ -4336,10 +4329,12 @@ joust (cand1, cand2, warn)
w = cand2, l = cand1; w = cand2, l = cand1;
if (warn) if (warn)
{ {
tree source = source_type (TREE_VEC_ELT (w->convs, 0));
if (! DECL_CONSTRUCTOR_P (w->fn))
source = TREE_TYPE (source);
cp_warning ("choosing `%D' over `%D'", w->fn, l->fn); cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
cp_warning (" for conversion from `%T' to `%T'", cp_warning (" for conversion from `%T' to `%T'",
TREE_TYPE (source_type (TREE_VEC_ELT (w->convs, 0))), source, TREE_TYPE (w->second_conv));
TREE_TYPE (w->second_conv));
cp_warning (" because conversion sequence for the argument is better"); cp_warning (" because conversion sequence for the argument is better");
} }
else else
......
...@@ -2251,7 +2251,7 @@ extern tree build_user_type_conversion PROTO((tree, tree, int)); ...@@ -2251,7 +2251,7 @@ extern tree build_user_type_conversion PROTO((tree, tree, int));
extern tree build_new_function_call PROTO((tree, tree)); extern tree build_new_function_call PROTO((tree, tree));
extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree)); extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree));
extern tree build_op_new_call PROTO((enum tree_code, tree, tree, int)); extern tree build_op_new_call PROTO((enum tree_code, tree, tree, int));
extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int)); extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int, tree));
extern int can_convert PROTO((tree, tree)); extern int can_convert PROTO((tree, tree));
extern int can_convert_arg PROTO((tree, tree, tree)); extern int can_convert_arg PROTO((tree, tree, tree));
extern void enforce_access PROTO((tree, tree)); extern void enforce_access PROTO((tree, tree));
......
...@@ -12507,20 +12507,22 @@ finish_function (lineno, call_poplevel, nested) ...@@ -12507,20 +12507,22 @@ finish_function (lineno, call_poplevel, nested)
virtual_size = c_sizeof (current_class_type); virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */ /* At the end, call delete if that's what's requested. */
if (TYPE_GETS_REG_DELETE (current_class_type))
/* This NOP_EXPR means we are in a static call context. */ /* FDIS sez: At the point of definition of a virtual destructor
exprstmt (including an implicit definition), non-placement operator
= build_method_call (build_indirect_ref (build1 (NOP_EXPR, delete shall be looked up in the scope of the destructor's
build_pointer_type (current_class_type), class and if found shall be accessible and unambiguous.
error_mark_node),
NULL_PTR), This is somewhat unclear, but I take it to mean that if the
ansi_opname[(int) DELETE_EXPR], class only defines placement deletes we don't do anything here.
expr_tree_cons (NULL_TREE, current_class_ptr, So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain
build_expr_list (NULL_TREE, virtual_size)), for us if they ever try to delete one of these. */
NULL_TREE, LOOKUP_NORMAL);
else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) if (TYPE_GETS_REG_DELETE (current_class_type)
exprstmt = build_x_delete (ptr_type_node, current_class_ptr, 0, || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
virtual_size); exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
else else
exprstmt = NULL_TREE; exprstmt = NULL_TREE;
......
...@@ -1326,8 +1326,8 @@ delete_sanity (exp, size, doing_vec, use_global_delete) ...@@ -1326,8 +1326,8 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
{ {
/* Only do access checking here; we'll be calling op delete /* Only do access checking here; we'll be calling op delete
from the destructor. */ from the destructor. */
tree tmp = build_op_delete_call (DELETE_EXPR, t, tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node,
size_zero_node, LOOKUP_NORMAL); LOOKUP_NORMAL, NULL_TREE);
if (tmp == error_mark_node) if (tmp == error_mark_node)
return error_mark_node; return error_mark_node;
} }
......
...@@ -2409,22 +2409,26 @@ build_new_1 (exp) ...@@ -2409,22 +2409,26 @@ build_new_1 (exp)
if (flag_exceptions && alloc_expr) if (flag_exceptions && alloc_expr)
{ {
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR; enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
tree cleanup; tree cleanup, fn = NULL_TREE;
int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL); int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL);
/* All cleanups must last longer than normal. */ /* All cleanups must last longer than normal. */
int yes = suspend_momentary (); int yes = suspend_momentary ();
if (placement) if (placement)
flags |= LOOKUP_SPECULATIVELY; {
flags |= LOOKUP_SPECULATIVELY;
/* We expect alloc_expr to look like a TARGET_EXPR around
a NOP_EXPR around the CALL_EXPR we want. */
fn = TREE_OPERAND (alloc_expr, 1);
fn = TREE_OPERAND (fn, 0);
}
/* Copy size to the saveable obstack. */ /* Copy size to the saveable obstack. */
size = copy_node (size); size = copy_node (size);
/* If we have a new-placement, we need to pass the alloc TARGET_EXPR cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
to build_op_delete_call so it can extract the args. */
cleanup = build_op_delete_call
(dcode, placement ? alloc_expr : alloc_node, size, flags);
resume_momentary (yes); resume_momentary (yes);
...@@ -2924,7 +2928,7 @@ build_x_delete (type, addr, which_delete, virtual_size) ...@@ -2924,7 +2928,7 @@ build_x_delete (type, addr, which_delete, virtual_size)
enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR; enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL); int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL);
return build_op_delete_call (code, addr, virtual_size, flags); return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
} }
/* Generate a call to a destructor. TYPE is the type to cast ADDR to. /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
...@@ -3020,7 +3024,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3020,7 +3024,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return build_op_delete_call return build_op_delete_call
(DELETE_EXPR, addr, c_sizeof_nowarn (type), (DELETE_EXPR, addr, c_sizeof_nowarn (type),
LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL)); LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
NULL_TREE);
} }
/* Below, we will reverse the order in which these calls are made. /* Below, we will reverse the order in which these calls are made.
......
...@@ -4777,6 +4777,8 @@ tsubst (t, args, in_decl) ...@@ -4777,6 +4777,8 @@ tsubst (t, args, in_decl)
#endif #endif
DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, in_decl); DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
return r; return r;
} }
...@@ -4836,6 +4838,8 @@ tsubst (t, args, in_decl) ...@@ -4836,6 +4838,8 @@ tsubst (t, args, in_decl)
SET_DECL_IMPLICIT_INSTANTIATION (r); SET_DECL_IMPLICIT_INSTANTIATION (r);
} }
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
return r; return r;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment