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;
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;
}
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;
}
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;
else
abort ();
}
- else if (IS_EXPR_CODE_CLASS (class) || class == 'r')
+ else if (IS_EXPR_CODE_CLASS (class))
{
val = iterative_hash_object (code, val);
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. */
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))
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. */
bool
variably_modified_type_p (tree type)
{
+ tree t;
+
if (type == error_mark_node)
return false;
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,
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,
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);
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);