decl.c (gnat_to_gnu_entity): If -gnatd.a and not optimizing alignment for space...
* decl.c (gnat_to_gnu_entity) <object>: If -gnatd.a and not optimizing alignment for space, promote the alignment of non-scalar variables with no size and alignment. * gigi.h (gnat_types_compatible_p): Declare. * misc.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Set to above predicate. * trans.c (gnat_to_gnu): Revert revision 129339 change. Minor cleanup. * utils.c (gnat_types_compatible_p) : New predicate. (convert): Use it throughout to test for cases where a mere view conversion is sufficient. * utils2.c (build_binary_op): Minor tweaks. (build_unary_op): Likewise. From-SVN: r134092
This commit is contained in:
parent
373140ef74
commit
ba3f46d091
|
@ -1,3 +1,17 @@
|
|||
2008-04-08 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* decl.c (gnat_to_gnu_entity) <object>: If -gnatd.a and not optimizing
|
||||
alignment for space, promote the alignment of non-scalar variables with
|
||||
no size and alignment.
|
||||
* gigi.h (gnat_types_compatible_p): Declare.
|
||||
* misc.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Set to above predicate.
|
||||
* trans.c (gnat_to_gnu): Revert revision 129339 change. Minor cleanup.
|
||||
* utils.c (gnat_types_compatible_p) : New predicate.
|
||||
(convert): Use it throughout to test for cases where a mere view
|
||||
conversion is sufficient.
|
||||
* utils2.c (build_binary_op): Minor tweaks.
|
||||
(build_unary_op): Likewise.
|
||||
|
||||
2008-04-08 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* decl.c (adjust_packed): Expand comment.
|
||||
|
|
|
@ -672,19 +672,42 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|
|||
&& !Present (Address_Clause (gnat_entity)))
|
||||
gnu_size = bitsize_unit_node;
|
||||
|
||||
/* If this is an atomic object with no specified size and alignment,
|
||||
but where the size of the type is a constant, set the alignment to
|
||||
the smallest not less than the size, or to the biggest meaningful
|
||||
alignment, whichever is smaller. */
|
||||
if (Is_Atomic (gnat_entity) && !gnu_size && align == 0
|
||||
/* If this is an object with no specified size and alignment, and if
|
||||
either it is atomic or we are not optimizing alignment for space
|
||||
and it is a non-scalar variable, and the size of its type is a
|
||||
constant, set the alignment to the smallest not less than the
|
||||
size, or to the biggest meaningful one, whichever is smaller. */
|
||||
if (!gnu_size && align == 0
|
||||
&& (Is_Atomic (gnat_entity)
|
||||
|| (Debug_Flag_Dot_A
|
||||
&& !Optimize_Alignment_Space (gnat_entity)
|
||||
&& kind == E_Variable
|
||||
&& AGGREGATE_TYPE_P (gnu_type)
|
||||
&& !const_flag && No (Renamed_Object (gnat_entity))
|
||||
&& !imported_p && No (Address_Clause (gnat_entity))))
|
||||
&& TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST)
|
||||
{
|
||||
/* No point in jumping through all the hoops needed in order
|
||||
to support BIGGEST_ALIGNMENT if we don't really have to. */
|
||||
unsigned int align_cap = Is_Atomic (gnat_entity)
|
||||
? BIGGEST_ALIGNMENT
|
||||
: MAX_FIXED_MODE_SIZE;
|
||||
|
||||
if (!host_integerp (TYPE_SIZE (gnu_type), 1)
|
||||
|| 0 <= compare_tree_int (TYPE_SIZE (gnu_type),
|
||||
BIGGEST_ALIGNMENT))
|
||||
align = BIGGEST_ALIGNMENT;
|
||||
|| compare_tree_int (TYPE_SIZE (gnu_type), align_cap) >= 0)
|
||||
align = align_cap;
|
||||
else
|
||||
align = ceil_alignment (tree_low_cst (TYPE_SIZE (gnu_type), 1));
|
||||
|
||||
/* But make sure not to under-align the object. */
|
||||
if (align < TYPE_ALIGN (gnu_type))
|
||||
align = TYPE_ALIGN (gnu_type);
|
||||
|
||||
/* And honor the minimum valid atomic alignment, if any. */
|
||||
#ifdef MINIMUM_ATOMIC_ALIGNMENT
|
||||
if (align < MINIMUM_ATOMIC_ALIGNMENT)
|
||||
align = MINIMUM_ATOMIC_ALIGNMENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If the object is set to have atomic components, find the component
|
||||
|
|
|
@ -468,6 +468,10 @@ extern tree gnat_unsigned_type (tree type_node);
|
|||
/* Return the signed version of a TYPE_NODE, a scalar type. */
|
||||
extern tree gnat_signed_type (tree type_node);
|
||||
|
||||
/* Return 1 if the types T1 and T2 are compatible, i.e. if they can be
|
||||
transparently converted to each other. */
|
||||
extern int gnat_types_compatible_p (tree t1, tree t2);
|
||||
|
||||
/* Create an expression whose value is that of EXPR,
|
||||
converted to type TYPE. The TREE_TYPE of the value
|
||||
is always TYPE. This function implements all reasonable
|
||||
|
|
|
@ -151,6 +151,8 @@ static tree gnat_type_max_size (const_tree);
|
|||
#define LANG_HOOKS_TYPE_FOR_MODE gnat_type_for_mode
|
||||
#undef LANG_HOOKS_TYPE_FOR_SIZE
|
||||
#define LANG_HOOKS_TYPE_FOR_SIZE gnat_type_for_size
|
||||
#undef LANG_HOOKS_TYPES_COMPATIBLE_P
|
||||
#define LANG_HOOKS_TYPES_COMPATIBLE_P gnat_types_compatible_p
|
||||
#undef LANG_HOOKS_ATTRIBUTE_TABLE
|
||||
#define LANG_HOOKS_ATTRIBUTE_TABLE gnat_internal_attribute_table
|
||||
#undef LANG_HOOKS_BUILTIN_FUNCTION
|
||||
|
|
|
@ -4832,34 +4832,41 @@ gnat_to_gnu (Node_Id gnat_node)
|
|||
|| CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))))
|
||||
gnu_result = gnat_stabilize_reference (gnu_result, false);
|
||||
|
||||
/* Now convert the result to the proper type. If the type is void or if
|
||||
we have no result, return error_mark_node to show we have no result.
|
||||
If the type of the result is correct or if we have a label (which doesn't
|
||||
have any well-defined type), return our result. Also don't do the
|
||||
conversion if the "desired" type involves a PLACEHOLDER_EXPR in its size
|
||||
since those are the cases where the front end may have the type wrong due
|
||||
to "instantiating" the unconstrained record with discriminant values
|
||||
or if this is a FIELD_DECL. If this is the Name of an assignment
|
||||
statement or a parameter of a procedure call, return what we have since
|
||||
the RHS has to be converted to our type there in that case, unless
|
||||
GNU_RESULT_TYPE has a simpler size. Similarly, if the two types are
|
||||
record types with the same name and GNU_RESULT_TYPE has BLKmode, don't
|
||||
convert. This will be the case when we are converting from a packable
|
||||
type to its actual type and we need those conversions to be NOPs in
|
||||
order for assignments into these types to work properly. Finally,
|
||||
don't convert integral types that are the operand of an unchecked
|
||||
conversion since we need to ignore those conversions (for 'Valid).
|
||||
Otherwise, convert the result to the proper type. */
|
||||
/* Now convert the result to the result type, unless we are in one of the
|
||||
following cases:
|
||||
|
||||
1. If this is the Name of an assignment statement or a parameter of
|
||||
a procedure call, return the result almost unmodified since the
|
||||
RHS will have to be converted to our type in that case, unless
|
||||
the result type has a simpler size. Similarly, don't convert
|
||||
integral types that are the operands of an unchecked conversion
|
||||
since we need to ignore those conversions (for 'Valid).
|
||||
|
||||
2. If we have a label (which doesn't have any well-defined type), a
|
||||
field or an error, return the result almost unmodified. Also don't
|
||||
do the conversion if the result type involves a PLACEHOLDER_EXPR in
|
||||
its size since those are the cases where the front end may have the
|
||||
type wrong due to "instantiating" the unconstrained record with
|
||||
discriminant values. Similarly, if the two types are record types
|
||||
with the same name and the result type has BLKmode, don't convert.
|
||||
This will be the case when we are converting from a packed version
|
||||
of a type to its original type and we need those conversions to be
|
||||
NOPs in order for assignments into these types to work properly.
|
||||
|
||||
3. If the type is void or if we have no result, return error_mark_node
|
||||
to show we have no result.
|
||||
|
||||
4. Finally, if the type of the result is already correct. */
|
||||
|
||||
if (Present (Parent (gnat_node))
|
||||
&& ((Nkind (Parent (gnat_node)) == N_Assignment_Statement
|
||||
&& Name (Parent (gnat_node)) == gnat_node)
|
||||
|| (Nkind (Parent (gnat_node)) == N_Procedure_Call_Statement
|
||||
&& Name (Parent (gnat_node)) != gnat_node)
|
||||
|| Nkind (Parent (gnat_node)) == N_Parameter_Association
|
||||
|| (Nkind (Parent (gnat_node)) == N_Unchecked_Type_Conversion
|
||||
&& !AGGREGATE_TYPE_P (gnu_result_type)
|
||||
&& !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result)))
|
||||
|| Nkind (Parent (gnat_node)) == N_Parameter_Association)
|
||||
&& !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result))))
|
||||
&& !(TYPE_SIZE (gnu_result_type)
|
||||
&& TYPE_SIZE (TREE_TYPE (gnu_result))
|
||||
&& (AGGREGATE_TYPE_P (gnu_result_type)
|
||||
|
@ -4874,16 +4881,14 @@ gnat_to_gnu (Node_Id gnat_node)
|
|||
&& !(TREE_CODE (gnu_result_type) == RECORD_TYPE
|
||||
&& TYPE_JUSTIFIED_MODULAR_P (gnu_result_type))))
|
||||
{
|
||||
/* In this case remove padding only if the inner object type is the
|
||||
same as gnu_result_type or is of self-referential size (in that later
|
||||
case it must be an object of unconstrained type with a default
|
||||
discriminant). We want to avoid copying too much data. */
|
||||
/* Remove padding only if the inner object is of self-referential
|
||||
size: in that case it must be an object of unconstrained type
|
||||
with a default discriminant and we want to avoid copying too
|
||||
much data. */
|
||||
if (TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P (TREE_TYPE (gnu_result))
|
||||
&& (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result)))
|
||||
== gnu_result_type
|
||||
|| CONTAINS_PLACEHOLDER_P (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS
|
||||
(TREE_TYPE (gnu_result)))))))
|
||||
&& CONTAINS_PLACEHOLDER_P (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS
|
||||
(TREE_TYPE (gnu_result))))))
|
||||
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
|
||||
gnu_result);
|
||||
}
|
||||
|
@ -4901,20 +4906,20 @@ gnat_to_gnu (Node_Id gnat_node)
|
|||
&& TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
|
||||
&& TYPE_MODE (gnu_result_type) == BLKmode))
|
||||
{
|
||||
/* Remove any padding record, but do nothing more in this case. */
|
||||
/* Remove any padding. */
|
||||
if (TREE_CODE (TREE_TYPE (gnu_result)) == RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P (TREE_TYPE (gnu_result)))
|
||||
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
|
||||
gnu_result);
|
||||
}
|
||||
|
||||
else if (gnu_result == error_mark_node
|
||||
|| gnu_result_type == void_type_node)
|
||||
gnu_result = error_mark_node;
|
||||
else if (gnu_result == error_mark_node || gnu_result_type == void_type_node)
|
||||
gnu_result = error_mark_node;
|
||||
|
||||
else if (gnu_result_type != TREE_TYPE (gnu_result))
|
||||
gnu_result = convert (gnu_result_type, gnu_result);
|
||||
|
||||
/* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RESULT. */
|
||||
/* We don't need any NOP_EXPR or NON_LVALUE_EXPR on the result. */
|
||||
while ((TREE_CODE (gnu_result) == NOP_EXPR
|
||||
|| TREE_CODE (gnu_result) == NON_LVALUE_EXPR)
|
||||
&& TREE_TYPE (TREE_OPERAND (gnu_result, 0)) == TREE_TYPE (gnu_result))
|
||||
|
|
|
@ -2378,6 +2378,42 @@ gnat_signed_type (tree type_node)
|
|||
return type;
|
||||
}
|
||||
|
||||
/* Return 1 if the types T1 and T2 are compatible, i.e. if they can be
|
||||
transparently converted to each other. */
|
||||
|
||||
int
|
||||
gnat_types_compatible_p (tree t1, tree t2)
|
||||
{
|
||||
enum tree_code code;
|
||||
|
||||
/* This is the default criterion. */
|
||||
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
|
||||
return 1;
|
||||
|
||||
/* We only check structural equivalence here. */
|
||||
if ((code = TREE_CODE (t1)) != TREE_CODE (t2))
|
||||
return 0;
|
||||
|
||||
/* Array types are also compatible if they are constrained and have
|
||||
the same component type and the same domain. */
|
||||
if (code == ARRAY_TYPE
|
||||
&& TREE_TYPE (t1) == TREE_TYPE (t2)
|
||||
&& tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (t1)),
|
||||
TYPE_MIN_VALUE (TYPE_DOMAIN (t2)))
|
||||
&& tree_int_cst_equal (TYPE_MAX_VALUE (TYPE_DOMAIN (t1)),
|
||||
TYPE_MAX_VALUE (TYPE_DOMAIN (t2))))
|
||||
return 1;
|
||||
|
||||
/* Padding record types are also compatible if they pad the same
|
||||
type and have the same constant size. */
|
||||
if (code == RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P (t1) && TYPE_IS_PADDING_P (t2)
|
||||
&& TREE_TYPE (TYPE_FIELDS (t1)) == TREE_TYPE (TYPE_FIELDS (t2))
|
||||
&& tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EXP is an expression for the size of an object. If this size contains
|
||||
discriminant references, replace them with the maximum (if MAX_P) or
|
||||
|
@ -3368,15 +3404,15 @@ convert (tree type, tree expr)
|
|||
/* If both input and output have padding and are of variable size, do this
|
||||
as an unchecked conversion. Likewise if one is a mere variant of the
|
||||
other, so we avoid a pointless unpad/repad sequence. */
|
||||
else if (ecode == RECORD_TYPE && code == RECORD_TYPE
|
||||
else if (code == RECORD_TYPE && ecode == RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P (type) && TYPE_IS_PADDING_P (etype)
|
||||
&& (!TREE_CONSTANT (TYPE_SIZE (type))
|
||||
|| !TREE_CONSTANT (TYPE_SIZE (etype))
|
||||
|| TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype)))
|
||||
|| gnat_types_compatible_p (type, etype)))
|
||||
;
|
||||
|
||||
/* If the output type has padding, make a constructor to build the
|
||||
record. */
|
||||
/* If the output type has padding, convert to the inner type and
|
||||
make a constructor to build the record. */
|
||||
else if (code == RECORD_TYPE && TYPE_IS_PADDING_P (type))
|
||||
{
|
||||
/* If we previously converted from another type and our type is
|
||||
|
@ -3387,12 +3423,15 @@ convert (tree type, tree expr)
|
|||
expr = TREE_OPERAND (expr, 0);
|
||||
|
||||
/* If we are just removing the padding from expr, convert the original
|
||||
object if we have variable size. That will avoid the need
|
||||
for some variable-size temporaries. */
|
||||
object if we have variable size in order to avoid the need for some
|
||||
variable-size temporaries. Likewise if the padding is a mere variant
|
||||
of the other, so we avoid a pointless unpad/repad sequence. */
|
||||
if (TREE_CODE (expr) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
|
||||
&& !TREE_CONSTANT (TYPE_SIZE (type)))
|
||||
&& (!TREE_CONSTANT (TYPE_SIZE (type))
|
||||
|| gnat_types_compatible_p (type,
|
||||
TREE_TYPE (TREE_OPERAND (expr, 0)))))
|
||||
return convert (type, TREE_OPERAND (expr, 0));
|
||||
|
||||
/* If the result type is a padded type with a self-referentially-sized
|
||||
|
@ -3506,14 +3545,9 @@ convert (tree type, tree expr)
|
|||
break;
|
||||
|
||||
case CONSTRUCTOR:
|
||||
/* If we are converting a CONSTRUCTOR to another constrained array type
|
||||
with the same domain, just make a new one in the proper type. */
|
||||
if (code == ecode && code == ARRAY_TYPE
|
||||
&& TREE_TYPE (type) == TREE_TYPE (etype)
|
||||
&& tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
|
||||
TYPE_MIN_VALUE (TYPE_DOMAIN (etype)))
|
||||
&& tree_int_cst_equal (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
|
||||
TYPE_MAX_VALUE (TYPE_DOMAIN (etype))))
|
||||
/* If we are converting a CONSTRUCTOR to a mere variant type, just make
|
||||
a new one in the proper type. */
|
||||
if (gnat_types_compatible_p (type, etype))
|
||||
{
|
||||
expr = copy_node (expr);
|
||||
TREE_TYPE (expr) = type;
|
||||
|
@ -3539,7 +3573,6 @@ convert (tree type, tree expr)
|
|||
the inner operand to the output type is fine in most cases, it
|
||||
might expose unexpected input/output type mismatches in special
|
||||
circumstances so we avoid such recursive calls when we can. */
|
||||
|
||||
tree op0 = TREE_OPERAND (expr, 0);
|
||||
|
||||
/* If we are converting back to the original type, we can just
|
||||
|
@ -3549,13 +3582,13 @@ convert (tree type, tree expr)
|
|||
return op0;
|
||||
|
||||
/* Otherwise, if we're converting between two aggregate types, we
|
||||
might be allowed to substitute the VIEW_CONVERT target type in
|
||||
place or to just convert the inner expression. */
|
||||
might be allowed to substitute the VIEW_CONVERT_EXPR target type
|
||||
in place or to just convert the inner expression. */
|
||||
if (AGGREGATE_TYPE_P (type) && AGGREGATE_TYPE_P (etype))
|
||||
{
|
||||
/* If we are converting between type variants, we can just
|
||||
substitute the VIEW_CONVERT in place. */
|
||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype))
|
||||
/* If we are converting between mere variants, we can just
|
||||
substitute the VIEW_CONVERT_EXPR in place. */
|
||||
if (gnat_types_compatible_p (type, etype))
|
||||
return build1 (VIEW_CONVERT_EXPR, type, op0);
|
||||
|
||||
/* Otherwise, we may just bypass the input view conversion unless
|
||||
|
@ -3594,10 +3627,10 @@ convert (tree type, tree expr)
|
|||
if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype))
|
||||
return convert_to_fat_pointer (type, expr);
|
||||
|
||||
/* If we're converting between two aggregate types that have the same main
|
||||
variant, just make a VIEW_CONVER_EXPR. */
|
||||
/* If we're converting between two aggregate types that are mere
|
||||
variants, just make a VIEW_CONVERT_EXPR. */
|
||||
else if (AGGREGATE_TYPE_P (type)
|
||||
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (etype))
|
||||
&& gnat_types_compatible_p (type, etype))
|
||||
return build1 (VIEW_CONVERT_EXPR, type, expr);
|
||||
|
||||
/* In all other cases of related types, make a NOP_EXPR. */
|
||||
|
|
|
@ -633,8 +633,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
|||
tree right_base_type = get_base_type (right_type);
|
||||
tree operation_type = result_type;
|
||||
tree best_type = NULL_TREE;
|
||||
tree modulus;
|
||||
tree result;
|
||||
tree modulus, result;
|
||||
bool has_side_effects = false;
|
||||
|
||||
if (operation_type
|
||||
|
@ -647,18 +646,19 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
|||
&& TYPE_EXTRA_SUBTYPE_P (operation_type))
|
||||
operation_type = get_base_type (operation_type);
|
||||
|
||||
modulus = (operation_type && TREE_CODE (operation_type) == INTEGER_TYPE
|
||||
modulus = (operation_type
|
||||
&& TREE_CODE (operation_type) == INTEGER_TYPE
|
||||
&& TYPE_MODULAR_P (operation_type)
|
||||
? TYPE_MODULUS (operation_type) : 0);
|
||||
? TYPE_MODULUS (operation_type) : NULL_TREE);
|
||||
|
||||
switch (op_code)
|
||||
{
|
||||
case MODIFY_EXPR:
|
||||
/* If there were any integral or pointer conversions on LHS, remove
|
||||
/* If there were integral or pointer conversions on the LHS, remove
|
||||
them; we'll be putting them back below if needed. Likewise for
|
||||
conversions between array and record types. But don't do this if
|
||||
the right operand is not BLKmode (for packed arrays)
|
||||
unless we are not changing the mode. */
|
||||
conversions between array and record types, except for justified
|
||||
modular types. But don't do this if the right operand is not
|
||||
BLKmode (for packed arrays) unless we are not changing the mode. */
|
||||
while ((TREE_CODE (left_operand) == CONVERT_EXPR
|
||||
|| TREE_CODE (left_operand) == NOP_EXPR
|
||||
|| TREE_CODE (left_operand) == VIEW_CONVERT_EXPR)
|
||||
|
@ -669,8 +669,6 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
|||
|| POINTER_TYPE_P (TREE_TYPE
|
||||
(TREE_OPERAND (left_operand, 0)))))
|
||||
|| (((TREE_CODE (left_type) == RECORD_TYPE
|
||||
/* Don't remove conversions to justified modular
|
||||
types. */
|
||||
&& !TYPE_JUSTIFIED_MODULAR_P (left_type))
|
||||
|| TREE_CODE (left_type) == ARRAY_TYPE)
|
||||
&& ((TREE_CODE (TREE_TYPE
|
||||
|
@ -692,8 +690,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
|||
if (!operation_type)
|
||||
operation_type = left_type;
|
||||
|
||||
/* If we are copying one array or record to another, find the best type
|
||||
to use. */
|
||||
/* Find the best type to use for copying between aggregate types. */
|
||||
if (((TREE_CODE (left_type) == ARRAY_TYPE
|
||||
&& TREE_CODE (right_type) == ARRAY_TYPE)
|
||||
|| (TREE_CODE (left_type) == RECORD_TYPE
|
||||
|
@ -709,11 +706,11 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
|||
|
||||
/* Ensure everything on the LHS is valid. If we have a field reference,
|
||||
strip anything that get_inner_reference can handle. Then remove any
|
||||
conversions with type types having the same code and mode. Mark
|
||||
conversions between types having the same code and mode. And mark
|
||||
VIEW_CONVERT_EXPRs with TREE_ADDRESSABLE. When done, we must have
|
||||
either an INDIRECT_REF or a decl. */
|
||||
either an INDIRECT_REF, a NULL_EXPR or a DECL node. */
|
||||
result = left_operand;
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
tree restype = TREE_TYPE (result);
|
||||
|
||||
|
@ -744,21 +741,21 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
|||
}
|
||||
|
||||
gcc_assert (TREE_CODE (result) == INDIRECT_REF
|
||||
|| TREE_CODE (result) == NULL_EXPR || DECL_P (result));
|
||||
|| TREE_CODE (result) == NULL_EXPR
|
||||
|| DECL_P (result));
|
||||
|
||||
/* Convert the right operand to the operation type unless
|
||||
it is either already of the correct type or if the type
|
||||
involves a placeholder, since the RHS may not have the same
|
||||
record type. */
|
||||
/* Convert the right operand to the operation type unless it is
|
||||
either already of the correct type or if the type involves a
|
||||
placeholder, since the RHS may not have the same record type. */
|
||||
if (operation_type != right_type
|
||||
&& (!CONTAINS_PLACEHOLDER_P (TYPE_SIZE (operation_type))))
|
||||
&& !CONTAINS_PLACEHOLDER_P (TYPE_SIZE (operation_type)))
|
||||
{
|
||||
right_operand = convert (operation_type, right_operand);
|
||||
right_type = operation_type;
|
||||
}
|
||||
|
||||
/* If the left operand is not the same type as the operation type,
|
||||
surround it in a VIEW_CONVERT_EXPR. */
|
||||
/* If the left operand is not of the same type as the operation
|
||||
type, wrap it up in a VIEW_CONVERT_EXPR. */
|
||||
if (left_type != operation_type)
|
||||
left_operand = unchecked_convert (operation_type, left_operand, false);
|
||||
|
||||
|
@ -1286,7 +1283,7 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
|
|||
tree modulus = ((operation_type
|
||||
&& TREE_CODE (operation_type) == INTEGER_TYPE
|
||||
&& TYPE_MODULAR_P (operation_type))
|
||||
? TYPE_MODULUS (operation_type) : 0);
|
||||
? TYPE_MODULUS (operation_type) : NULL_TREE);
|
||||
int mod_pow2 = modulus && integer_pow2p (modulus);
|
||||
|
||||
/* If this is a modular type, there are various possibilities
|
||||
|
|
Loading…
Reference in New Issue