OSDN Git Service

* Make-lang.in (stmp-f2c.h): Don't configure the runtime
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index f09c36a..6812aa4 100644 (file)
@@ -47,6 +47,14 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #include <stdio.h>
 
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free PROTO((void *));
+#endif
+
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
@@ -696,6 +704,16 @@ savealloc (size)
 {
   return (char *) obstack_alloc (saveable_obstack, size);
 }
+
+/* Allocate SIZE bytes in the expression obstack
+   and return a pointer to them.  */
+
+char *
+expralloc (size)
+     int size;
+{
+  return (char *) obstack_alloc (expression_obstack, size);
+}
 \f
 /* Print out which obstack an object is in.  */
 
@@ -1994,6 +2012,20 @@ build_decl_list (parm, value)
   return node;
 }
 
+/* Similar, but build on the expression_obstack.  */
+
+tree
+build_expr_list (parm, value)
+     tree parm, value;
+{
+  register tree node;
+  register struct obstack *ambient_obstack = current_obstack;
+  current_obstack = expression_obstack;
+  node = build_tree_list (parm, value);
+  current_obstack = ambient_obstack;
+  return node;
+}
+
 /* Return a newly created TREE_LIST node whose
    purpose and value fields are PARM and VALUE
    and whose TREE_CHAIN is CHAIN.  */
@@ -2040,6 +2072,20 @@ decl_tree_cons (purpose, value, chain)
   return node;
 }
 
+/* Similar, but build on the expression_obstack.  */
+
+tree
+expr_tree_cons (purpose, value, chain)
+     tree purpose, value, chain;
+{
+  register tree node;
+  register struct obstack *ambient_obstack = current_obstack;
+  current_obstack = expression_obstack;
+  node = tree_cons (purpose, value, chain);
+  current_obstack = ambient_obstack;
+  return node;
+}
+
 /* Same as `tree_cons' but make a permanent object.  */
 
 tree
@@ -2138,19 +2184,49 @@ int_size_in_bytes (type)
 }
 \f
 /* Return, as a tree node, the number of elements for TYPE (which is an
-   ARRAY_TYPE) minus one. This counts only elements of the top array.  */
+   ARRAY_TYPE) minus one. This counts only elements of the top array.
+
+   Don't let any SAVE_EXPRs escape; if we are called as part of a cleanup
+   action, they would get unsaved.  */
 
 tree
 array_type_nelts (type)
      tree type;
 {
-  tree index_type = TYPE_DOMAIN (type);
+  tree index_type, min, max;
+
+  /* If they did it with unspecified bounds, then we should have already
+     given an error about it before we got here.  */
+  if (! TYPE_DOMAIN (type))
+    return error_mark_node;
+
+  index_type = TYPE_DOMAIN (type);
+  min = TYPE_MIN_VALUE (index_type);
+  max = TYPE_MAX_VALUE (index_type);
 
-  return (integer_zerop (TYPE_MIN_VALUE (index_type))
-         ? TYPE_MAX_VALUE (index_type)
-         : fold (build (MINUS_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)),
-                        TYPE_MAX_VALUE (index_type),
-                        TYPE_MIN_VALUE (index_type))));
+  if (! TREE_CONSTANT (min))
+    {
+      STRIP_NOPS (min);
+      if (TREE_CODE (min) == SAVE_EXPR)
+       min = build (RTL_EXPR, TREE_TYPE (TYPE_MIN_VALUE (index_type)), 0,
+                    SAVE_EXPR_RTL (min));
+      else
+       min = TYPE_MIN_VALUE (index_type);
+    }
+
+  if (! TREE_CONSTANT (max))
+    {
+      STRIP_NOPS (max);
+      if (TREE_CODE (max) == SAVE_EXPR)
+       max = build (RTL_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)), 0,
+                    SAVE_EXPR_RTL (max));
+      else
+       max = TYPE_MAX_VALUE (index_type);
+    }
+
+  return (integer_zerop (min)
+         ? max
+         : fold (build (MINUS_EXPR, TREE_TYPE (max), max, min)));
 }
 \f
 /* Return nonzero if arg is static -- a reference to an object in
@@ -2293,15 +2369,18 @@ unsave_expr_now (expr)
 {
   enum tree_code code;
   register int i;
+  int first_rtl;
 
   if (expr == NULL_TREE)
     return expr;
 
   code = TREE_CODE (expr);
+  first_rtl = tree_code_length [(int) code];
   switch (code)
     {
     case SAVE_EXPR:
       SAVE_EXPR_RTL (expr) = 0;
+      first_rtl = 2;
       break;
 
     case TARGET_EXPR:
@@ -2313,6 +2392,7 @@ unsave_expr_now (expr)
       /* I don't yet know how to emit a sequence multiple times.  */
       if (RTL_EXPR_SEQUENCE (expr) != 0)
        abort ();
