aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1998-06-23 01:49:05 +0000
committerJason Merrill <jason@gcc.gnu.org>1998-06-22 21:49:05 -0400
commit519ebd1eecb18d95a75b8e4e3e5c063c4b82608b (patch)
tree9ef5d9ccc281c5e870c35df3179c526ac1ef69ca /gcc
parent5b8e7fa3f89041ca0e46f4cd71851c69df71a2e4 (diff)
downloadgcc-519ebd1eecb18d95a75b8e4e3e5c063c4b82608b.zip
gcc-519ebd1eecb18d95a75b8e4e3e5c063c4b82608b.tar.gz
gcc-519ebd1eecb18d95a75b8e4e3e5c063c4b82608b.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c75
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c30
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/init.c21
-rw-r--r--gcc/cp/pt.c4
7 files changed, 82 insertions, 65 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6dd8d02..27a8178 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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'.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f9a49aa..f6ff5f6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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. */
-
- /* 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. */
+ /* placement is a CALL_EXPR around an ADDR_EXPR around a function. */
+
+ /* 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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d3a6df9..429f0ba 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1aaa3de..ab2a462 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index b4b78fc..b3e3385 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3b30779..93367f7 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3b883b8..3bd9016 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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;
}