From b7d687279421b83415fefb62121156f37714093e Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 29 Apr 1999 08:33:55 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@26692 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 8 ++++ gcc/cp/cp-tree.h | 5 +++ gcc/cp/decl2.c | 4 ++ gcc/cp/init.c | 5 +-- gcc/cp/typeck.c | 7 ++++ gcc/testsuite/g++.old-deja/g++.bob/delete1.C | 4 +- gcc/testsuite/g++.old-deja/g++.jason/new3.C | 34 ++++++++++----- gcc/testsuite/g++.old-deja/g++.law/operators15.C | 2 +- gcc/testsuite/g++.old-deja/g++.law/operators23.C | 4 +- gcc/testsuite/g++.old-deja/g++.law/visibility15.C | 2 +- gcc/testsuite/g++.old-deja/g++.other/delete4.C | 51 +++++++++++++++++++++++ gcc/testsuite/g++.old-deja/g++.other/delete5.C | 39 +++++++++++++++++ gcc/testsuite/g++.old-deja/g++.robertl/eb101.C | 2 +- 13 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/delete4.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/delete5.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b8b3e5dd4f9..e19e6d3da23 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +1999-04-29 Nathan Sidwell + + * 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 * cp-tree.h (build_component_addr): Remove prototype. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index eb0411c4575..209d95bb6fa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 9d3288f8fc3..20a395783ec 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b825bfbe2a1..492a1ce0447 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index c64d72c317e..0053f1d9504 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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. */ diff --git a/gcc/testsuite/g++.old-deja/g++.bob/delete1.C b/gcc/testsuite/g++.old-deja/g++.bob/delete1.C index d4fc3210d67..cf4c8df8949 100644 --- a/gcc/testsuite/g++.old-deja/g++.bob/delete1.C +++ b/gcc/testsuite/g++.old-deja/g++.bob/delete1.C @@ -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() { diff --git a/gcc/testsuite/g++.old-deja/g++.jason/new3.C b/gcc/testsuite/g++.old-deja/g++.jason/new3.C index ede3a00e9dd..9bf944c8c08 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/new3.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/new3.C @@ -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 ; } diff --git a/gcc/testsuite/g++.old-deja/g++.law/operators15.C b/gcc/testsuite/g++.old-deja/g++.law/operators15.C index 08d952de82c..0b0623c94c5 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/operators15.C +++ b/gcc/testsuite/g++.old-deja/g++.law/operators15.C @@ -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) diff --git a/gcc/testsuite/g++.old-deja/g++.law/operators23.C b/gcc/testsuite/g++.old-deja/g++.law/operators23.C index 64036550934..7271840baa9 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/operators23.C +++ b/gcc/testsuite/g++.old-deja/g++.law/operators23.C @@ -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; diff --git a/gcc/testsuite/g++.old-deja/g++.law/visibility15.C b/gcc/testsuite/g++.old-deja/g++.law/visibility15.C index 9371eec798c..33fdb176e4a 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/visibility15.C +++ b/gcc/testsuite/g++.old-deja/g++.law/visibility15.C @@ -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 index 00000000000..ae98343b03c --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/delete4.C @@ -0,0 +1,51 @@ +// Build don't link: + +// Copyright (C) 1999 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 15 Apr 1999 + +// 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 index 00000000000..b522e9c16bb --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/delete5.C @@ -0,0 +1,39 @@ +// Copyright (C) 1999 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 15 Apr 1999 + +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; +} diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb101.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb101.C index 3004c0f7320..74c6cbb8141 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb101.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb101.C @@ -863,7 +863,7 @@ inline ios::~ios() { - if (_arrays) delete [] _arrays; + operator delete(_arrays); } } -- 2.11.0