aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2011-09-26 08:26:37 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2011-09-26 08:26:37 +0000
commita1c7d7973c44afbee5e1251b200cc6e7a27409b1 (patch)
tree0bbfdf9e810f8a0d87f499a7747d27b4dadc2da4
parent20633efc34fadc76b339620c2d37f3c12231c40a (diff)
downloadgcc-a1c7d7973c44afbee5e1251b200cc6e7a27409b1.zip
gcc-a1c7d7973c44afbee5e1251b200cc6e7a27409b1.tar.gz
gcc-a1c7d7973c44afbee5e1251b200cc6e7a27409b1.tar.bz2
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
-rw-r--r--gcc/ada/ChangeLog13
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h5
-rw-r--r--gcc/ada/gcc-interface/decl.c2
-rw-r--r--gcc/ada/gcc-interface/utils.c41
-rw-r--r--gcc/ada/gcc-interface/utils2.c92
5 files changed, 94 insertions, 59 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index b114542..4784219 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,18 @@
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.
(SET_TYPE_NULL_BOUNDS): Likewise.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Set again
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 4a0981d..d10fcf0 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -352,6 +352,9 @@ do { \
is needed to access the object. */
#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. */
#define DECL_INTERNAL_P(NODE) DECL_LANG_FLAG_3 (FIELD_DECL_CHECK (NODE))
@@ -364,7 +367,7 @@ do { \
DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (NODE))
/* 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)
/* Nonzero in a PARM_DECL if we are to pass by descriptor. */
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index ea8eb91..98d68fe 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -1417,6 +1417,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnat_entity);
DECL_BY_REF_P (gnu_decl) = used_by_ref;
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,
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,
mech == By_Short_Descriptor);
DECL_POINTS_TO_READONLY_P (gnu_param)
= (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. */
if (gnu_param_type_alt)
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 4d95845..baa4ca1 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -3819,8 +3819,7 @@ convert (tree type, tree expr)
return gnat_build_constructor (type, v);
}
- /* There are some special cases of expressions that we process
- specially. */
+ /* There are some cases of expressions that we process specially. */
switch (TREE_CODE (expr))
{
case ERROR_MARK:
@@ -3976,21 +3975,11 @@ convert (tree type, tree expr)
break;
case UNCONSTRAINED_ARRAY_REF:
- {
- /* Convert this to the type of the inner array by getting the address
- of the array from the template. */
- const bool no_trap = TREE_THIS_NOTRAP (expr);
- expr = TREE_OPERAND (expr, 0);
- 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;
- }
+ /* First retrieve the underlying array. */
+ expr = maybe_unconstrained_array (expr);
+ etype = TREE_TYPE (expr);
+ ecode = TREE_CODE (etype);
+ break;
case VIEW_CONVERT_EXPR:
{
@@ -4282,6 +4271,8 @@ maybe_unconstrained_array (tree exp)
if (code == UNCONSTRAINED_ARRAY_REF)
{
const bool read_only = TREE_READONLY (exp);
+ const bool no_trap = TREE_THIS_NOTRAP (exp);
+
exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == COND_EXPR)
{
@@ -4306,12 +4297,16 @@ maybe_unconstrained_array (tree exp)
TREE_OPERAND (exp, 0), op1, op2);
}
else
- exp = build_unary_op (INDIRECT_REF, NULL_TREE,
- build_component_ref (exp, NULL_TREE,
- TYPE_FIELDS
- (TREE_TYPE (exp)),
- false));
- TREE_READONLY (exp) = read_only;
+ {
+ exp = build_unary_op (INDIRECT_REF, NULL_TREE,
+ build_component_ref (exp, NULL_TREE,
+ TYPE_FIELDS
+ (TREE_TYPE (exp)),
+ false));
+ TREE_READONLY (exp) = read_only;
+ TREE_THIS_NOTRAP (exp) = no_trap;
+ }
+
return exp;
}
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 0cc554d..12c517c 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1276,44 +1276,60 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
break;
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.
- But if TYPE is a thin pointer, first convert to a 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))),
+ {
+ bool can_never_be_null;
+ tree t = operand;
+
+ while (CONVERT_EXPR_P (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ 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);
- type = TREE_TYPE (operand);
- }
+ type = TREE_TYPE (operand);
+ }
- if (TYPE_IS_FAT_POINTER_P (type))
- {
- result = build1 (UNCONSTRAINED_ARRAY_REF,
- TYPE_UNCONSTRAINED_ARRAY (type), operand);
- TREE_READONLY (result)
- = TYPE_READONLY (TYPE_UNCONSTRAINED_ARRAY (type));
- }
+ /* If we want to refer to an unconstrained array, use the appropriate
+ expression. But this will never survive down to the back-end. */
+ if (TYPE_IS_FAT_POINTER_P (type))
+ {
+ result = build1 (UNCONSTRAINED_ARRAY_REF,
+ TYPE_UNCONSTRAINED_ARRAY (type), operand);
+ TREE_READONLY (result)
+ = TYPE_READONLY (TYPE_UNCONSTRAINED_ARRAY (type));
+ }
- /* If we are dereferencing an ADDR_EXPR, return its operand. */
- else if (TREE_CODE (operand) == ADDR_EXPR)
- result = TREE_OPERAND (operand, 0);
+ /* If we are dereferencing an ADDR_EXPR, return its operand. */
+ else if (TREE_CODE (operand) == ADDR_EXPR)
+ result = TREE_OPERAND (operand, 0);
- /* Otherwise, build and fold the indirect reference. */
- else
- {
- result = build_fold_indirect_ref (operand);
- TREE_READONLY (result) = TYPE_READONLY (TREE_TYPE (type));
- }
+ /* Otherwise, build and fold the indirect reference. */
+ else
+ {
+ result = build_fold_indirect_ref (operand);
+ TREE_READONLY (result) = TYPE_READONLY (TREE_TYPE (type));
+ }
- if (!TYPE_IS_FAT_POINTER_P (type) && TYPE_VOLATILE (TREE_TYPE (type)))
- {
- TREE_SIDE_EFFECTS (result) = 1;
- if (TREE_CODE (result) == INDIRECT_REF)
- TREE_THIS_VOLATILE (result) = TYPE_VOLATILE (TREE_TYPE (result));
- }
- break;
+ if (!TYPE_IS_FAT_POINTER_P (type) && TYPE_VOLATILE (TREE_TYPE (type)))
+ {
+ TREE_SIDE_EFFECTS (result) = 1;
+ if (TREE_CODE (result) == INDIRECT_REF)
+ TREE_THIS_VOLATILE (result) = TYPE_VOLATILE (TREE_TYPE (result));
+ }
+
+ 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 BIT_NOT_EXPR:
@@ -2442,7 +2458,10 @@ gnat_stabilize_reference_1 (tree e, bool force)
TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (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);
return result;
@@ -2578,7 +2597,10 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (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);
return result;