Commit a1c7d797 by Eric Botcazou Committed by Eric Botcazou

ada-tree.h (DECL_CAN_NEVER_BE_NULL_P): New macro.

	* gcc-interface/ada-tree.h (DECL_CAN_NEVER_BE_NULL_P): New macro.
	* gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Set the flag.
	(gnat_to_gnu_param): Likewise.
	* gcc-interface/utils.c (convert) <UNCONSTRAINED_ARRAY_REF>: Invoke
	maybe_unconstrained_array instead of doing the work manually.
	(maybe_unconstrained_array): Propagate the TREE_THIS_NOTRAP flag.
	* gcc-interface/utils2.c (build_unary_op) <INDIRECT_REF>: If operand
	is a DECL with the flag, set TREE_THIS_NOTRAP on the reference.
	(gnat_stabilize_reference_1): Propagate the TREE_THIS_NOTRAP flag.
	(gnat_stabilize_reference): Likewise.

From-SVN: r179182
parent 20633efc
2011-09-26 Eric Botcazou <ebotcazou@adacore.com> 2011-09-26 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (DECL_CAN_NEVER_BE_NULL_P): New macro.
* gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Set the flag.
(gnat_to_gnu_param): Likewise.
* gcc-interface/utils.c (convert) <UNCONSTRAINED_ARRAY_REF>: Invoke
maybe_unconstrained_array instead of doing the work manually.
(maybe_unconstrained_array): Propagate the TREE_THIS_NOTRAP flag.
* gcc-interface/utils2.c (build_unary_op) <INDIRECT_REF>: If operand
is a DECL with the flag, set TREE_THIS_NOTRAP on the reference.
(gnat_stabilize_reference_1): Propagate the TREE_THIS_NOTRAP flag.
(gnat_stabilize_reference): Likewise.
2011-09-26 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (TYPE_NULL_BOUNDS): New macro. * gcc-interface/ada-tree.h (TYPE_NULL_BOUNDS): New macro.
(SET_TYPE_NULL_BOUNDS): Likewise. (SET_TYPE_NULL_BOUNDS): Likewise.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Set again * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Set again
......
...@@ -352,6 +352,9 @@ do { \ ...@@ -352,6 +352,9 @@ do { \
is needed to access the object. */ is needed to access the object. */
#define DECL_BY_REF_P(NODE) DECL_LANG_FLAG_1 (NODE) #define DECL_BY_REF_P(NODE) DECL_LANG_FLAG_1 (NODE)
/* Nonzero in a DECL if it is made for a pointer that can never be null. */
#define DECL_CAN_NEVER_BE_NULL_P(NODE) DECL_LANG_FLAG_2 (NODE)
/* Nonzero in a FIELD_DECL that is a dummy built for some internal reason. */ /* Nonzero in a FIELD_DECL that is a dummy built for some internal reason. */
#define DECL_INTERNAL_P(NODE) DECL_LANG_FLAG_3 (FIELD_DECL_CHECK (NODE)) #define DECL_INTERNAL_P(NODE) DECL_LANG_FLAG_3 (FIELD_DECL_CHECK (NODE))
...@@ -364,7 +367,7 @@ do { \ ...@@ -364,7 +367,7 @@ do { \
DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (NODE)) DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (NODE))
/* Nonzero in a DECL if it is made for a pointer that points to something which /* Nonzero in a DECL if it is made for a pointer that points to something which
is readonly. Used mostly for fat pointers. */ is readonly. */
#define DECL_POINTS_TO_READONLY_P(NODE) DECL_LANG_FLAG_4 (NODE) #define DECL_POINTS_TO_READONLY_P(NODE) DECL_LANG_FLAG_4 (NODE)
/* Nonzero in a PARM_DECL if we are to pass by descriptor. */ /* Nonzero in a PARM_DECL if we are to pass by descriptor. */
......
...@@ -1417,6 +1417,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -1417,6 +1417,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnat_entity); gnat_entity);
DECL_BY_REF_P (gnu_decl) = used_by_ref; DECL_BY_REF_P (gnu_decl) = used_by_ref;
DECL_POINTS_TO_READONLY_P (gnu_decl) = used_by_ref && inner_const_flag; DECL_POINTS_TO_READONLY_P (gnu_decl) = used_by_ref && inner_const_flag;
DECL_CAN_NEVER_BE_NULL_P (gnu_decl) = Can_Never_Be_Null (gnat_entity);
/* If we are defining an Out parameter and optimization isn't enabled, /* If we are defining an Out parameter and optimization isn't enabled,
create a fake PARM_DECL for debugging purposes and make it point to create a fake PARM_DECL for debugging purposes and make it point to
...@@ -5568,6 +5569,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech, ...@@ -5568,6 +5569,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
mech == By_Short_Descriptor); mech == By_Short_Descriptor);
DECL_POINTS_TO_READONLY_P (gnu_param) DECL_POINTS_TO_READONLY_P (gnu_param)
= (ro_param && (by_ref || by_component_ptr)); = (ro_param && (by_ref || by_component_ptr));
DECL_CAN_NEVER_BE_NULL_P (gnu_param) = Can_Never_Be_Null (gnat_param);
/* Save the alternate descriptor type, if any. */ /* Save the alternate descriptor type, if any. */
if (gnu_param_type_alt) if (gnu_param_type_alt)
......
...@@ -3819,8 +3819,7 @@ convert (tree type, tree expr) ...@@ -3819,8 +3819,7 @@ convert (tree type, tree expr)
return gnat_build_constructor (type, v); return gnat_build_constructor (type, v);
} }
/* There are some special cases of expressions that we process /* There are some cases of expressions that we process specially. */
specially. */
switch (TREE_CODE (expr)) switch (TREE_CODE (expr))
{ {
case ERROR_MARK: case ERROR_MARK:
...@@ -3976,21 +3975,11 @@ convert (tree type, tree expr) ...@@ -3976,21 +3975,11 @@ convert (tree type, tree expr)
break; break;
case UNCONSTRAINED_ARRAY_REF: case UNCONSTRAINED_ARRAY_REF:
{ /* First retrieve the underlying array. */
/* Convert this to the type of the inner array by getting the address expr = maybe_unconstrained_array (expr);
of the array from the template. */ etype = TREE_TYPE (expr);
const bool no_trap = TREE_THIS_NOTRAP (expr); ecode = TREE_CODE (etype);
expr = TREE_OPERAND (expr, 0); break;
expr = build_unary_op (INDIRECT_REF, NULL_TREE,
build_component_ref (expr, NULL_TREE,
TYPE_FIELDS
(TREE_TYPE (expr)),
false));
TREE_THIS_NOTRAP (expr) = no_trap;
etype = TREE_TYPE (expr);
ecode = TREE_CODE (etype);
break;
}
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
{ {
...@@ -4282,6 +4271,8 @@ maybe_unconstrained_array (tree exp) ...@@ -4282,6 +4271,8 @@ maybe_unconstrained_array (tree exp)
if (code == UNCONSTRAINED_ARRAY_REF) if (code == UNCONSTRAINED_ARRAY_REF)
{ {
const bool read_only = TREE_READONLY (exp); const bool read_only = TREE_READONLY (exp);
const bool no_trap = TREE_THIS_NOTRAP (exp);
exp = TREE_OPERAND (exp, 0); exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == COND_EXPR) if (TREE_CODE (exp) == COND_EXPR)
{ {
...@@ -4306,12 +4297,16 @@ maybe_unconstrained_array (tree exp) ...@@ -4306,12 +4297,16 @@ maybe_unconstrained_array (tree exp)
TREE_OPERAND (exp, 0), op1, op2); TREE_OPERAND (exp, 0), op1, op2);
} }
else else
exp = build_unary_op (INDIRECT_REF, NULL_TREE, {
build_component_ref (exp, NULL_TREE, exp = build_unary_op (INDIRECT_REF, NULL_TREE,
TYPE_FIELDS build_component_ref (exp, NULL_TREE,
(TREE_TYPE (exp)), TYPE_FIELDS
false)); (TREE_TYPE (exp)),
TREE_READONLY (exp) = read_only; false));
TREE_READONLY (exp) = read_only;
TREE_THIS_NOTRAP (exp) = no_trap;
}
return exp; return exp;
} }
......
...@@ -1276,44 +1276,60 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand) ...@@ -1276,44 +1276,60 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
break; break;
case INDIRECT_REF: case INDIRECT_REF:
/* If we want to refer to an unconstrained array, use the appropriate {
expression to do so. This will never survive down to the back-end. bool can_never_be_null;
But if TYPE is a thin pointer, first convert to a fat pointer. */ tree t = operand;
if (TYPE_IS_THIN_POINTER_P (type)
&& TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (type))) while (CONVERT_EXPR_P (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
{ t = TREE_OPERAND (t, 0);
operand
= convert (TREE_TYPE (TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (type))), can_never_be_null = DECL_P (t) && DECL_CAN_NEVER_BE_NULL_P (t);
/* If TYPE is a thin pointer, first convert to the fat pointer. */
if (TYPE_IS_THIN_POINTER_P (type)
&& TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (type)))
{
operand = convert
(TREE_TYPE (TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (type))),
operand); operand);
type = TREE_TYPE (operand); type = TREE_TYPE (operand);
} }
if (TYPE_IS_FAT_POINTER_P (type)) /* If we want to refer to an unconstrained array, use the appropriate
{ expression. But this will never survive down to the back-end. */
result = build1 (UNCONSTRAINED_ARRAY_REF, if (TYPE_IS_FAT_POINTER_P (type))
TYPE_UNCONSTRAINED_ARRAY (type), operand); {
TREE_READONLY (result) result = build1 (UNCONSTRAINED_ARRAY_REF,
= TYPE_READONLY (TYPE_UNCONSTRAINED_ARRAY (type)); TYPE_UNCONSTRAINED_ARRAY (type), operand);
} TREE_READONLY (result)
= TYPE_READONLY (TYPE_UNCONSTRAINED_ARRAY (type));
}
/* If we are dereferencing an ADDR_EXPR, return its operand. */ /* If we are dereferencing an ADDR_EXPR, return its operand. */
else if (TREE_CODE (operand) == ADDR_EXPR) else if (TREE_CODE (operand) == ADDR_EXPR)
result = TREE_OPERAND (operand, 0); result = TREE_OPERAND (operand, 0);
/* Otherwise, build and fold the indirect reference. */ /* Otherwise, build and fold the indirect reference. */
else else
{ {
result = build_fold_indirect_ref (operand); result = build_fold_indirect_ref (operand);
TREE_READONLY (result) = TYPE_READONLY (TREE_TYPE (type)); TREE_READONLY (result) = TYPE_READONLY (TREE_TYPE (type));
} }
if (!TYPE_IS_FAT_POINTER_P (type) && TYPE_VOLATILE (TREE_TYPE (type))) if (!TYPE_IS_FAT_POINTER_P (type) && TYPE_VOLATILE (TREE_TYPE (type)))
{ {
TREE_SIDE_EFFECTS (result) = 1; TREE_SIDE_EFFECTS (result) = 1;
if (TREE_CODE (result) == INDIRECT_REF) if (TREE_CODE (result) == INDIRECT_REF)
TREE_THIS_VOLATILE (result) = TYPE_VOLATILE (TREE_TYPE (result)); TREE_THIS_VOLATILE (result) = TYPE_VOLATILE (TREE_TYPE (result));
} }
break;
if ((TREE_CODE (result) == INDIRECT_REF
|| TREE_CODE (result) == UNCONSTRAINED_ARRAY_REF)
&& can_never_be_null)
TREE_THIS_NOTRAP (result) = 1;
break;
}
case NEGATE_EXPR: case NEGATE_EXPR:
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
...@@ -2442,7 +2458,10 @@ gnat_stabilize_reference_1 (tree e, bool force) ...@@ -2442,7 +2458,10 @@ gnat_stabilize_reference_1 (tree e, bool force)
TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (e); TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (e);
TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e); TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF) if (code == INDIRECT_REF
|| code == UNCONSTRAINED_ARRAY_REF
|| code == ARRAY_REF
|| code == ARRAY_RANGE_REF)
TREE_THIS_NOTRAP (result) = TREE_THIS_NOTRAP (e); TREE_THIS_NOTRAP (result) = TREE_THIS_NOTRAP (e);
return result; return result;
...@@ -2578,7 +2597,10 @@ gnat_stabilize_reference (tree ref, bool force, bool *success) ...@@ -2578,7 +2597,10 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (ref); TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (ref);
TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref); TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF) if (code == INDIRECT_REF
|| code == UNCONSTRAINED_ARRAY_REF
|| code == ARRAY_REF
|| code == ARRAY_RANGE_REF)
TREE_THIS_NOTRAP (result) = TREE_THIS_NOTRAP (ref); TREE_THIS_NOTRAP (result) = TREE_THIS_NOTRAP (ref);
return result; return result;
......
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