OSDN Git Service

* config/mips/mips.md (*lowsi): Renamed from lowsi.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 7ac0402..dcbf74d 100644 (file)
@@ -488,7 +488,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
    and whose value is the integer value of the INTEGER_CST node I.  */
 
 REAL_VALUE_TYPE
-real_value_from_int_cst (tree type ATTRIBUTE_UNUSED, tree i)
+real_value_from_int_cst (tree type, tree i)
 {
   REAL_VALUE_TYPE d;
 
@@ -496,12 +496,9 @@ real_value_from_int_cst (tree type ATTRIBUTE_UNUSED, tree i)
      bitwise comparisons to see if two values are the same.  */
   memset (&d, 0, sizeof d);
 
-  if (! TREE_UNSIGNED (TREE_TYPE (i)))
-    REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
-                        TYPE_MODE (type));
-  else
-    REAL_VALUE_FROM_UNSIGNED_INT (d, TREE_INT_CST_LOW (i),
-                                 TREE_INT_CST_HIGH (i), TYPE_MODE (type));
+  real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode,
+                    TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
+                    TREE_UNSIGNED (TREE_TYPE (i)));
   return d;
 }
 
@@ -2378,6 +2375,17 @@ build (enum tree_code code, tree tt, ...)
   va_end (p);
 
   TREE_CONSTANT (t) = constant;
+  
+  if (code == CALL_EXPR && !TREE_SIDE_EFFECTS (t))
+    {
+      /* Calls have side-effects, except those to const or
+        pure functions.  */
+      tree fn = get_callee_fndecl (t);
+
+      if (!fn || (!DECL_IS_PURE (fn) && !TREE_READONLY (fn)))
+       TREE_SIDE_EFFECTS (t) = 1;
+    }
+
   return t;
 }
 
@@ -2849,7 +2857,8 @@ get_qualified_type (tree type, int type_quals)
      preserve the TYPE_NAME, since there is code that depends on this.  */
   for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
     if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type)
-        && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
+        && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+       && attribute_list_equal (TYPE_ATTRIBUTES (t), TYPE_ATTRIBUTES (type)))
       return t;
 
   return NULL_TREE;
@@ -3526,7 +3535,7 @@ iterative_hash_expr (tree t, hashval_t val)
       else
        abort ();
     }
-  else if (IS_EXPR_CODE_CLASS (class) || class == 'r')
+  else if (IS_EXPR_CODE_CLASS (class))
     {
       val = iterative_hash_object (code, val);
 
@@ -3823,7 +3832,7 @@ build_function_type (tree value_type, tree arg_types)
   return t;
 }
 
-/* Build a function type.  The RETURN_TYPE is the type retured by the
+/* Build a function type.  The RETURN_TYPE is the type returned by the
    function.  If additional arguments are provided, they are
    additional argument types.  The list of argument types must always
    be terminated by NULL_TREE.  */
@@ -3849,35 +3858,37 @@ build_function_type_list (tree return_type, ...)
   return args;
 }
 
-/* Construct, lay out and return the type of methods belonging to class
-   BASETYPE and whose arguments and values are described by TYPE.
-   If that type exists already, reuse it.
-   TYPE must be a FUNCTION_TYPE node.  */
+/* Build a METHOD_TYPE for a member of BASETYPE.  The RETTYPE (a TYPE)
+   and ARGTYPES (a TREE_LIST) are the return type and arguments types
+   for the method.  An implicit additional parameter (of type
+   pointer-to-BASETYPE) is added to the ARGTYPES.  */
 
 tree
-build_method_type (tree basetype, tree type)
+build_method_type_directly (tree basetype,
+                           tree rettype,
+                           tree argtypes)
 {
   tree t;
-  unsigned int hashcode;
+  tree ptype;
+  int hashcode;
 
   /* Make a node of the sort we want.  */
   t = make_node (METHOD_TYPE);
 
-  if (TREE_CODE (type) != FUNCTION_TYPE)
-    abort ();
-
   TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
-  TREE_TYPE (t) = TREE_TYPE (type);
+  TREE_TYPE (t) = rettype;
+  ptype = build_pointer_type (basetype);
 
   /* The actual arglist for this function includes a "hidden" argument
      which is "this".  Put it into the list of argument types.  */
+  argtypes = tree_cons (NULL_TREE, ptype, argtypes);
+  TYPE_ARG_TYPES (t) = argtypes;
 
-  TYPE_ARG_TYPES (t)
-    = tree_cons (NULL_TREE,
-                build_pointer_type (basetype), TYPE_ARG_TYPES (type));
+  /* If we already have such a type, use the old one and free this one.
+     Note that it also frees up the above cons cell if found.  */
+  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
+    type_hash_list (argtypes);
 
-  /* If we already have such a type, use the old one and free this one.  */
-  hashcode = TYPE_HASH (basetype) + TYPE_HASH (type);
   t = type_hash_canon (hashcode, t);
 
   if (!COMPLETE_TYPE_P (t))
@@ -3886,6 +3897,22 @@ build_method_type (tree basetype, tree type)
   return t;
 }
 
