OSDN Git Service

* cp-tree.h (TYPE_NOTHROW_P): New macro.
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 29 Apr 1999 08:33:55 +0000 (08:33 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 29 Apr 1999 08:33:55 +0000 (08:33 +0000)
* decl2.c (delete_sanity): Warn on deleting void *.
* init.c (build_new_1): Use TYPE_NOTHROW_P.
* typeck.c (c_expand_return): cp_pedwarn on returning NULL from
throwing operator new.

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

13 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.bob/delete1.C
gcc/testsuite/g++.old-deja/g++.jason/new3.C
gcc/testsuite/g++.old-deja/g++.law/operators15.C
gcc/testsuite/g++.old-deja/g++.law/operators23.C
gcc/testsuite/g++.old-deja/g++.law/visibility15.C
gcc/testsuite/g++.old-deja/g++.other/delete4.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/delete5.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.robertl/eb101.C

index b8b3e5d..e19e6d3 100644 (file)
@@ -1,3 +1,11 @@
+1999-04-29  Nathan Sidwell  <nathan@acm.org>
+
+       * cp-tree.h (TYPE_NOTHROW_P): New macro.
+       * decl2.c (delete_sanity): Warn on deleting void *.
+       * init.c (build_new_1): Use TYPE_NOTHROW_P.
+       * typeck.c (c_expand_return): cp_pedwarn on returning NULL from
+       throwing operator new.
+
 1999-04-28  Nathan Sidwell  <nathan@acm.org>
 
        * cp-tree.h (build_component_addr): Remove prototype.
index eb0411c..209d95b 100644 (file)
@@ -1130,6 +1130,11 @@ struct lang_type
    equivalently, no throw specification.  */
 #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
 
+/* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'.  */
+#define TYPE_NOTHROW_P(NODE) \
+  (TYPE_RAISES_EXCEPTIONS (NODE) \
+   && TREE_VALUE (TYPE_RAISES_EXCEPTIONS (NODE)) == NULL_TREE)
+
 /* The binding level associated with the namespace.  */
 #define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
 \f
index 9d3288f..20a3957 100644 (file)
@@ -1212,6 +1212,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
       return error_mark_node;
     }
 
+  /* Deleting ptr to void is undefined behaviour [expr.delete/3].  */
+  if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
+    cp_warning ("`%T' is not a pointer-to-object type", type);
+  
   /* An array can't have been allocated by new, so complain.  */
   if (TREE_CODE (t) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
index b825bfb..492a1ce 100644 (file)
@@ -2260,10 +2260,7 @@ build_new_1 (exp)
       tree t = TREE_OPERAND (rval, 0);
       /* The function.  */
       t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
-      t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
-
-      if (t && TREE_VALUE (t) == NULL_TREE)
-       nothrow = 1;
+      nothrow = TYPE_NOTHROW_P (TREE_TYPE (t));
     }
   check_new = (flag_check_new || nothrow) && ! use_java_new;
 
index c64d72c..0053f1d 100644 (file)
@@ -7307,6 +7307,13 @@ c_expand_return (retval)
       return;
     }
 
