Commit ce3da0d0 by Eric Botcazou Committed by Eric Botcazou

stor-layout.c (layout_type): Do not clear TREE_OVERFLOW on overflowed zeroes,…

stor-layout.c (layout_type): Do not clear TREE_OVERFLOW on overflowed zeroes, except in one specific case.

	* stor-layout.c (layout_type) <ARRAY_TYPE>: Do not clear TREE_OVERFLOW
	on overflowed zeroes, except in one specific case.
ada/
	* gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Use
	valid_constant_size_p to detect too large objects.
	<E_Subprogram_Type>: Likewise for too large return types.
	(allocatable_size_p): Call valid_constant_size_p in the fixed case.
	(annotate_value) <INTEGER_CST>: Simplify.
	<BIT_AND_EXPR>: Deal with negative values here.
	* gcc-interface/trans.c (gnat_to_gnu) <N_Assignment_Statement>: Use
	valid_constant_size_p to detect too large objects on the LHS.
	* gcc-interface/misc.c (default_pass_by_ref): Likewise for large types.
	And use TYPE_SIZE_UNIT throughout.
	(must_pass_by_ref): Likewise.
	* gcc-interface/utils.c (max_size) <tcc_unary>: Split from common case.
	<tcc_binary>: Likewise.  Call size_binop instead of fold_build2.
	<tcc_expression>: Simplify.
	* gcc-interface/utils2.c (build_allocator): Use valid_constant_size_p
	to detect too large allocations.

