aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/utils2.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2015-05-25 14:00:28 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2015-05-25 14:00:28 +0000
commitea292448322b87fcd3f8da04467420b49f609053 (patch)
treead069168b45b5aa8b35d5e2c20ccbc3558fcf80d /gcc/ada/gcc-interface/utils2.c
parent288cbbbdacf90e3da12df2fd0cffba69f66369ac (diff)
downloadgcc-ea292448322b87fcd3f8da04467420b49f609053.zip
gcc-ea292448322b87fcd3f8da04467420b49f609053.tar.gz
gcc-ea292448322b87fcd3f8da04467420b49f609053.tar.bz2
ada-tree.h (DECL_RENAMING_GLOBAL_P): Rename into...
* gcc-interface/ada-tree.h (DECL_RENAMING_GLOBAL_P): Rename into... (DECL_GLOBAL_NONCONSTANT_RENAMING_P): ...this. * gcc-interface/gigi.h (record_global_renaming_pointer): Delete. (invalidate_global_renaming_pointers): Likewise. (record_global_nonconstant_renaming): New. (invalidate_global_nonconstant_renamings): Likewise. (get_inner_constant_reference): Likewise. (gnat_constant_reference_p): Likewise. * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Adjust to above and register the renaming pointer only if the object is non-constant. (elaborate_expression_1): Call get_inner_constant_reference instead of get_inner_reference. * gcc-interface/trans.c (fold_constant_decl_in_expr): Minor tweak. (Identifier_to_gnu): Adjust to above and do not recheck the renamed object before substituting it. (Compilation_Unit_to_gnu): Adjust to above renaming. Minor tweaks. (gnat_to_gnu) <N_Object_Renaming_Declaration>: Do not return the result at the global level. (N_Exception_Renaming_Declaration): Likewise. * gcc-interface/utils.c (global_renaming_pointers): Rename into... (global_nonconstant_renamings): ...this. (destroy_gnat_utils): Adjust to above renaming. (record_global_renaming_pointer): Rename into... (record_global_nonconstant_renaming): ...this. (invalidate_global_renaming_pointers): Rename into... (invalidate_global_nonconstant_renamings): ...this and do not recheck the renamed object before invalidating. * gcc-interface/utils2.c (gnat_stabilize_reference): Minor tweak. (get_inner_constant_reference): New public function. (gnat_constant_reference_p): New predicate. From-SVN: r223644
Diffstat (limited to 'gcc/ada/gcc-interface/utils2.c')
-rw-r--r--gcc/ada/gcc-interface/utils2.c77
1 files changed, 73 insertions, 4 deletions
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index e25b815..e09b5b9 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -2692,10 +2692,10 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
break;
case COMPONENT_REF:
- result = build3 (COMPONENT_REF, type,
- gnat_stabilize_reference (TREE_OPERAND (ref, 0), force,
- success),
- TREE_OPERAND (ref, 1), NULL_TREE);
+ result = build3 (COMPONENT_REF, type,
+ gnat_stabilize_reference (TREE_OPERAND (ref, 0), force,
+ success),
+ TREE_OPERAND (ref, 1), NULL_TREE);
break;
case BIT_FIELD_REF:
@@ -2782,6 +2782,75 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
return result;
}
+/* This is equivalent to get_inner_reference in expr.c but it returns the
+ ultimate containing object only if the reference (lvalue) is constant,
+ i.e. if it doesn't depend on the context in which it is evaluated. */
+
+tree
+get_inner_constant_reference (tree exp)
+{
+ while (true)
+ {
+ switch (TREE_CODE (exp))
+ {
+ case BIT_FIELD_REF:
+ break;
+
+ case COMPONENT_REF:
+ if (TREE_OPERAND (exp, 2) != NULL_TREE)
+ return NULL_TREE;
+
+ if (!TREE_CONSTANT (DECL_FIELD_OFFSET (TREE_OPERAND (exp, 1))))
+ return NULL_TREE;
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ {
+ if (TREE_OPERAND (exp, 2) != NULL_TREE
+ || TREE_OPERAND (exp, 3) != NULL_TREE)
+ return NULL_TREE;
+
+ tree array_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ if (!TREE_CONSTANT (TREE_OPERAND (exp, 1))
+ || !TREE_CONSTANT (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)))
+ || !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (array_type))))
+ return NULL_TREE;
+ }
+ break;
+
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case VIEW_CONVERT_EXPR:
+ break;
+
+ default:
+ goto done;
+ }
+
+ exp = TREE_OPERAND (exp, 0);
+ }
+
+done:
+ return exp;
+}
+
+/* Return true if REF is a constant reference, i.e. a reference (lvalue) that
+ doesn't depend on the context in which it is evaluated. */
+
+bool
+gnat_constant_reference_p (tree ref)
+{
+ if (handled_component_p (ref))
+ {
+ ref = get_inner_constant_reference (ref);
+ if (!ref)
+ return false;
+ }
+
+ return DECL_P (ref);
+}
+
/* If EXPR is an expression that is invariant in the current function, in the
sense that it can be evaluated anywhere in the function and any number of
times, return EXPR or an equivalent expression. Otherwise return NULL. */