Commit 7f477e81 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 9939c435
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> 1999-04-28 Nathan Sidwell <nathan@acm.org>
* cp-tree.h (build_component_addr): Remove prototype. * cp-tree.h (build_component_addr): Remove prototype.
......
...@@ -1130,6 +1130,11 @@ struct lang_type ...@@ -1130,6 +1130,11 @@ struct lang_type
equivalently, no throw specification. */ equivalently, no throw specification. */
#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE) #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. */ /* The binding level associated with the namespace. */
#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level) #define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
......
...@@ -1212,6 +1212,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete) ...@@ -1212,6 +1212,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return error_mark_node; 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. */ /* An array can't have been allocated by new, so complain. */
if (TREE_CODE (t) == ADDR_EXPR if (TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
......
...@@ -2260,10 +2260,7 @@ build_new_1 (exp) ...@@ -2260,10 +2260,7 @@ build_new_1 (exp)
tree t = TREE_OPERAND (rval, 0); tree t = TREE_OPERAND (rval, 0);
/* The function. */ /* The function. */
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t)); nothrow = TYPE_NOTHROW_P (TREE_TYPE (t));
if (t && TREE_VALUE (t) == NULL_TREE)
nothrow = 1;
} }
check_new = (flag_check_new || nothrow) && ! use_java_new; check_new = (flag_check_new || nothrow) && ! use_java_new;
......
...@@ -7307,6 +7307,13 @@ c_expand_return (retval) ...@@ -7307,6 +7307,13 @@ c_expand_return (retval)
return; 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) if (retval == NULL_TREE)
{ {
/* A non-named return value does not count. */ /* A non-named return value does not count. */
......
...@@ -4,11 +4,11 @@ int size = 0; ...@@ -4,11 +4,11 @@ int size = 0;
struct X { struct X {
int x; int x;
void *operator new[](size_t sz) { void *operator new[](size_t sz) throw() {
size = sz; size = sz;
return 0; return 0;
} }
void operator delete[] (void *vp) { ::delete[] vp; } void operator delete[] (void *vp) { ::operator delete(vp); }
}; };
int main() int main()
{ {
......
// PRMS Id: 6037 // PRMS Id: 6037
// Special g++ Options: -fcheck-new // Special g++ Options: -fcheck-new -pedantic
extern "C" void * malloc (__SIZE_TYPE__); extern "C" void * malloc (__SIZE_TYPE__);
int ena = 0;
struct A { struct A {
int i; int i;
A () { i = 2; } A () { i = 2; }
void * operator new (__SIZE_TYPE__ s)
{
if (ena)
return 0; // WARNING - returning NULL
return malloc (s);
}
}; };
int ena = 0; struct B {
void * operator new (__SIZE_TYPE__ s) int i;
{ B () { i = 2; }
if (ena) void * operator new (__SIZE_TYPE__ s) throw()
return 0; {
return malloc (s); if (ena)
} return 0;
return malloc (s);
}
};
main () int main ()
{ {
ena = 1; ena = 1;
A* ap = new A; A *ap = new A;
B *bp = new B;
return ap || bp ;
} }
...@@ -10,7 +10,7 @@ extern "C" int printf(const char* ...); ...@@ -10,7 +10,7 @@ extern "C" int printf(const char* ...);
int delete_counter = -1; int delete_counter = -1;
struct T{ struct T{
void operator delete (void * p) {delete_counter ++; ::delete p;} void operator delete (void * p) {delete_counter ++; ::operator delete(p);}
}; };
int main(void) int main(void)
......
...@@ -13,7 +13,7 @@ class blah { ...@@ -13,7 +13,7 @@ class blah {
int j; int j;
public: public:
blah(); blah();
void *operator new(size_t size); void *operator new(size_t size) throw();
}; };
inline blah::blah() : j(0) { inline blah::blah() : j(0) {
...@@ -21,7 +21,7 @@ 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"); printf ("FAIL\n");
exit (1); exit (1);
return NULL; return NULL;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
class X { class X {
private: private:
void* operator new(size_t) {// ERROR - .* void* operator new(size_t) throw(){// ERROR - .*
printf("Inside private new().\n"); printf("Inside private new().\n");
return NULL; return NULL;
} }
......
// 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
}
// 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;
}
...@@ -863,7 +863,7 @@ inline ios::~ios() { ...@@ -863,7 +863,7 @@ inline ios::~ios() {
if (_arrays) delete [] _arrays; operator delete(_arrays);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment