call.c (joust): Fix confusing conversion warning.
authorJason Merrill <jason@yorick.cygnus.com>
Tue, 23 Jun 1998 01:49:05 +0000 (01:49 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 23 Jun 1998 01:49:05 +0000 (21:49 -0400)
* 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
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/pt.c

index 6dd8d02df64e455e33e4e579aab5427fba0d20fd..27a81786e74a3bf597589a7abff4022981ea3fb3 100644 (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'.
index f9a49aa48eb87afb70ed64846a84961a11dfffd9..f6ff5f605d2b5bd3e3ed84fb4b5ab88e89c9a68d 100644 (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.  */
-
-      /* 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
index d3a6df954442f07538e9771a16973955bc2cb075..429f0ba8be90556fee77c999284560b9048b50ae 100644 (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));
index 1aaa3de7e223034931fb4bdcefd92fb4e071f30f..ab2a462fa26074ef7012c81d338c7614c783e814 100644 (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;
 
index b4b78fc69ade03eadc9501061d36f7bc41d43f1e..b3e3385c8e6c38cf2cac131cf13b724ba1c333b7 100644 (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;
        }
index 3b307791ec3d7d42422d5b801ecff2b5b8946b54..93367f73867e6bfd9f47f08bd938df57dd8de995 100644 (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.
index 3b883b8c06b1cc2f1027590a6f36bdb1d3e65ffd..3bd901625c3efc37a374381757152e46627eff71 100644 (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;
       }