init.c (init_init_processing): Go back to aligning like double_type_node for old ABI.

* init.c (init_init_processing): Go back to aligning like
        double_type_node for old ABI.
        (get_cookie_size): Make cookie larger if we get a type that needs
        more alignment.
        (build_vec_delete): Call it.

        * typeck.c (qualify_type_recursive): New fn.
        (composite_pointer_type): Use it.
        (build_binary_op): Use composite_pointer_type.

        * typeck.c (check_return_expr): Don't complain about returning
        NULL from operator new if -fcheck-new.
        * cp-tree.h: Declare flag_check_new here.
        * init.c: Not here.

From-SVN: r34824
This commit is contained in:
Jason Merrill 2000-07-01 23:00:03 -04:00
parent 792a328b3b
commit 708cae9771
8 changed files with 110 additions and 20780 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1223,6 +1223,11 @@ extern int flag_enforce_eh_specs;
extern int flag_access_control;
/* Nonzero if we want to check the return value of new and avoid calling
constructors if it is a null pointer. */
extern int flag_check_new;
/* If this variable is defined to a non-NULL value, it will be called
after the file has been completely parsed. The argument will be
the GLOBAL_NAMESPACE. */

View File

@ -58,7 +58,7 @@ static tree build_vtbl_address PARAMS ((tree));
/* Set up local variable for this file. MUST BE CALLED AFTER
INIT_DECL_PROCESSING. */
static tree BI_header_type, BI_header_size;
static tree BI_header_type;
void init_init_processing ()
{
@ -71,16 +71,10 @@ void init_init_processing ()
BI_header_type = make_aggr_type (RECORD_TYPE);
fields[0] = build_decl (FIELD_DECL, nelts_identifier, sizetype);
/* Use the biggest alignment supported by the target to prevent operator
new from returning misaligned pointers. */
TYPE_ALIGN (BI_header_type) = BIGGEST_ALIGNMENT;
TYPE_USER_ALIGN (BI_header_type) = 0;
finish_builtin_type (BI_header_type, "__new_cookie", fields,
0, BI_header_type);
BI_header_size = size_in_bytes (BI_header_type);
0, double_type_node);
ggc_add_tree_root (&BI_header_type, 1);
ggc_add_tree_root (&BI_header_size, 1);
}
/* We are about to generate some complex initialization code.
@ -1975,8 +1969,6 @@ build_builtin_delete_call (addr)
PLACEMENT is the `placement' list for user-defined operator new (). */
extern int flag_check_new;
tree
build_new (placement, decl, init, use_global_new)
tree placement;
@ -2205,7 +2197,12 @@ get_cookie_size (type)
cookie_size = type_align;
}
else
cookie_size = BI_header_size;
{
if (TYPE_ALIGN (type) > TYPE_ALIGN (BI_header_type))
return size_int (TYPE_ALIGN_UNIT (type));
else
return size_in_bytes (BI_header_type);
}
return cookie_size;
}
@ -2385,8 +2382,8 @@ build_new_1 (exp)
else
alloc_expr = NULL_TREE;
/* if rval is NULL_TREE I don't have to allocate it, but are we totally
sure we have some extra bytes in that case for the BI_header_size
/* if rval is NULL_TREE I don't have to allocate it, but are we
totally sure we have some extra bytes in that case for the
cookies? And how does that interact with the code below? (mrs) */
/* Finish up some magic for new'ed arrays */
if (use_cookie && rval != NULL_TREE)
@ -2633,7 +2630,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
goto no_destructor;
}
/* The below is short by BI_header_size */
/* The below is short by the cookie size. */
virtual_size = size_binop (MULT_EXPR, size_exp,
convert (sizetype, maxindex));
@ -2676,7 +2673,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
{
tree base_tbd;
/* The below is short by BI_header_size */
/* The below is short by the cookie size. */
virtual_size = size_binop (MULT_EXPR, size_exp,
convert (sizetype, maxindex));
@ -3378,6 +3375,7 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
/* Step back one from start of vector, and read dimension. */
tree cookie_addr;
type = strip_array_types (TREE_TYPE (type));
if (flag_new_abi)
{
cookie_addr = build (MINUS_EXPR,
@ -3391,13 +3389,11 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
tree cookie;
cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
base, BI_header_size);
base, get_cookie_size (type));
cookie = build_indirect_ref (cookie_addr, NULL_PTR);
maxindex = build_component_ref (cookie, nelts_identifier,
NULL_TREE, 0);
}
type = strip_array_types (TREE_TYPE (type));
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{

View File

@ -61,6 +61,7 @@ static tree lookup_anon_field PARAMS ((tree, tree));
static tree pointer_diff PARAMS ((tree, tree, tree));
static tree build_component_addr PARAMS ((tree, tree));
static tree qualify_type PARAMS ((tree, tree));
static tree qualify_type_recursive PARAMS ((tree, tree));
static tree get_delta_difference PARAMS ((tree, tree, int));
static int comp_cv_target_types PARAMS ((tree, tree, int));
static void casts_away_constness_r PARAMS ((tree *, tree *));
@ -209,6 +210,44 @@ qualify_type (type, like)
return cp_build_qualified_type (type, (CP_TYPE_QUALS (type)
| CP_TYPE_QUALS (like)));
}
/* Return a pointer or pointer to member type similar to T1, with a
cv-qualification signature that is the union of the cv-qualification
signatures of T1 and T2: [expr.rel], [expr.eq]. */
static tree
qualify_type_recursive (t1, t2)
tree t1, t2;
{
if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
|| (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)))
{
tree tt1 = TREE_TYPE (t1);
tree tt2 = TREE_TYPE (t2);
tree b1;
int type_quals;
tree target;
tree attributes = merge_machine_type_attributes (t1, t2);
if (TREE_CODE (tt1) == OFFSET_TYPE)
{
b1 = TYPE_OFFSET_BASETYPE (tt1);
tt1 = TREE_TYPE (tt1);
tt2 = TREE_TYPE (tt2);
}
else
b1 = NULL_TREE;
type_quals = (CP_TYPE_QUALS (tt1) | CP_TYPE_QUALS (tt2));
target = qualify_type_recursive (tt1, tt2);
target = cp_build_qualified_type (target, type_quals);
if (b1)
target = build_offset_type (b1, target);
t1 = build_pointer_type (target);
t1 = build_type_attribute_variant (t1, attributes);
}
return t1;
}
/* Return the common type of two parameter lists.
We assume that comptypes has already been done and returned 1;
@ -441,49 +480,35 @@ composite_pointer_type (t1, t2, arg1, arg2, location)
if (TYPE_PTRMEMFUNC_P (t2))
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
if (comp_target_types (t1, t2, 1))
result_type = common_type (t1, t2);
else if (VOID_TYPE_P (TREE_TYPE (t1)))
if (VOID_TYPE_P (TREE_TYPE (t1)))
{
if (pedantic && TREE_CODE (t2) == FUNCTION_TYPE)
if (pedantic && TYPE_PTRFN_P (t2))
pedwarn ("ISO C++ forbids %s between pointer of type `void *' and pointer-to-function", location);
result_type = qualify_type (t1, t2);
}
else if (VOID_TYPE_P (TREE_TYPE (t2)))
{
if (pedantic && TREE_CODE (t1) == FUNCTION_TYPE)
if (pedantic && TYPE_PTRFN_P (t1))
pedwarn ("ISO C++ forbids %s between pointer of type `void *' and pointer-to-function", location);
result_type = qualify_type (t2, t1);
}
/* C++ */
else if (same_or_base_type_p (t2, t1))
result_type = t2;
else if (IS_AGGR_TYPE (TREE_TYPE (t1))
&& IS_AGGR_TYPE (TREE_TYPE (t2))
&& (result_type = common_base_type (TREE_TYPE (t1),
TREE_TYPE (t2))))
{
if (result_type == error_mark_node)
{
cp_error ("common base type of types `%T' and `%T' is ambiguous",
TREE_TYPE (t1), TREE_TYPE (t2));
result_type = ptr_type_node;
}
else
{
if (pedantic
&& result_type != TREE_TYPE (t1)
&& result_type != TREE_TYPE (t2))
cp_pedwarn ("types `%T' and `%T' converted to `%T *' in %s",
t1, t2, result_type, location);
result_type = build_pointer_type (result_type);
}
}
else
{
cp_pedwarn ("pointer type mismatch in %s", location);
result_type = ptr_type_node;
tree full1 = qualify_type_recursive (t1, t2);
tree full2 = qualify_type_recursive (t2, t1);
int val = comp_target_types (full1, full2, 1);
if (val > 0)
result_type = full1;
else if (val < 0)
result_type = full2;
else
{
cp_pedwarn ("%s between distinct pointer types `%T' and `%T' lacks a cast",
location, t1, t2);
result_type = ptr_type_node;
}
}
return result_type;
@ -3578,33 +3603,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
|| code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
register tree tt0 = TYPE_MAIN_VARIANT (TREE_TYPE (type0));
register tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (type1));
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else if (VOID_TYPE_P (tt0))
{
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE
&& tree_int_cst_lt (TYPE_SIZE (type0), TYPE_SIZE (type1)))
pedwarn ("ISO C++ forbids comparison of `void *' with function pointer");
else if (TREE_CODE (tt1) == OFFSET_TYPE)
pedwarn ("ISO C++ forbids conversion of a pointer to member to `void *'");
}
else if (VOID_TYPE_P (tt1))
{
if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE
&& tree_int_cst_lt (TYPE_SIZE (type1), TYPE_SIZE (type0)))
pedwarn ("ISO C++ forbids comparison of `void *' with function pointer");
}
else
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
if (result_type == NULL_TREE)
result_type = ptr_type_node;
}
result_type = composite_pointer_type (type0, type1, op0, op1,
"comparison");
else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
result_type = type0;
else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
@ -3723,16 +3723,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else
{
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
result_type = ptr_type_node;
}
}
result_type = composite_pointer_type (type0, type1, op0, op1,
"comparison");
break;
case LE_EXPR:
@ -3744,16 +3736,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else
{
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
result_type = ptr_type_node;
}
}
result_type = composite_pointer_type (type0, type1, op0, op1,
"comparison");
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
result_type = type0;
@ -6844,8 +6828,9 @@ check_return_expr (retval)
if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
|| DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
&& !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
&& ! flag_check_new
&& null_ptr_cst_p (retval))
cp_warning ("`operator new' should throw an exception, not return NULL");
cp_warning ("`operator new' must not return NULL unless it is declared `throw()' (or -fcheck-new is in effect)");
/* Effective C++ rule 15. See also start_function. */
if (warn_ecpp

View File

@ -11,7 +11,7 @@ struct A {
void * operator new (__SIZE_TYPE__ s)
{
if (ena)
return 0; // WARNING - returning NULL
return 0;
return malloc (s);
}
};

View File

@ -6,5 +6,5 @@ void *vp;
void example ()
{
vp != fp; // gets bogus error - nuttin' wrong wit dat
vp != fp; // ERROR - no conversion from pfn to void*
}

View File

@ -4,12 +4,11 @@
// by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
// simplified from bug report by Paul Burchard <burchard@pobox.com>
// crash test - XFAIL *-*-*
template<class> struct A {};
template<template<class> class T> struct B {
B() {
T<B>(); // gets bogus error - conversion from int to non-scalar - XFAIL *-*-*
T<B>(); // gets bogus error - conversion from int to non-scalar
}
};
B<A> foo;

View File

@ -11,18 +11,18 @@ int main ()
// The composite type is `A const *'
A* ap = &b;
const B* bp = &b;
if (ap != bp) // gets bogus error - distinct types XFAIL *-*-*
if (ap != bp) // gets bogus error - distinct types
return 1;
// The composite type is `B const *const *'
B *const * p = 0;
B const * * q = 0;
if (p != q) // gets bogus error - distinct types XFAIL *-*-*
if (p != q) // gets bogus error - distinct types
return 1;
// The common type is `int const B::*'
const int A::*apm = &A::i;
int B::*bpm = &A::i;
if (apm != bpm) // gets bogus error - distinct types XFAIL *-*-*
if (apm != bpm) // gets bogus error - distinct types
return 1;
}