+  /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
+  if ((DECL_NAME (current_function_decl) == ansi_opname[(int) NEW_EXPR]
+       || DECL_NAME (current_function_decl) == ansi_opname[(int) VEC_NEW_EXPR])
+      && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
+      && null_ptr_cst_p (retval))
+    cp_pedwarn ("operator new should throw an exception, not return NULL");
+  
   if (retval == NULL_TREE)
     {
       /* A non-named return value does not count.  */
index d4fc321..cf4c8df 100644 (file)
@@ -4,11 +4,11 @@ int size = 0;
 
 struct X {
     int x;
-    void *operator new[](size_t sz)   {
+    void *operator new[](size_t sz) throw()  {
          size = sz;
          return 0;  
     }
-    void operator delete[] (void *vp) { ::delete[] vp; }  
+    void operator delete[] (void *vp) { ::operator delete(vp); }  
 };
 int main()
 {
index ede3a00..9bf944c 100644 (file)
@@ -1,23 +1,37 @@
 // PRMS Id: 6037
-// Special g++ Options: -fcheck-new
+// Special g++ Options: -fcheck-new -pedantic
 
 extern "C" void * malloc (__SIZE_TYPE__);
 
+int ena = 0;
+
 struct A {
   int i;
   A () { i = 2; }
+  void * operator new (__SIZE_TYPE__ s)
+  {
+    if (ena)
+      return 0; // WARNING - returning NULL
+    return malloc (s);
+  }
 };
 
-int ena = 0;
-void * operator new (__SIZE_TYPE__ s)
-{
-  if (ena)
-    return 0;
-  return malloc (s);
-}
+struct B {
+  int i;
+  B () { i = 2; }
+  void * operator new (__SIZE_TYPE__ s) throw()
+  {
+    if (ena)
+      return 0;
+    return malloc (s);
+  }
+};
 
-main ()
+int main ()
 {
   ena = 1;
-  A* ap = new A;
+  A *ap = new A;
+  B *bp = new B;
+  
+  return ap || bp ;
 }
index 08d952d..0b0623c 100644 (file)
@@ -10,7 +10,7 @@ extern "C" int printf(const char* ...);
 int     delete_counter = -1;
 
 struct T{
-  void operator delete (void * p) {delete_counter ++; ::delete p;}
+  void operator delete (void * p) {delete_counter ++; ::operator delete(p);}
 };
 
 int main(void)
index 6403655..7271840 100644 (file)
@@ -13,7 +13,7 @@ class blah {
      int j;
    public:
      blah();
-     void *operator new(size_t size);
+     void *operator new(size_t size) throw();
 };
 
 inline blah::blah() : j(0) {
@@ -21,7 +21,7 @@ inline blah::blah() : j(0) {
 }
 
 
-void *blah::operator new(size_t size) {
+void *blah::operator new(size_t size) throw(){
      printf ("FAIL\n");
      exit (1);
      return NULL;
index 9371eec..33fdb17 100644 (file)
@@ -10,7 +10,7 @@
 
 class X {
 private:
-  void* operator new(size_t) {// ERROR - .*
+  void* operator new(size_t) throw(){// ERROR - .*
     printf("Inside private new().\n");
     return NULL;
   }
diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete4.C b/gcc/testsuite/g++.old-deja/g++.other/delete4.C
new file mode 100644 (file)
index 0000000..ae98343
--- /dev/null
@@ -0,0 +1,51 @@
+// Build don't link:
+
+// Copyright (C) 1999 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 15 Apr 1999 <nathan@acm.org>
+
+// delete (void *)e and delete[] (void *)e result in undefined behaviour
+// [expr.delete/3]. Check we warn about them
+// operator new functions can only return NULL, if their exceptions
+// specification is `throw()'. All other cases must return a non-null pointer
+// [expr.new/13].
+
+void *operator new(unsigned)
+{
+  return 0; // ERROR - cannot return NULL
+}
+void *operator new[](unsigned)
+{
+  return 0; // ERROR - cannot return NULL
+}
+
+struct X
+{
+  void *operator new(unsigned)
+  {
+    return 0; // ERROR - cannot return NULL
+  }
+  void *operator new[](unsigned)
+  {
+    return 0; // ERROR - cannot return NULL
+  }
+};
+
+struct Y
+{
+  void *operator new(unsigned) throw()
+  {
+    return 0; // ok
+  }
+  void *operator new[](unsigned) throw()
+  {
+    return 0; // ok
+  }
+};
+
+void fn(double *d, void *v)
+{
+  delete d;   // ok
+  delete v;   // WARNING - deleting void
+  delete[] d; // ok
+  delete[] v; // WARNING - deleting void
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete5.C b/gcc/testsuite/g++.old-deja/g++.other/delete5.C
new file mode 100644 (file)
index 0000000..b522e9c
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 1999 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 15 Apr 1999 <nathan@acm.org>
+
+struct X
+{
+  int i;
+  
+  X():i(){}
+  void *operator new(unsigned)
+  {
+    return 0; // WARNING - cannot return NULL
+  }
+  void *operator new[](unsigned)
+  {
+    return 0; // WARNING - cannot return NULL
+  }
+};
+
+struct Y
+{
+  int i;
+  
+  Y():i(){}
+  void *operator new(unsigned) throw()
+  {
+    return 0; // ok
+  }
+  void *operator new[](unsigned) throw()
+  {
+    return 0; // ok
+  }
+};
+
+int main()
+{
+  Y *yp = new Y;
+  
+  return yp != 0;
+}
index 3004c0f..74c6cbb 100644 (file)
@@ -863,7 +863,7 @@ inline ios::~ios() {
 
 
 
-    if (_arrays) delete [] _arrays;
+    operator delete(_arrays);
 }
 }