diff options
Diffstat (limited to 'contrib/gcc/tree.c')
-rw-r--r-- | contrib/gcc/tree.c | 73 |
1 files changed, 66 insertions, 7 deletions
diff --git a/contrib/gcc/tree.c b/contrib/gcc/tree.c index bd89387..5ffb010 100644 --- a/contrib/gcc/tree.c +++ b/contrib/gcc/tree.c @@ -286,7 +286,7 @@ tree_size (node) case '1': /* a unary arithmetic expression */ case '2': /* a binary arithmetic expression */ return (sizeof (struct tree_exp) - + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); + + TREE_CODE_LENGTH (code) * sizeof (char *) - sizeof (char *)); case 'c': /* a constant */ /* We can't use TREE_CODE_LENGTH for INTEGER_CST, since the number of @@ -304,12 +304,12 @@ tree_size (node) case 'x': /* something random, like an identifier. */ { - size_t length; - length = (sizeof (struct tree_common) - + TREE_CODE_LENGTH (code) * sizeof (char *)); - if (code == TREE_VEC) - length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *); - return length; + size_t length; + length = (sizeof (struct tree_common) + + TREE_CODE_LENGTH (code) * sizeof (char *)); + if (code == TREE_VEC) + length += TREE_VEC_LENGTH (node) * sizeof (char *) - sizeof (char *); + return length; } default: @@ -4335,6 +4335,65 @@ int_fits_type_p (c, type) } } +/* Returns true if T is, contains, or refers to a type with variable + size. This concept is more general than that of C99 'variably + modified types': in C99, a struct type is never variably modified + because a VLA may not appear as a structure member. However, in + GNU C code like: + + struct S { int i[f()]; }; + + is valid, and other languages may define similar constructs. */ + +bool +variably_modified_type_p (type) + tree type; +{ + /* If TYPE itself has variable size, it is variably modified. + + 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) + 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; + + /* 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; + + /* 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; + } + + /* The current language may have other cases to check, but in general, + all other types are not variably modified. */ + return (*lang_hooks.tree_inlining.var_mod_type_p) (type); +} + /* Given a DECL or TYPE, return the scope in which it was declared, or NULL_TREE if there is no containing scope. */ |