cp-tree.h (TYPE_NOTHROW_P): New macro.

* 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.

From-SVN: r26692
This commit is contained in:
Nathan Sidwell 1999-04-29 08:33:55 +00:00 committed by Nathan Sidwell
parent 9939c435d2
commit 7f477e818a
13 changed files with 146 additions and 21 deletions

View 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.

View 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)

View 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

View 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;

View 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. */

View 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()
{

View 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 ;
}

View 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)

View 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;

View 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;
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -863,7 +863,7 @@ inline ios::~ios() {
if (_arrays) delete [] _arrays;
operator delete(_arrays);
}
}