+      first_rtl = 0;
       break;
 
     case CALL_EXPR:
@@ -2327,6 +2407,16 @@ unsave_expr_now (expr)
              exp = TREE_CHAIN (exp);
            }
        }
+      first_rtl = 2;
+      break;
+
+    case WITH_CLEANUP_EXPR:
+      /* Should be defined to be 2.  */
+      first_rtl = 1;
+      break;
+
+    case METHOD_CALL_EXPR:
+      first_rtl = 3;
       break;
     }
 
@@ -2345,7 +2435,7 @@ unsave_expr_now (expr)
     case '<':  /* a comparison expression */
     case '2':  /* a binary arithmetic expression */
     case '1':  /* a unary arithmetic expression */
-      for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
+      for (i = first_rtl - 1; i >= 0; i--)
        unsave_expr_now (TREE_OPERAND (expr, i));
       return expr;
 
@@ -2355,17 +2445,13 @@ unsave_expr_now (expr)
 }
 \f
 /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
-   or offset that depends on a field within a record.
-
-   Note that we only allow such expressions within simple arithmetic
-   or a COND_EXPR.  */
+   or offset that depends on a field within a record.  */
 
 int
 contains_placeholder_p (exp)
      tree exp;
 {
   register enum tree_code code = TREE_CODE (exp);
-  tree inner;
 
   /* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR
      in it since it is supplying a value for it.  */
@@ -2377,31 +2463,42 @@ contains_placeholder_p (exp)
   switch (TREE_CODE_CLASS (code))
     {
     case 'r':
-      for (inner = TREE_OPERAND (exp, 0);
-          TREE_CODE_CLASS (TREE_CODE (inner)) == 'r';
-          inner = TREE_OPERAND (inner, 0))
-       ;
-      return TREE_CODE (inner) == PLACEHOLDER_EXPR;
+      /* Don't look at any PLACEHOLDER_EXPRs that might be in index or bit
+        position computations since they will be converted into a
+        WITH_RECORD_EXPR involving the reference, which will assume
+        here will be valid.  */
+      return contains_placeholder_p (TREE_OPERAND (exp, 0));
 
     case '1':
     case '2':  case '<':
     case 'e':
+      switch (code)
+       {
+       case COMPOUND_EXPR:
+         /* Ignoring the first operand isn't quite right, but works best. */
+         return contains_placeholder_p (TREE_OPERAND (exp, 1));
+
+       case RTL_EXPR:
+       case CONSTRUCTOR:
+         return 0;
+
+       case COND_EXPR:
+         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
+                 || contains_placeholder_p (TREE_OPERAND (exp, 1))
+                 || contains_placeholder_p (TREE_OPERAND (exp, 2)));
+
+       case SAVE_EXPR:
+          return (SAVE_EXPR_RTL (exp) == 0
+                  && contains_placeholder_p (TREE_OPERAND (exp, 0)));
+       }
+
       switch (tree_code_length[(int) code])
        {
        case 1:
          return contains_placeholder_p (TREE_OPERAND (exp, 0));
        case 2:
-         return (code != RTL_EXPR
-                 && code != CONSTRUCTOR
-                 && ! (code == SAVE_EXPR && SAVE_EXPR_RTL (exp) != 0)
-                 && code != WITH_RECORD_EXPR
-                 && (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                     || contains_placeholder_p (TREE_OPERAND (exp, 1))));
-       case 3:
-         return (code == COND_EXPR
-                 && (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                     || contains_placeholder_p (TREE_OPERAND (exp, 1))
-                     || contains_placeholder_p (TREE_OPERAND (exp, 2))));
+         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
+                 || contains_placeholder_p (TREE_OPERAND (exp, 1)));
        }
     }
 
