static tree build_unary_op_trapv (enum tree_code, tree, tree, Node_Id);
static tree build_binary_op_trapv (enum tree_code, tree, tree, tree, Node_Id);
static tree convert_with_check (Entity_Id, tree, bool, bool, Node_Id);
-static bool addressable_p (tree, tree);
+static bool addressable_p (tree, tree, bool);
static bool aliasable_p (tree, tree);
static tree assoc_to_constructor (Entity_Id, Node_Id, tree);
static tree pos_to_constructor (Node_Id, tree);
tree gnu_formal = present_gnu_tree (gnat_formal)
? get_gnu_tree (gnat_formal) : NULL_TREE;
tree gnu_actual_type = gnat_to_gnu_type (Etype (gnat_actual));
+ const bool is_init_proc
+ = Is_Entity_Name (gnat_subprog) && Is_Init_Proc (Entity (gnat_subprog));
const bool in_param = (Ekind (gnat_formal) == E_In_Parameter);
const bool is_true_formal_parm
= gnu_formal && TREE_CODE (gnu_formal) == PARM_DECL;
copy to avoid breaking strict aliasing rules. */
if (is_by_ref_formal_parm
&& (gnu_name_type = gnat_to_gnu_type (Etype (gnat_name)))
- && (!addressable_p (gnu_name, gnu_name_type)
+ && (!addressable_p (gnu_name, gnu_name_type, is_init_proc)
|| (node_is_type_conversion (gnat_actual)
&& (aliasing = !aliasable_p (gnu_name, gnu_actual_type)))))
{
/* Do not initialize it for the _Init parameter of an initialization
procedure since no data is meant to be passed in. */
- if (Ekind (gnat_formal) == E_Out_Parameter
- && Is_Entity_Name (gnat_subprog)
- && Is_Init_Proc (Entity (gnat_subprog)))
+ if (Ekind (gnat_formal) == E_Out_Parameter && is_init_proc)
gnu_name = gnu_temp = create_temporary ("A", TREE_TYPE (gnu_name));
/* Initialize it on the fly like for an implicit temporary in the
unless it is an expression involving computation or if it involves a
reference to a bitfield or to an object not sufficiently aligned for
its type. If GNU_TYPE is non-null, return true only if GNU_EXPR can
- be directly addressed as an object of this type.
+ be directly addressed as an object of this type. COMPG is true when
+ the predicate is invoked for compiler-generated code.
*** Notes on addressability issues in the Ada compiler ***
generated to connect everything together. */
static bool
-addressable_p (tree gnu_expr, tree gnu_type)
+addressable_p (tree gnu_expr, tree gnu_type, bool compg)
{
/* For an integral type, the size of the actual type of the object may not
be greater than that of the expected type, otherwise an indirect access
case COMPOUND_EXPR:
/* The address of a compound expression is that of its 2nd operand. */
- return addressable_p (TREE_OPERAND (gnu_expr, 1), gnu_type);
+ return addressable_p (TREE_OPERAND (gnu_expr, 1), gnu_type, compg);
case COND_EXPR:
/* We accept &COND_EXPR as soon as both operands are addressable and
expect the outcome to be the address of the selected operand. */
- return (addressable_p (TREE_OPERAND (gnu_expr, 1), NULL_TREE)
- && addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE));
+ return (addressable_p (TREE_OPERAND (gnu_expr, 1), NULL_TREE, compg)
+ && addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE, compg));
case COMPONENT_REF:
return (((!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
&& (DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
>= default_field_alignment (TREE_OPERAND (gnu_expr, 1),
TREE_TYPE (gnu_expr))
- /* We do not enforce this on strict-alignment platforms for
- internal fields in order to keep supporting misalignment
- of tagged types in legacy code. */
+ /* But this was historically not enforced for targets that
+ do not require strict alignment, so we keep not doing
+ it for 1) internal fields in order to keep supporting
+ misalignment of tagged types and 2) compiler-generated
+ code in order to avoid creating useless temporaries. */
|| (!STRICT_ALIGNMENT
- && DECL_INTERNAL_P (TREE_OPERAND (gnu_expr, 1)))))
+ && (DECL_INTERNAL_P (TREE_OPERAND (gnu_expr, 1))
+ || compg))))
/* The field of a padding record is always addressable. */
|| TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))))
- && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
+ && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE, compg));
case ARRAY_REF: case ARRAY_RANGE_REF:
case REALPART_EXPR: case IMAGPART_EXPR:
case NOP_EXPR:
- return addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE);
+ return addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE, compg);
case CONVERT_EXPR:
return (AGGREGATE_TYPE_P (TREE_TYPE (gnu_expr))
- && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
+ && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE, compg));
case VIEW_CONVERT_EXPR:
{
|| TYPE_ALIGN (inner_type) >= BIGGEST_ALIGNMENT
|| TYPE_ALIGN_OK (type)
|| TYPE_ALIGN_OK (inner_type))))
- && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
+ && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE,
+ compg));
}
default: