* cp-tree.h (CLASSTYPE_DESTRUCTORS): Fix typo in comment.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Feb 2001 06:32:15 +0000 (06:32 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Feb 2001 06:32:15 +0000 (06:32 +0000)
* call.c (build_op_delete_call): Simplify to remove duplicate
code.
* class.c (clone_function_decl): Don't build the deleting variant
of a non-virtual destructor.
* decl.c (finish_destructor_body): Don't call delete if this is a
non-virtual destructor.
* init.c (build_delete): Explicitly call `operator delete' when
deleting an object with a non-virtual destructor.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39659 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/testsuite/g++.old-deja/g++.oliva/delete1.C

index 64deaaf..4dad898 100644 (file)
@@ -1,3 +1,15 @@
+2001-02-13  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (CLASSTYPE_DESTRUCTORS): Fix typo in comment.
+       * call.c (build_op_delete_call): Simplify to remove duplicate
+       code.
+       * class.c (clone_function_decl): Don't build the deleting variant
+       of a non-virtual destructor.
+       * decl.c (finish_destructor_body): Don't call delete if this is a
+       non-virtual destructor.
+       * init.c (build_delete): Explicitly call `operator delete' when
+       deleting an object with a non-virtual destructor.
+       
 2001-02-13  Jason Merrill  <jason@redhat.com>
 
        * lang-specs.h: Add more __EXCEPTIONS.
index 7cb34bd..11cb640 100644 (file)
@@ -3547,6 +3547,7 @@ build_op_delete_call (code, addr, size, flags, placement)
      int flags;
 {
   tree fn, fns, fnname, fntype, argtypes, args, type;
+  int pass;
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -3595,48 +3596,45 @@ build_op_delete_call (code, addr, size, flags, placement)
       args = NULL_TREE;
     }
 
-  argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
-  fntype = build_function_type (void_type_node, argtypes);
-
   /* Strip const and volatile from addr.  */
   addr = cp_convert (ptr_type_node, addr);
 
-  fn = instantiate_type (fntype, fns, itf_no_attributes);
-
-  if (fn != error_mark_node)
+  /* We make two tries at finding a matching `operator delete'.  On
+     the first pass, we look for an one-operator (or placement)
+     operator delete.  If we're not doing placement delete, then on
+     the second pass we look for a two-argument delete.  */
+  for (pass = 0; pass < (placement ? 1 : 2); ++pass) 
     {
-      if (TREE_CODE (fns) == TREE_LIST)
-       /* Member functions.  */
-       enforce_access (type, fn);
-      return build_function_call (fn, 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;
+      if (pass == 0)
+       argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
+      else 
+       /* Normal delete; now try to find a match including the size
+          argument.  */
+       argtypes = tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, sizetype, 
+                                        void_list_node));
 
-  /* Normal delete; now try to find a match including the size argument.  */
-  argtypes = tree_cons (NULL_TREE, ptr_type_node,
-                       tree_cons (NULL_TREE, sizetype, void_list_node));
-  fntype = build_function_type (void_type_node, argtypes);
+      fntype = build_function_type (void_type_node, argtypes);
+      fn = instantiate_type (fntype, fns, itf_no_attributes);
 
-  fn = instantiate_type (fntype, fns, itf_no_attributes);
+      if (fn != error_mark_node)
+       {
+         /* Member functions.  */
+         if (BASELINK_P (fns))
+           enforce_access (type, fn);
 
-  if (fn != error_mark_node)
-    {
-      if (BASELINK_P (fns))
-       /* Member functions.  */
-       enforce_access (type, fn);
-      return build_function_call
-       (fn, tree_cons (NULL_TREE, addr,
-                       build_tree_list (NULL_TREE, size)));
+         if (pass == 0)
+           args = tree_cons (NULL_TREE, addr, args);
+         else
+           args = tree_cons (NULL_TREE, addr, 
+                             build_tree_list (NULL_TREE, size));
+         return build_function_call (fn, args);
+       }
     }
 
-  /* 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)
+  /* If we are doing placement delete we do nothing if we don't find a
+     matching op delete.  */
+  if (placement)
     return NULL_TREE;
 
   cp_error ("no suitable `operator delete' for `%T'", type);
index 3f50da3..2d8ab83 100644 (file)
@@ -4319,10 +4319,16 @@ clone_function_decl (fn, update_method_vec_p)
         version.  We clone the deleting version first because that
         means it will go second on the TYPE_METHODS list -- and that
         corresponds to the correct layout order in the virtual
-        function table.  */
-      clone = build_clone (fn, deleting_dtor_identifier);
-      if (update_method_vec_p)
-       add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+        function table.  
+
+         For a non-virtual destructor, we do not build a deleting
+        destructor.  */
+      if (DECL_VIRTUAL_P (fn))
+       {
+         clone = build_clone (fn, deleting_dtor_identifier);
+         if (update_method_vec_p)
+           add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+       }
       clone = build_clone (fn, complete_dtor_identifier);
       if (update_method_vec_p)
        add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
index eb7afc0..7881429 100644 (file)
@@ -1456,7 +1456,7 @@ struct lang_type
 #define CLASSTYPE_CONSTRUCTORS(NODE) \
   (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
 
-/* A FUNCTION_DECL for the destructor for NODE.  These are te
+/* A FUNCTION_DECL for the destructor for NODE.  These are the
    destructors that take an in-charge parameter.  */
 #define CLASSTYPE_DESTRUCTORS(NODE) \
   (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT))
index ead15db..3e3f37b 100644 (file)
@@ -13730,9 +13730,7 @@ static void
 finish_destructor_body ()
 {
   tree compound_stmt;
-  tree virtual_size;
   tree exprstmt;
-  tree if_stmt;
 
   /* Create a block to contain all the extra code.  */
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
@@ -13814,31 +13812,31 @@ finish_destructor_body ()
        }
     }
 
