From 519ebd1eecb18d95a75b8e4e3e5c063c4b82608b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 23 Jun 1998 01:49:05 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 11 +++++++ gcc/cp/call.c | 75 ++++++++++++++++++++++-------------------------- gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 30 ++++++++++--------- gcc/cp/decl2.c | 4 +-- gcc/cp/init.c | 21 ++++++++------ gcc/cp/pt.c | 4 +++ 7 files changed, 82 insertions(+), 65 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6dd8d02df64..27a81786e74 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +1998-06-23 Jason Merrill + + * 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 * call.c (build_scoped_method_call): Remove unused variable `tmp'. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f9a49aa48eb..f6ff5f605d2 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 d3a6df95444..429f0ba8be9 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 1aaa3de7e22..ab2a462fa26 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 b4b78fc69ad..b3e3385c8e6 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 3b307791ec3..93367f73867 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 3b883b8c06b..3bd901625c3 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; } -- 2.30.2