@@ -3286,34 +3383,6 @@ build_type_variant (type, constp, volatilep)
   return t;
 }
 
-/* Give TYPE a new main variant: NEW_MAIN.
-   This is the right thing to do only when something else
-   about TYPE is modified in place.  */
-
-void
-change_main_variant (type, new_main)
-     tree type, new_main;
-{
-  tree t;
-  tree omain = TYPE_MAIN_VARIANT (type);
-
-  /* Remove TYPE from the TYPE_NEXT_VARIANT chain of its main variant.  */
-  if (TYPE_NEXT_VARIANT (omain) == type)
-    TYPE_NEXT_VARIANT (omain) = TYPE_NEXT_VARIANT (type);
-  else
-    for (t = TYPE_NEXT_VARIANT (omain); t && TYPE_NEXT_VARIANT (t);
-        t = TYPE_NEXT_VARIANT (t))
-      if (TYPE_NEXT_VARIANT (t) == type)
-       {
-         TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (type);
-         break;
-       }
-
-  TYPE_MAIN_VARIANT (type) = new_main;
-  TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (new_main);
-  TYPE_NEXT_VARIANT (new_main) = type;
-}
-
 /* Create a new variant of TYPE, equivalent but distinct.
    This is so the caller can modify it.  */
 
@@ -3936,15 +4005,6 @@ build_array_type (elt_type, index_type)
   hashcode = TYPE_HASH (elt_type) + TYPE_HASH (index_type);
   t = type_hash_canon (hashcode, t);
 
-#if 0 /* This led to crashes, because it could put a temporary node
-        on the TYPE_NEXT_VARIANT chain of a permanent one.  */
-  /* The main variant of an array type should always
-     be an array whose element type is the main variant.  */
-  if (elt_type != TYPE_MAIN_VARIANT (elt_type))
-    change_main_variant (t, build_array_type (TYPE_MAIN_VARIANT (elt_type),
-                                             index_type));
-#endif
-
   if (TYPE_SIZE (t) == 0)
     layout_type (t);
   return t;
@@ -4332,12 +4392,18 @@ int_fits_type_p (c, type)
     return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
               && INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c))
            && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-                 && INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))));
+                 && INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type)))
+           /* Negative ints never fit unsigned types.  */
+           && ! (TREE_INT_CST_HIGH (c) < 0
+                 && ! TREE_UNSIGNED (TREE_TYPE (c))));
   else
     return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
               && INT_CST_LT (TYPE_MAX_VALUE (type), c))
            && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-                 && INT_CST_LT (c, TYPE_MIN_VALUE (type))));
+                 && INT_CST_LT (c, TYPE_MIN_VALUE (type)))
+           /* Unsigned ints with top bit set never fit signed types.  */
+           && ! (TREE_INT_CST_HIGH (c) < 0
+                 && TREE_UNSIGNED (TREE_TYPE (c))));
 }
 
 /* Return the innermost context enclosing DECL that is
@@ -4541,8 +4607,8 @@ get_set_constructor_bits (init, buffer, bit_size)
       if (TREE_CODE (TREE_VALUE (vals)) != INTEGER_CST
          || (TREE_PURPOSE (vals) != NULL_TREE
              && TREE_CODE (TREE_PURPOSE (vals)) != INTEGER_CST))
-       non_const_bits =
-         tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
+       non_const_bits
+         tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
       else if (TREE_PURPOSE (vals) != NULL_TREE)
        {
          /* Set a range of bits to ones.  */