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:
parent
5b8e7fa3f8
commit
519ebd1eec
|
@ -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'.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* 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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue