* 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
+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.
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
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
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;
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. */
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()
{
// 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 ;
}
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)
int j;
public:
blah();
- void *operator new(size_t size);
+ void *operator new(size_t size) throw();
};
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;
class X {
private:
- void* operator new(size_t) {// ERROR - .*
+ void* operator new(size_t) throw(){// ERROR - .*
printf("Inside private new().\n");
return NULL;
}
--- /dev/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
+}
--- /dev/null
+// 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;
+}
- if (_arrays) delete [] _arrays;
+ operator delete(_arrays);
}
}