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
This commit is contained in:
Jason Merrill 1998-06-23 01:49:05 +00:00 committed by Jason Merrill
parent 5b8e7fa3f8
commit 519ebd1eec
7 changed files with 81 additions and 64 deletions

View File

@ -1,3 +1,14 @@
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>
* call.c (build_scoped_method_call): Remove unused variable `tmp'.

View File

@ -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
used to determine what the corresponding new looked like.
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
build_op_delete_call (code, addr, size, flags)
build_op_delete_call (code, addr, size, flags, placement)
enum tree_code code;
tree addr, size;
tree addr, size, placement;
int flags;
{
tree fn, fns, fnname, fntype, argtypes, args, type;
int placement;
if (addr == error_mark_node)
return error_mark_node;
@ -2946,42 +2946,20 @@ build_op_delete_call (code, addr, size, flags)
else
fns = NULL_TREE;
if (fns)
{
#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
if (fns == NULL_TREE)
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, we are coming from build_new, and we know that addr
is the allocation expression, so extract the info we need from it.
Obviously, if the build_new process changes this may have to
change as well. */
/* placement is a CALL_EXPR around an ADDR_EXPR around a function. */
/* 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. */
/* Extract the function. */
argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
/* Then the second parm type. */
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. */
addr = TREE_OPERAND (addr, 0);
/* Also the second argument. */
args = TREE_CHAIN (TREE_OPERAND (placement, 1));
}
else
{
@ -3012,6 +2990,8 @@ build_op_delete_call (code, addr, size, flags)
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)
return NULL_TREE;
@ -3023,9 +3003,20 @@ build_op_delete_call (code, addr, size, flags)
fn = instantiate_type (fntype, fns, 0);
if (fn != error_mark_node)
return build_function_call
(fn, expr_tree_cons (NULL_TREE, addr,
build_expr_list (NULL_TREE, size)));
{
if (TREE_CODE (fns) == TREE_LIST)
/* 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);
return error_mark_node;
@ -4324,7 +4315,9 @@ joust (cand1, cand2, warn)
}
/* 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);
if (comp != winner)
@ -4336,10 +4329,12 @@ joust (cand1, cand2, warn)
w = cand2, l = cand1;
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 (" for conversion from `%T' to `%T'",
TREE_TYPE (source_type (TREE_VEC_ELT (w->convs, 0))),
TREE_TYPE (w->second_conv));
source, TREE_TYPE (w->second_conv));
cp_warning (" because conversion sequence for the argument is better");
}
else

View File

@ -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_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_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_arg PROTO((tree, tree, tree));
extern void enforce_access PROTO((tree, tree));

View File

@ -12507,20 +12507,22 @@ finish_function (lineno, call_poplevel, nested)
virtual_size = c_sizeof (current_class_type);
/* 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. */
exprstmt
= build_method_call (build_indirect_ref (build1 (NOP_EXPR,
build_pointer_type (current_class_type),
error_mark_node),
NULL_PTR),
ansi_opname[(int) DELETE_EXPR],
expr_tree_cons (NULL_TREE, current_class_ptr,
build_expr_list (NULL_TREE, virtual_size)),
NULL_TREE, LOOKUP_NORMAL);
else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
exprstmt = build_x_delete (ptr_type_node, current_class_ptr, 0,
virtual_size);
/* FDIS sez: At the point of definition of a virtual destructor
(including an implicit definition), non-placement operator
delete shall be looked up in the scope of the destructor's
class and if found shall be accessible and unambiguous.
This is somewhat unclear, but I take it to mean that if the
class only defines placement deletes we don't do anything here.
So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain
for us if they ever try to delete one of these. */
if (TYPE_GETS_REG_DELETE (current_class_type)
|| TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
else
exprstmt = NULL_TREE;

View File

@ -1326,8 +1326,8 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
{
/* Only do access checking here; we'll be calling op delete
from the destructor. */
tree tmp = build_op_delete_call (DELETE_EXPR, t,
size_zero_node, LOOKUP_NORMAL);
tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node,
LOOKUP_NORMAL, NULL_TREE);
if (tmp == error_mark_node)
return error_mark_node;
}

View File

@ -2409,22 +2409,26 @@ build_new_1 (exp)
if (flag_exceptions && alloc_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);
/* All cleanups must last longer than normal. */
int yes = suspend_momentary ();
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. */
size = copy_node (size);
/* If we have a new-placement, we need to pass the alloc TARGET_EXPR
to build_op_delete_call so it can extract the args. */
cleanup = build_op_delete_call
(dcode, placement ? alloc_expr : alloc_node, size, flags);
cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
resume_momentary (yes);
@ -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;
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.
@ -3020,7 +3024,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return build_op_delete_call
(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.

View File

@ -4777,6 +4777,8 @@ tsubst (t, args, in_decl)
#endif
DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
return r;
}
@ -4836,6 +4838,8 @@ tsubst (t, args, in_decl)
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
return r;
}