OSDN Git Service

* gcc-interface/ada-tree.h (DECL_LOOP_PARM_P): New flag.
[pf3gnuchains/gcc-fork.git] / gcc / ada / gcc-interface / utils2.c
index cf290a3..4679ea8 100644 (file)
@@ -798,7 +798,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
       /* Then convert the right operand to its base type.  This will prevent
         unneeded sign conversions when sizetype is wider than integer.  */
       right_operand = convert (right_base_type, right_operand);
-      right_operand = convert (sizetype, right_operand);
+      right_operand = convert_to_index_type (right_operand);
       modulus = NULL_TREE;
       break;
 
@@ -2598,3 +2598,88 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
 
   return result;
 }
+
+/* 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.  */
+
+tree
+gnat_invariant_expr (tree expr)
+{
+  tree type = TREE_TYPE (expr), t;
+
+  STRIP_NOPS (expr);
+
+  while ((TREE_CODE (expr) == CONST_DECL
+         || (TREE_CODE (expr) == VAR_DECL && TREE_READONLY (expr)))
+        && decl_function_context (expr) == current_function_decl
+        && DECL_INITIAL (expr))
+    {
+      expr = DECL_INITIAL (expr);
+      STRIP_NOPS (expr);
+    }
+
+  if (TREE_CONSTANT (expr))
+    return fold_convert (type, expr);
+
+  t = expr;
+
+  while (true)
+    {
+      switch (TREE_CODE (t))
+       {
+       case COMPONENT_REF:
+         if (TREE_OPERAND (t, 2) != NULL_TREE)
+           return NULL_TREE;
+         break;
+
+       case ARRAY_REF:
+       case ARRAY_RANGE_REF:
+         if (!TREE_CONSTANT (TREE_OPERAND (t, 1))
+             || TREE_OPERAND (t, 2) != NULL_TREE
+             || TREE_OPERAND (t, 3) != NULL_TREE)
+           return NULL_TREE;
+         break;
+
+       case BIT_FIELD_REF:
+       case VIEW_CONVERT_EXPR:
+       case REALPART_EXPR:
+       case IMAGPART_EXPR:
+         break;
+
+       case INDIRECT_REF:
+         if (!TREE_READONLY (t)
+             || TREE_SIDE_EFFECTS (t)
+             || !TREE_THIS_NOTRAP (t))
+           return NULL_TREE;
+         break;
+
+       default:
+         goto object;
+       }
+
+      t = TREE_OPERAND (t, 0);
+    }
+
+object:
+  if (TREE_SIDE_EFFECTS (t))
+    return NULL_TREE;
+
+  if (TREE_CODE (t) == CONST_DECL
+      && (DECL_EXTERNAL (t)
+         || decl_function_context (t) != current_function_decl))
+    return fold_convert (type, expr);
+
+  if (!TREE_READONLY (t))
+    return NULL_TREE;
+
+  if (TREE_CODE (t) == PARM_DECL)
+    return fold_convert (type, expr);
+
+  if (TREE_CODE (t) == VAR_DECL
+      && (DECL_EXTERNAL (t)
+         || decl_function_context (t) != current_function_decl))
+    return fold_convert (type, expr);
+
+  return NULL_TREE;
+}