-  virtual_size = c_sizeof (current_class_type);
-
-  /* At the end, call delete if that's what's requested.  */
+  /* In a virtual destructor, we must call delete.  */
+  if (DECL_VIRTUAL_P (current_function_decl))
+    {
+      tree if_stmt;
+      tree virtual_size = c_sizeof (current_class_type);
 
-  /* 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.
+      /* [class.dtor]
 
-     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.  */
-  exprstmt = build_op_delete_call
-    (DELETE_EXPR, current_class_ptr, virtual_size,
-     LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+        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.  */
+      exprstmt = build_op_delete_call
+       (DELETE_EXPR, current_class_ptr, virtual_size,
+        LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
 
-  if_stmt = begin_if_stmt ();
-  finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
-                             current_in_charge_parm,
-                             integer_one_node),
-                      if_stmt);
-  finish_expr_stmt (exprstmt);
-  finish_then_clause (if_stmt);
-  finish_if_stmt ();
+      if_stmt = begin_if_stmt ();
+      finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
+                                 current_in_charge_parm,
+                                 integer_one_node),
+                          if_stmt);
+      finish_expr_stmt (exprstmt);
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 
   /* Close the block we started above.  */
   finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
index 4e68b64..becb347 100644 (file)
@@ -3235,6 +3235,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       tree do_delete = NULL_TREE;
       tree ifexp;
 
+      /* For `::delete x', we must not use the deleting destructor
+        since then we would not be sure to get the global `operator
+        delete'.  */
       if (use_global_delete && auto_delete == sfk_deleting_destructor)
        {
          /* Delete the object. */
@@ -3243,6 +3246,21 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
             call.  */
          auto_delete = sfk_complete_destructor;
        }
+      /* If the destructor is non-virtual, there is no deleting
+        variant.  Instead, we must explicitly call the appropriate
+        `operator delete' here.  */
+      else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type))
+              && auto_delete == sfk_deleting_destructor)
+       {
+         /* Buidl the call.  */
+         do_delete = build_op_delete_call (DELETE_EXPR,
+                                           addr,
+                                           c_sizeof_nowarn (type),
+                                           LOOKUP_NORMAL,
+                                           NULL_TREE);
+         /* Call the complete object destructor.  */
+         auto_delete = sfk_complete_destructor;
+       }
 
       expr = build_dtor_call (ref, auto_delete, flags);
       if (do_delete)
index dee7f21..d8ddefe 100644 (file)
@@ -1,6 +1,6 @@
 // Build don't link:
 
-// Copyright (C) 1999 Free Software Foundation
+// Copyright (C) 1999, 2001 Free Software Foundation
 
 // by Alexandre Oliva <oliva@dcc.unicamp.br>
 // simplified from bug report by K. Haley <khaley@bigfoot.com>
@@ -21,7 +21,7 @@ struct bar : foo {
     delete this; // ERROR - delete is private
     // An implicit invocation of delete is emitted in destructors, but
     // it should only be checked in virtual destructors
-  } // gets bogus error - not virtual - XFAIL *-*-*
+  } // gets bogus error - not virtual
 } bar_;
 
 struct baz : foo {