From-SVN: r193886
parent fb1fbef2
2012-11-28 Eric Botcazou <ebotcazou@adacore.com>
* stor-layout.c (layout_type) <ARRAY_TYPE>: Do not clear TREE_OVERFLOW
on overflowed zeroes, except in one specific case.
2012-11-28 Marc Glisse <marc.glisse@inria.fr> 2012-11-28 Marc Glisse <marc.glisse@inria.fr>
PR middle-end/55266 PR middle-end/55266
2012-11-27 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Use
valid_constant_size_p to detect too large objects.
<E_Subprogram_Type>: Likewise for too large return types.
(allocatable_size_p): Call valid_constant_size_p in the fixed case.
(annotate_value) <INTEGER_CST>: Simplify.
<BIT_AND_EXPR>: Deal with negative values here.
* gcc-interface/trans.c (gnat_to_gnu) <N_Assignment_Statement>: Use
valid_constant_size_p to detect too large objects on the LHS.
* gcc-interface/misc.c (default_pass_by_ref): Likewise for large types.
And use TYPE_SIZE_UNIT throughout.
(must_pass_by_ref): Likewise.
* gcc-interface/utils.c (max_size) <tcc_unary>: Split from common case.
<tcc_binary>: Likewise. Call size_binop instead of fold_build2.
<tcc_expression>: Simplify.
* gcc-interface/utils2.c (build_allocator): Use valid_constant_size_p
to detect too large allocations.
2012-11-23 Eric Botcazou <ebotcazou@adacore.com> 2012-11-23 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Length>: Look through * gcc-interface/trans.c (Attribute_to_gnu) <Attr_Length>: Look through
......
...@@ -1337,7 +1337,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -1337,7 +1337,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
} }
if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (gnu_alloc_type))) && !valid_constant_size_p (TYPE_SIZE_UNIT (gnu_alloc_type)))
post_error ("?`Storage_Error` will be raised at run time!", post_error ("?`Storage_Error` will be raised at run time!",
gnat_entity); gnat_entity);
...@@ -4240,8 +4240,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -4240,8 +4240,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
a function that returns that type. This usage doesn't make a function that returns that type. This usage doesn't make
sense anyway, so give an error here. */ sense anyway, so give an error here. */
if (TYPE_SIZE_UNIT (gnu_return_type) if (TYPE_SIZE_UNIT (gnu_return_type)
&& TREE_CONSTANT (TYPE_SIZE_UNIT (gnu_return_type)) && TREE_CODE (TYPE_SIZE_UNIT (gnu_return_type)) == INTEGER_CST
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (gnu_return_type))) && !valid_constant_size_p (TYPE_SIZE_UNIT (gnu_return_type)))
{ {
post_error ("cannot return type whose size overflows", post_error ("cannot return type whose size overflows",
gnat_entity); gnat_entity);
...@@ -5989,10 +5989,9 @@ elaborate_entity (Entity_Id gnat_entity) ...@@ -5989,10 +5989,9 @@ elaborate_entity (Entity_Id gnat_entity)
static bool static bool
allocatable_size_p (tree gnu_size, bool static_p) allocatable_size_p (tree gnu_size, bool static_p)
{ {
/* We can allocate a fixed size if it hasn't overflowed and can be handled /* We can allocate a fixed size if it is a valid for the middle-end. */
(efficiently) on the host. */
if (TREE_CODE (gnu_size) == INTEGER_CST) if (TREE_CODE (gnu_size) == INTEGER_CST)
return !TREE_OVERFLOW (gnu_size) && host_integerp (gnu_size, 1); return valid_constant_size_p (gnu_size);
/* We can allocate a variable size if this isn't a static allocation. */ /* We can allocate a variable size if this isn't a static allocation. */
else else
...@@ -7254,7 +7253,7 @@ static Uint ...@@ -7254,7 +7253,7 @@ static Uint
annotate_value (tree gnu_size) annotate_value (tree gnu_size)
{ {
TCode tcode; TCode tcode;
Node_Ref_Or_Val ops[3], ret; Node_Ref_Or_Val ops[3], ret, pre_op1 = No_Uint;
struct tree_int_map in; struct tree_int_map in;
int i; int i;
...@@ -7283,24 +7282,7 @@ annotate_value (tree gnu_size) ...@@ -7283,24 +7282,7 @@ annotate_value (tree gnu_size)
switch (TREE_CODE (gnu_size)) switch (TREE_CODE (gnu_size))
{ {
case INTEGER_CST: case INTEGER_CST:
if (TREE_OVERFLOW (gnu_size)) return TREE_OVERFLOW (gnu_size) ? No_Uint : UI_From_gnu (gnu_size);
return No_Uint;
/* This may come from a conversion from some smaller type, so ensure
this is in bitsizetype. */
gnu_size = convert (bitsizetype, gnu_size);
/* For a negative value, build NEGATE_EXPR of the opposite. Such values
appear in expressions containing aligning patterns. Note that, since
sizetype is sign-extended but nonetheless unsigned, we don't directly
use tree_int_cst_sgn. */
if (TREE_INT_CST_HIGH (gnu_size) < 0)
{
tree op_size = fold_build1 (NEGATE_EXPR, bitsizetype, gnu_size);
return annotate_value (build1 (NEGATE_EXPR, bitsizetype, op_size));
}
return UI_From_gnu (gnu_size);
case COMPONENT_REF: case COMPONENT_REF:
/* The only case we handle here is a simple discriminant reference. */ /* The only case we handle here is a simple discriminant reference. */
...@@ -7339,7 +7321,6 @@ annotate_value (tree gnu_size) ...@@ -7339,7 +7321,6 @@ annotate_value (tree gnu_size)
case TRUTH_OR_EXPR: tcode = Truth_Or_Expr; break; case TRUTH_OR_EXPR: tcode = Truth_Or_Expr; break;
case TRUTH_XOR_EXPR: tcode = Truth_Xor_Expr; break; case TRUTH_XOR_EXPR: tcode = Truth_Xor_Expr; break;
case TRUTH_NOT_EXPR: tcode = Truth_Not_Expr; break; case TRUTH_NOT_EXPR: tcode = Truth_Not_Expr; break;
case BIT_AND_EXPR: tcode = Bit_And_Expr; break;
case LT_EXPR: tcode = Lt_Expr; break; case LT_EXPR: tcode = Lt_Expr; break;
case LE_EXPR: tcode = Le_Expr; break; case LE_EXPR: tcode = Le_Expr; break;
case GT_EXPR: tcode = Gt_Expr; break; case GT_EXPR: tcode = Gt_Expr; break;
...@@ -7347,6 +7328,24 @@ annotate_value (tree gnu_size) ...@@ -7347,6 +7328,24 @@ annotate_value (tree gnu_size)
case EQ_EXPR: tcode = Eq_Expr; break; case EQ_EXPR: tcode = Eq_Expr; break;
case NE_EXPR: tcode = Ne_Expr; break; case NE_EXPR: tcode = Ne_Expr; break;
case BIT_AND_EXPR:
tcode = Bit_And_Expr;
/* For negative values, build NEGATE_EXPR of the opposite. Such values
appear in expressions containing aligning patterns. Note that, since
sizetype is unsigned, we have to jump through some hoops. */
if (TREE_CODE (TREE_OPERAND (gnu_size, 1)) == INTEGER_CST)
{
tree op1 = TREE_OPERAND (gnu_size, 1);
double_int signed_op1
= tree_to_double_int (op1).sext (TYPE_PRECISION (sizetype));
if (signed_op1.is_negative ())
{
op1 = double_int_to_tree (sizetype, -signed_op1);
pre_op1 = annotate_value (build1 (NEGATE_EXPR, sizetype, op1));
}
}
break;
case CALL_EXPR: case CALL_EXPR:
{ {
tree t = maybe_inline_call_in_expr (gnu_size); tree t = maybe_inline_call_in_expr (gnu_size);
...@@ -7367,6 +7366,9 @@ annotate_value (tree gnu_size) ...@@ -7367,6 +7366,9 @@ annotate_value (tree gnu_size)
for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (gnu_size)); i++) for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (gnu_size)); i++)
{ {
if (i == 1 && pre_op1 != No_Uint)
ops[i] = pre_op1;
else
ops[i] = annotate_value (TREE_OPERAND (gnu_size, i)); ops[i] = annotate_value (TREE_OPERAND (gnu_size, i));
if (ops[i] == No_Uint) if (ops[i] == No_Uint)
return No_Uint; return No_Uint;
......
...@@ -604,8 +604,8 @@ gnat_get_subrange_bounds (const_tree gnu_type, tree *lowval, tree *highval) ...@@ -604,8 +604,8 @@ gnat_get_subrange_bounds (const_tree gnu_type, tree *lowval, tree *highval)
bool bool
default_pass_by_ref (tree gnu_type) default_pass_by_ref (tree gnu_type)
{ {
/* We pass aggregates by reference if they are sufficiently large. The /* We pass aggregates by reference if they are sufficiently large for
choice of constant here is somewhat arbitrary. We also pass by their alignment. The ratio is somewhat arbitrary. We also pass by
reference if the target machine would either pass or return by reference if the target machine would either pass or return by
reference. Strictly speaking, we need only check the return if this reference. Strictly speaking, we need only check the return if this
is an In Out parameter, but it's probably best to err on the side of is an In Out parameter, but it's probably best to err on the side of
...@@ -618,9 +618,9 @@ default_pass_by_ref (tree gnu_type) ...@@ -618,9 +618,9 @@ default_pass_by_ref (tree gnu_type)
return true; return true;
if (AGGREGATE_TYPE_P (gnu_type) if (AGGREGATE_TYPE_P (gnu_type)
&& (!host_integerp (TYPE_SIZE (gnu_type), 1) && (!valid_constant_size_p (TYPE_SIZE_UNIT (gnu_type))
|| 0 < compare_tree_int (TYPE_SIZE (gnu_type), || 0 < compare_tree_int (TYPE_SIZE_UNIT (gnu_type),
8 * TYPE_ALIGN (gnu_type)))) TYPE_ALIGN (gnu_type))))
return true; return true;
return false; return false;
...@@ -639,8 +639,8 @@ must_pass_by_ref (tree gnu_type) ...@@ -639,8 +639,8 @@ must_pass_by_ref (tree gnu_type)
not have such objects. */ not have such objects. */
return (TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE return (TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE
|| TYPE_IS_BY_REFERENCE_P (gnu_type) || TYPE_IS_BY_REFERENCE_P (gnu_type)
|| (TYPE_SIZE (gnu_type) || (TYPE_SIZE_UNIT (gnu_type)
&& TREE_CODE (TYPE_SIZE (gnu_type)) != INTEGER_CST)); && TREE_CODE (TYPE_SIZE_UNIT (gnu_type)) != INTEGER_CST));
} }
/* This function is called by the front-end to enumerate all the supported /* This function is called by the front-end to enumerate all the supported
......
...@@ -6115,7 +6115,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6115,7 +6115,7 @@ gnat_to_gnu (Node_Id gnat_node)
/* If the type has a size that overflows, convert this into raise of /* If the type has a size that overflows, convert this into raise of
Storage_Error: execution shouldn't have gotten here anyway. */ Storage_Error: execution shouldn't have gotten here anyway. */
if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (gnu_lhs))) == INTEGER_CST if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (gnu_lhs))) == INTEGER_CST
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (TREE_TYPE (gnu_lhs)))) && !valid_constant_size_p (TYPE_SIZE_UNIT (TREE_TYPE (gnu_lhs))))
gnu_result = build_call_raise (SE_Object_Too_Large, gnat_node, gnu_result = build_call_raise (SE_Object_Too_Large, gnat_node,
N_Raise_Storage_Error); N_Raise_Storage_Error);
else if (Nkind (Expression (gnat_node)) == N_Function_Call) else if (Nkind (Expression (gnat_node)) == N_Function_Call)
......
...@@ -3024,59 +3024,67 @@ max_size (tree exp, bool max_p) ...@@ -3024,59 +3024,67 @@ max_size (tree exp, bool max_p)
return max_p ? size_one_node : size_zero_node; return max_p ? size_one_node : size_zero_node;
case tcc_unary: case tcc_unary:
case tcc_binary: if (code == NON_LVALUE_EXPR)
case tcc_expression:
switch (TREE_CODE_LENGTH (code))
{
case 1:
if (code == SAVE_EXPR)
return exp;
else if (code == NON_LVALUE_EXPR)
return max_size (TREE_OPERAND (exp, 0), max_p); return max_size (TREE_OPERAND (exp, 0), max_p);
else
return return fold_build1 (code, type,
fold_build1 (code, type,
max_size (TREE_OPERAND (exp, 0), max_size (TREE_OPERAND (exp, 0),
code == NEGATE_EXPR ? !max_p : max_p)); code == NEGATE_EXPR ? !max_p : max_p));
case 2: case tcc_binary:
if (code == COMPOUND_EXPR)
return max_size (TREE_OPERAND (exp, 1), max_p);
{ {
tree lhs = max_size (TREE_OPERAND (exp, 0), max_p); tree lhs = max_size (TREE_OPERAND (exp, 0), max_p);
tree rhs = max_size (TREE_OPERAND (exp, 1), tree rhs = max_size (TREE_OPERAND (exp, 1),
code == MINUS_EXPR ? !max_p : max_p); code == MINUS_EXPR ? !max_p : max_p);
/* Special-case wanting the maximum value of a MIN_EXPR. /* Special-case wanting the maximum value of a MIN_EXPR.
In that case, if one side overflows, return the other. In that case, if one side overflows, return the other. */
sizetype is signed, but we know sizes are non-negative. if (max_p && code == MIN_EXPR)
Likewise, handle a MINUS_EXPR or PLUS_EXPR with the LHS {
overflowing and the RHS a variable. */ if (TREE_CODE (rhs) == INTEGER_CST && TREE_OVERFLOW (rhs))
if (max_p
&& code == MIN_EXPR
&& TREE_CODE (rhs) == INTEGER_CST
&& TREE_OVERFLOW (rhs))
return lhs; return lhs;
else if (max_p
&& code == MIN_EXPR if (TREE_CODE (lhs) == INTEGER_CST && TREE_OVERFLOW (lhs))
&& TREE_CODE (lhs) == INTEGER_CST
&& TREE_OVERFLOW (lhs))
return rhs; return rhs;
else if ((code == MINUS_EXPR || code == PLUS_EXPR) }
/* Likewise, handle a MINUS_EXPR or PLUS_EXPR with the LHS
overflowing and the RHS a variable. */
if ((code == MINUS_EXPR || code == PLUS_EXPR)
&& TREE_CODE (lhs) == INTEGER_CST && TREE_CODE (lhs) == INTEGER_CST
&& TREE_OVERFLOW (lhs) && TREE_OVERFLOW (lhs)
&& !TREE_CONSTANT (rhs)) && !TREE_CONSTANT (rhs))
return lhs; return lhs;
else
return fold_build2 (code, type, lhs, rhs); return size_binop (code, lhs, rhs);
} }
case tcc_expression:
switch (TREE_CODE_LENGTH (code))
{
case 1:
if (code == SAVE_EXPR)
return exp;
return fold_build1 (code, type,
max_size (TREE_OPERAND (exp, 0), max_p));
case 2:
if (code == COMPOUND_EXPR)
return max_size (TREE_OPERAND (exp, 1), max_p);
return fold_build2 (code, type,
max_size (TREE_OPERAND (exp, 0), max_p),
max_size (TREE_OPERAND (exp, 1), max_p));
case 3: case 3:
if (code == COND_EXPR) if (code == COND_EXPR)
return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type, return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
max_size (TREE_OPERAND (exp, 1), max_p), max_size (TREE_OPERAND (exp, 1), max_p),
max_size (TREE_OPERAND (exp, 2), max_p)); max_size (TREE_OPERAND (exp, 2), max_p));
default:
break;
} }
/* Other tree classes cannot happen. */ /* Other tree classes cannot happen. */
......
...@@ -2286,7 +2286,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, ...@@ -2286,7 +2286,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
init); init);
/* If the size overflows, pass -1 so Storage_Error will be raised. */ /* If the size overflows, pass -1 so Storage_Error will be raised. */
if (TREE_CODE (size) == INTEGER_CST && TREE_OVERFLOW (size)) if (TREE_CODE (size) == INTEGER_CST && !valid_constant_size_p (size))
size = size_int (-1); size = size_int (-1);
storage = build_call_alloc_dealloc (NULL_TREE, size, storage_type, storage = build_call_alloc_dealloc (NULL_TREE, size, storage_type,
...@@ -2345,7 +2345,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, ...@@ -2345,7 +2345,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
} }
/* If the size overflows, pass -1 so Storage_Error will be raised. */ /* If the size overflows, pass -1 so Storage_Error will be raised. */
if (TREE_CODE (size) == INTEGER_CST && TREE_OVERFLOW (size)) if (TREE_CODE (size) == INTEGER_CST && !valid_constant_size_p (size))
size = size_int (-1); size = size_int (-1);
storage = convert (result_type, storage = convert (result_type,
......
...@@ -2233,12 +2233,12 @@ layout_type (tree type) ...@@ -2233,12 +2233,12 @@ layout_type (tree type)
size_binop (MINUS_EXPR, ub, lb))); size_binop (MINUS_EXPR, ub, lb)));
} }
/* If we arrived at a length of zero ignore any overflow /* ??? We have no way to distinguish a null-sized array from an
that occurred as part of the calculation. There exists array spanning the whole sizetype range, so we arbitrarily
an association of the plus one where that overflow would decide that [0, -1] is the only valid representation. */
not happen. */
if (integer_zerop (length) if (integer_zerop (length)
&& TREE_OVERFLOW (length)) && TREE_OVERFLOW (length)
&& integer_zerop (lb))
length = size_zero_node; length = size_zero_node;
TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size, TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
......
2012-11-28 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/object_overflow.adb: Rename to...
* gnat.dg/object_overflow1.adb: ...this.
* gnat.dg/object_overflow2.adb: New test.
* gnat.dg/object_overflow3.adb: Likewise.
* gnat.dg/object_overflow4.adb: Likewise.
2012-11-28 Paolo Carlini <paolo.carlini@oracle.com> 2012-11-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/55497 PR c++/55497
......
-- { dg-do compile } -- { dg-do compile }
procedure Object_Overflow is procedure Object_Overflow1 is
procedure Proc (x : Boolean) is begin null; end; procedure Proc (x : Boolean) is begin null; end;
......
-- { dg-do compile }
procedure Object_Overflow2 is
procedure Proc (x : Boolean) is begin null; end;
type Arr is array(0 .. Long_Integer'Last) of Boolean;
Obj : Arr; -- { dg-warning "Storage_Error" }
begin
Obj(1) := True;
Proc (Obj(1));
end;
-- { dg-do compile }
procedure Object_Overflow3 is
procedure Proc (x : Boolean) is begin null; end;
type Arr is array(0 .. Long_Integer'Last) of Boolean;
type Rec is record
A : Arr;
B : Arr;
end record;
Obj : Rec; -- { dg-warning "Storage_Error" }
begin
Obj.A(1) := True;
Proc (Obj.A(1));
end;
-- { dg-do compile }
procedure Object_Overflow4 is
procedure Proc (x : Integer) is begin null; end;
type Index is new Long_Integer range 0 .. Long_Integer'Last;
type Arr is array(Index range <>) of Integer;
type Rec (Size: Index := 6) is record -- { dg-warning "Storage_Error" }
A: Arr (0..Size);
end record;
Obj : Rec; -- { dg-warning "Storage_Error" }
begin
Obj.A(1) := 0;
Proc (Obj.A(1));
end;
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