+/* Construct, lay out and return the type of methods belonging to class
+   BASETYPE and whose arguments and values are described by TYPE.
+   If that type exists already, reuse it.
+   TYPE must be a FUNCTION_TYPE node.  */
+
+tree
+build_method_type (tree basetype, tree type)
+{
+  if (TREE_CODE (type) != FUNCTION_TYPE)
+    abort ();
+
+  return build_method_type_directly (basetype, 
+                                    TREE_TYPE (type),
+                                    TYPE_ARG_TYPES (type));
+}
+
 /* Construct, lay out and return the type of offsets to a value
    of type TYPE, within an object of type BASETYPE.
    If a suitable offset type exists already, reuse it.  */
@@ -4246,6 +4273,8 @@ int_fits_type_p (tree c, tree type)
 bool
 variably_modified_type_p (tree type)
 {
+  tree t;
+
   if (type == error_mark_node)
     return false;
 
@@ -4254,39 +4283,50 @@ variably_modified_type_p (tree type)
      We do not yet have a representation of the C99 '[*]' syntax.
      When a representation is chosen, this function should be modified
      to test for that case as well.  */
-  if (TYPE_SIZE (type)
-      && TYPE_SIZE (type) != error_mark_node
-      && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  t = TYPE_SIZE (type);
+  if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
     return true;
 
-  /* If TYPE is a pointer or reference, it is variably modified if
-     the type pointed to is variably modified.  */
-  if ((TREE_CODE (type) == POINTER_TYPE
-       || TREE_CODE (type) == REFERENCE_TYPE)
-      && variably_modified_type_p (TREE_TYPE (type)))
-    return true;
+  switch (TREE_CODE (type))
+    {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case ARRAY_TYPE:
+      /* If TYPE is a pointer or reference, it is variably modified if
+        the type pointed to is variably modified.  Similarly for arrays;
+        note that VLAs are handled by the TYPE_SIZE check above.  */
+      return variably_modified_type_p (TREE_TYPE (type));
 
-  /* If TYPE is an array, it is variably modified if the array
-     elements are.  (Note that the VLA case has already been checked
-     above.)  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && variably_modified_type_p (TREE_TYPE (type)))
-    return true;
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+      /* If TYPE is a function type, it is variably modified if any of the
+         parameters or the return type are variably modified.  */
+      {
+       tree parm;
 
-  /* If TYPE is a function type, it is variably modified if any of the
-     parameters or the return type are variably modified.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE
-      || TREE_CODE (type) == METHOD_TYPE)
-    {
-      tree parm;
+       if (variably_modified_type_p (TREE_TYPE (type)))
+         return true;
+       for (parm = TYPE_ARG_TYPES (type);
+            parm && parm != void_list_node;
+            parm = TREE_CHAIN (parm))
+         if (variably_modified_type_p (TREE_VALUE (parm)))
+           return true;
+      }
+      break;
 
-      if (variably_modified_type_p (TREE_TYPE (type)))
+    case INTEGER_TYPE:
+      /* Scalar types are variably modified if their end points
+        aren't constant.  */
+      t = TYPE_MIN_VALUE (type);
+      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
        return true;
-      for (parm = TYPE_ARG_TYPES (type);
-          parm && parm != void_list_node;
-          parm = TREE_CHAIN (parm))
-       if (variably_modified_type_p (TREE_VALUE (parm)))
-         return true;
+      t = TYPE_MAX_VALUE (type);
+      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
+       return true;
+      return false;
+
+    default:
+      break;
     }
 
   /* The current language may have other cases to check, but in general,
@@ -4409,9 +4449,10 @@ get_callee_fndecl (tree call)
   if (TREE_CODE (addr) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
     return TREE_OPERAND (addr, 0);
-
-  /* We couldn't figure out what was being called.  */
-  return NULL_TREE;
+  
+  /* We couldn't figure out what was being called.  Maybe the front
+     end has some idea.  */
+  return (*lang_hooks.lang_get_callee_fndecl) (call);
 }
 
 /* Print debugging information about tree nodes generated during the compile,
@@ -4517,7 +4558,7 @@ get_file_function_name_long (const char *type)
        file = input_filename;
 
       len = strlen (file);
-      q = alloca (9 * 2 + len);
+      q = alloca (9 * 2 + len + 1);
       memcpy (q, file, len + 1);
       clean_symbol_name (q);
 
@@ -4828,6 +4869,11 @@ build_common_tree_nodes_2 (int short_double)
   TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
   layout_type (long_double_type_node);
 
+  float_ptr_type_node = build_pointer_type (float_type_node);
+  double_ptr_type_node = build_pointer_type (double_type_node);
+  long_double_ptr_type_node = build_pointer_type (long_double_type_node);
+  integer_ptr_type_node = build_pointer_type (integer_type_node);
+
   complex_integer_type_node = make_node (COMPLEX_TYPE);
   TREE_TYPE (complex_integer_type_node) = integer_type_node;
   layout_type (complex_integer_type_node);