summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2004-07-06 02:20:16 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2004-07-06 02:20:16 +0000
commit1f8a6ff8484e367b87d47717fae8eacf2deea6da (patch)
treee36b5564359495ed12dc4107ed22bf65a3afddcc
parent03fee89c3c1c11afc6073aebba4e2d5cee7ed29f (diff)
downloadgcc-1f8a6ff8484e367b87d47717fae8eacf2deea6da.tar.gz
* langhooks-def.h (LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P): Extra arg.
* langhooks.h (var_mod_type_p): Likewise. * c-decl.c (finish_decl): Add extra arg to variably_modified_type_p. * expr.c (count_type_elements): Properly handle return from array_type_nelts and properly test for overflow. * gimplify.c (gimplify_init_constructor): Properly handle return from array_type_nelts. (gimplify_addr_expr): Remove redundant clear of TREE_SIDE_EFFECTS. * integrate.c (copy_decl_for_inlining): Correct comments. * tree-inline.c (remap_decl): Update comments, remove dead code, and copy DECL_FIELD_OFFSET and DECL_QUALIFIER, if they exist. (remap_type): Only remap if variably modified by vars in function being inlined. (copy_body_r): Use compatible_type langhooks to see when can fold. (setup_one_parameter): Don't remap type. (inline_forbidden_p_1): Add arg to variably_modified_type_p. * tree.c (recompute_tree_invarant_for_addr_expr): Properly compute TREE_INVARIANT for decl case. (find_var_from_fn): New function. (variably_modified_type_p): Add arg and call new function. * tree.h (variably_modified_type_p): Add extra arg. * cp/cp-lang.c (cp_var_mod_type_p): Add extra arg. * cp/decl.c (grokdeclarator): Extra arg to variably_modified_type_p. * cp/pt.c (check_instantiated_args, unify): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84144 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/c-decl.c2
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-lang.c12
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/expr.c4
-rw-r--r--gcc/gimplify.c10
-rw-r--r--gcc/integrate.c7
-rw-r--r--gcc/langhooks-def.h2
-rw-r--r--gcc/langhooks.h2
-rw-r--r--gcc/tree-inline.c76
-rw-r--r--gcc/tree.c89
-rw-r--r--gcc/tree.h2
14 files changed, 145 insertions, 97 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 347bad3988f..878bc56282b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2004-07-05 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * langhooks-def.h (LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P): Extra arg.
+ * langhooks.h (var_mod_type_p): Likewise.
+ * c-decl.c (finish_decl): Add extra arg to variably_modified_type_p.
+ * expr.c (count_type_elements): Properly handle return from
+ array_type_nelts and properly test for overflow.
+ * gimplify.c (gimplify_init_constructor): Properly handle return
+ from array_type_nelts.
+ (gimplify_addr_expr): Remove redundant clear of TREE_SIDE_EFFECTS.
+ * integrate.c (copy_decl_for_inlining): Correct comments.
+ * tree-inline.c (remap_decl): Update comments, remove dead code,
+ and copy DECL_FIELD_OFFSET and DECL_QUALIFIER, if they exist.
+ (remap_type): Only remap if variably modified by vars in function
+ being inlined.
+ (copy_body_r): Use compatible_type langhooks to see when can fold.
+ (setup_one_parameter): Don't remap type.
+ (inline_forbidden_p_1): Add arg to variably_modified_type_p.
+ * tree.c (recompute_tree_invarant_for_addr_expr): Properly
+ compute TREE_INVARIANT for decl case.
+ (find_var_from_fn): New function.
+ (variably_modified_type_p): Add arg and call new function.
+ * tree.h (variably_modified_type_p): Add extra arg.
+
2004-07-05 Eric Botcazou <ebotcazou@libertysurf.fr>
* config/sparc/sparc.md (nonlocal_goto): Remove disabled code.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 5e34bb59e82..3f6be35d91a 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3037,7 +3037,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
if (TREE_CODE (decl) == TYPE_DECL)
{
if (!DECL_FILE_SCOPE_P (decl)
- && variably_modified_type_p (TREE_TYPE (decl)))
+ && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
add_stmt (build_stmt (DECL_EXPR, decl));
rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1b48f3c272e..2d7f89dcb19 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2004-07-05 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * cp-lang.c (cp_var_mod_type_p): Add extra arg.
+ * decl.c (grokdeclarator): Extra arg to variably_modified_type_p.
+ * pt.c (check_instantiated_args, unify): Likewise.
+
2004-07-05 Phil Edwards <phil@codesourcery.com>
* Make-lang.in (check-c++, lang_checks): Add some comments.
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 98b94581793..5e403d86d97 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -38,7 +38,7 @@ static HOST_WIDE_INT cxx_get_alias_set (tree);
static bool cxx_warn_unused_global_decl (tree);
static tree cp_expr_size (tree);
static size_t cp_tree_size (enum tree_code);
-static bool cp_var_mod_type_p (tree);
+static bool cp_var_mod_type_p (tree, tree);
static int cxx_types_compatible_p (tree, tree);
static void cxx_initialize_diagnostics (diagnostic_context *);
@@ -307,17 +307,19 @@ cp_tree_size (enum tree_code code)
}
/* Returns true if T is a variably modified type, in the sense of C99.
+ FN is as passed to variably_modified_p.
This routine needs only check cases that cannot be handled by the
- language-independent logic in tree-inline.c. */
+ language-independent logic in tree.c. */
static bool
-cp_var_mod_type_p (tree type)
+cp_var_mod_type_p (tree type, tree fn)
{
/* If TYPE is a pointer-to-member, it is variably modified if either
the class or the member are variably modified. */
if (TYPE_PTR_TO_MEMBER_P (type))
- return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
- || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)));
+ return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type), fn)
+ || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type),
+ fn));
/* All other types are not variably modified. */
return false;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bee0402b954..25ecca7ab1c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7329,7 +7329,7 @@ grokdeclarator (const cp_declarator *declarator,
if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
- && variably_modified_type_p (type))
+ && variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
error ("data member may not have variably modified type `%T'", type);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ca52f65fded..5a644b421a8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8557,7 +8557,7 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
}
/* In order to avoid all sorts of complications, we do not
allow variably-modified types as template arguments. */
- else if (variably_modified_type_p (t))
+ else if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
error ("`%T' is a variably modified type", t);
@@ -9732,7 +9732,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
the bound of the array will not be computable in an
instantiation. Besides, such types are not allowed in
ISO C++, so we can do as we please here. */
- if (variably_modified_type_p (arg))
+ if (variably_modified_type_p (arg, NULL_TREE))
return 1;
}
diff --git a/gcc/expr.c b/gcc/expr.c
index e0404449e12..6e4f5c739a4 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4497,11 +4497,11 @@ count_type_elements (tree type)
tree telts = array_type_nelts (type);
if (telts && host_integerp (telts, 1))
{
- HOST_WIDE_INT n = tree_low_cst (telts, 1);
+ HOST_WIDE_INT n = tree_low_cst (telts, 1) + 1;
HOST_WIDE_INT m = count_type_elements (TREE_TYPE (type));
if (n == 0)
return 0;
- if (max / n < m)
+ else if (max / n > m)
return n * m;
}
return -1;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 20196fecfed..0493efa0b37 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2514,7 +2514,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
{
tree nelts = array_type_nelts (type);
if (!host_integerp (nelts, 1)
- || tree_low_cst (nelts, 1) != len)
+ || tree_low_cst (nelts, 1) + 1 != len)
cleared = 1;;
}
else if (len != fields_length (type))
@@ -3050,12 +3050,8 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p)
is_gimple_addr_expr_arg, fb_either);
if (ret != GS_ERROR)
{
- /* At this point, the argument of the ADDR_EXPR should be
- sufficiently simple that there are never side effects. */
- /* ??? Could split out the decision code from build1 to verify. */
- TREE_SIDE_EFFECTS (expr) = 0;
-
- /* Make sure TREE_INVARIANT/TREE_CONSTANT is set properly. */
+ /* Make sure TREE_INVARIANT, TREE_CONSTANT, and TREE_SIDE_EFFECTS
+ is set properly. */
recompute_tree_invarant_for_addr_expr (expr);
/* Mark the RHS addressable. */
diff --git a/gcc/integrate.c b/gcc/integrate.c
index 03711d9baf0..892f4534f81 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -105,9 +105,8 @@ function_attribute_inlinable_p (tree fndecl)
return true;
}
-/* Copy NODE (which must be a DECL, but not a PARM_DECL). The DECL
- originally was in the FROM_FN, but now it will be in the
- TO_FN. */
+/* Copy NODE (which must be a DECL). The DECL originally was in the FROM_FN,
+ but now it will be in the TO_FN. */
tree
copy_decl_for_inlining (tree decl, tree from_fn, tree to_fn)
@@ -132,7 +131,7 @@ copy_decl_for_inlining (tree decl, tree from_fn, tree to_fn)
else
type = TREE_TYPE (decl);
- /* For a parameter, we must make an equivalent VAR_DECL, not a
+ /* For a parameter or result, we must make an equivalent VAR_DECL, not a
new PARM_DECL. */
copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
if (!invisiref)
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index da8b6081e54..f3182603a6d 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -157,7 +157,7 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
lhd_tree_inlining_anon_aggr_type_p
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
- hook_bool_tree_false
+ hook_bool_tree_tree_false
#define LANG_HOOKS_TREE_INLINING_START_INLINING \
lhd_tree_inlining_start_inlining
#define LANG_HOOKS_TREE_INLINING_END_INLINING \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 895d94b16d8..ac785feb4ac 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -43,7 +43,7 @@ struct lang_hooks_for_tree_inlining
tree (*copy_res_decl_for_inlining) (tree, tree, tree,
void *, int *, tree);
int (*anon_aggr_type_p) (tree);
- bool (*var_mod_type_p) (tree);
+ bool (*var_mod_type_p) (tree, tree);
int (*start_inlining) (tree);
void (*end_inlining) (tree);
tree (*convert_parm_for_inlining) (tree, tree, tree, int);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 34a158c20f6..fcda4ad5f77 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -155,35 +155,21 @@ insert_decl_map (inline_data *id, tree key, tree value)
(splay_tree_value) value);
}
-/* Remap DECL during the copying of the BLOCK tree for the function. */
+/* Remap DECL during the copying of the BLOCK tree for the function.
+ We are only called to remap local variables in the current function. */
static tree
remap_decl (tree decl, inline_data *id)
{
- splay_tree_node n;
- tree fn;
-
- /* We only remap local variables in the current function. */
- fn = VARRAY_TOP_TREE (id->fns);
-#if 0
- /* We need to remap statics, too, so that they get expanded even if the
- inline function is never emitted out of line. We might as well also
- remap extern decls so that they show up in the debug info. */
- if (! lang_hooks.tree_inlining.auto_var_in_fn_p (decl, fn))
- return NULL_TREE;
-#endif
-
- /* See if we have remapped this declaration. */
- n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
+ splay_tree_node n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
+ tree fn = VARRAY_TOP_TREE (id->fns);
- /* If we didn't already have an equivalent for this declaration,
- create one now. */
+ /* See if we have remapped this declaration. If we didn't already have an
+ equivalent for this declaration, create one now. */
if (!n)
{
- tree t;
-
/* Make a copy of the variable or label. */
- t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
+ tree t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
/* Remap types, if necessary. */
TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
@@ -197,6 +183,14 @@ remap_decl (tree decl, inline_data *id)
walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL);
walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL);
+ /* If fields, do likewise for offset and qualifier. */
+ if (TREE_CODE (t) == FIELD_DECL)
+ {
+ walk_tree (&DECL_FIELD_OFFSET (t), copy_body_r, id, NULL);
+ if (TREE_CODE (DECL_CONTEXT (t)) == QUAL_UNION_TYPE)
+ walk_tree (&DECL_QUALIFIER (t), copy_body_r, id, NULL);
+ }
+
#if 0
/* FIXME handle anon aggrs. */
if (! DECL_NAME (t) && TREE_TYPE (t)
@@ -243,8 +237,9 @@ remap_type (tree type, inline_data *id)
if (node)
return (tree) node->value;
- /* The type only needs remapping if it's variably modified. */
- if (! variably_modified_type_p (type))
+ /* The type only needs remapping if it's variably modified by a variable
+ in the function we are inlining. */
+ if (! variably_modified_type_p (type, VARRAY_TOP_TREE (id->fns)))
{
insert_decl_map (id, type, type);
return type;
@@ -458,12 +453,8 @@ copy_bind_expr (tree *tp, int *walk_subtrees, inline_data *id)
static tree
copy_body_r (tree *tp, int *walk_subtrees, void *data)
{
- inline_data* id;
- tree fn;
-
- /* Set up. */
- id = (inline_data *) data;
- fn = VARRAY_TOP_TREE (id->fns);
+ inline_data *id = (inline_data *) data;
+ tree fn = VARRAY_TOP_TREE (id->fns);
#if 0
/* All automatic variables should have a DECL_CONTEXT indicating
@@ -507,7 +498,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
/* Local variables and labels need to be replaced by equivalent
variables. We don't want to copy static variables; there's only
one of those, no matter how many times we inline the containing
- function. */
+ function. Similarly for globals from an outer function. */
else if (lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
{
tree new_decl;
@@ -603,13 +594,13 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
value = (tree) n->value;
if (TREE_CODE (value) == INDIRECT_REF)
{
- /* Assume that the argument types properly match the
- parameter types. We can't compare them well enough
- without a comptypes langhook, and we don't want to
- call convert and introduce a NOP_EXPR to convert
- between two equivalent types (i.e. that only differ
- in use of typedef names). */
- *tp = TREE_OPERAND (value, 0);
+ if (!lang_hooks.types_compatible_p
+ (TREE_TYPE (*tp), TREE_TYPE (TREE_OPERAND (value, 0))))
+ *tp = fold_convert (TREE_TYPE (*tp),
+ TREE_OPERAND (value, 0));
+ else
+ *tp = TREE_OPERAND (value, 0);
+
return copy_body_r (tp, walk_subtrees, data);
}
}
@@ -626,7 +617,9 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
{
value = (tree) n->value;
STRIP_NOPS (value);
- if (TREE_CODE (value) == ADDR_EXPR)
+ if (TREE_CODE (value) == ADDR_EXPR
+ && (lang_hooks.types_compatible_p
+ (TREE_TYPE (*tp), TREE_TYPE (TREE_OPERAND (value, 0)))))
{
*tp = TREE_OPERAND (value, 0);
return copy_body_r (tp, walk_subtrees, data);
@@ -739,9 +732,10 @@ setup_one_parameter (inline_data *id, tree p, tree value, tree fn,
}
}
- /* Make an equivalent VAR_DECL with the remapped type. */
+ /* Make an equivalent VAR_DECL. Note that we must NOT remap the type
+ here since the type of this decl must be visible to the calling
+ function. */
var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
- TREE_TYPE (var) = remap_type (TREE_TYPE (var), id);
/* See if the frontend wants to pass this by invisible reference. If
so, our new VAR_DECL will have REFERENCE_TYPE, and we need to
@@ -1072,7 +1066,7 @@ inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
then the type node for S doesn't get adjusted properly when
F is inlined, and we abort in find_function_data. */
for (t = TYPE_FIELDS (node); t; t = TREE_CHAIN (t))
- if (variably_modified_type_p (TREE_TYPE (t)))
+ if (variably_modified_type_p (TREE_TYPE (t), NULL))
{
inline_forbidden_reason
= N_("%Jfunction '%F' can never be inlined "
diff --git a/gcc/tree.c b/gcc/tree.c
index 9183a5cc864..410acdfb552 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2352,16 +2352,20 @@ do { tree _node = (NODE); \
}
/* Now see what's inside. If it's an INDIRECT_REF, copy our properties from
- it. If it's a decl, it's definitely invariant and it's constant if the
- decl is static. (Taking the address of a volatile variable is not
- volatile.) If it's a constant, the address is both invariant and
- constant. Otherwise it's neither. */
+ it. If it's a decl, it's invariant and constant if the decl is static.
+ It's also invariant if it's a decl in the current function. (Taking the
+ address of a volatile variable is not volatile.) If it's a constant,
+ the address is both invariant and constant. Otherwise it's neither. */
if (TREE_CODE (node) == INDIRECT_REF)
UPDATE_TITCSE (node);
else if (DECL_P (node))
{
- if (!staticp (node))
+ if (staticp (node))
+ ;
+ else if (decl_function_context (node) == current_function_decl)
tc = false;
+ else
+ ti = tc = false;
}
else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c')
;
@@ -4685,21 +4689,50 @@ int_fits_type_p (tree c, tree type)
}
}
+/* Subprogram of following function. Called by walk_tree.
+
+ Return *TP if it is an automatic variable or parameter of the
+ function passed in as DATA. */
+
+static tree
+find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
+{
+ tree fn = (tree) data;
+
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+
+ else if (DECL_P (*tp) && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+ return *tp;
+
+ return NULL_TREE;
+}
+
/* 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:
+ size. If FN is nonzero, only return true if a modifier of the type
+ or position of FN is a variable or parameter inside FN.
+
+ 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 (tree type)
+variably_modified_type_p (tree type, tree fn)
{
tree t;
+/* Test if T is either variable (if FN is zero) or an expression containing
+ a variable in FN. */
+#define RETURN_TRUE_IF_VAR(T) \
+ do { tree _t = (T); \
+ if (_t && _t != error_mark_node && TREE_CODE (_t) != INTEGER_CST \
+ && (!fn || walk_tree (&_t, find_var_from_fn, fn, NULL))) \
+ return true; } while (0)
+
if (type == error_mark_node)
return false;
@@ -4708,9 +4741,8 @@ 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. */
- t = TYPE_SIZE (type);
- if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
- return true;
+ RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
+ RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type));
switch (TREE_CODE (type))
{
@@ -4719,7 +4751,7 @@ variably_modified_type_p (tree type)
case ARRAY_TYPE:
case SET_TYPE:
case VECTOR_TYPE:
- if (variably_modified_type_p (TREE_TYPE (type)))
+ if (variably_modified_type_p (TREE_TYPE (type), fn))
return true;
break;
@@ -4727,13 +4759,13 @@ variably_modified_type_p (tree 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. */
- if (variably_modified_type_p (TREE_TYPE (type)))
+ if (variably_modified_type_p (TREE_TYPE (type), fn))
return true;
for (t = TYPE_ARG_TYPES (type);
t && t != void_list_node;
t = TREE_CHAIN (t))
- if (variably_modified_type_p (TREE_VALUE (t)))
+ if (variably_modified_type_p (TREE_VALUE (t), fn))
return true;
break;
@@ -4744,13 +4776,8 @@ variably_modified_type_p (tree type)
case CHAR_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;
-
- t = TYPE_MAX_VALUE (type);
- if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
- return true;
+ RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type));
+ RETURN_TRUE_IF_VAR (TYPE_MAX_VALUE (type));
break;
case RECORD_TYPE:
@@ -4763,14 +4790,12 @@ variably_modified_type_p (tree type)
for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL)
{
- tree t1 = DECL_FIELD_OFFSET (t);
+ RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t));
+ RETURN_TRUE_IF_VAR (DECL_SIZE (t));
+ RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t));
- if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
- return true;
-
- t1 = DECL_SIZE (t);
- if (t1 && t1 != error_mark_node && TREE_CODE (t1) != INTEGER_CST)
- return true;
+ if (TREE_CODE (type) == QUAL_UNION_TYPE)
+ RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t));
}
break;
@@ -4780,7 +4805,9 @@ variably_modified_type_p (tree type)
/* 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);
+ return lang_hooks.tree_inlining.var_mod_type_p (type, fn);
+
+#undef RETURN_TRUE_IF_VAR
}
/* Given a DECL or TYPE, return the scope in which it was declared, or
diff --git a/gcc/tree.h b/gcc/tree.h
index f093f799987..d8fed6c61ed 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3469,7 +3469,7 @@ extern int objects_must_conflict_p (tree, tree);
/* In tree.c */
extern int really_constant_p (tree);
extern int int_fits_type_p (tree, tree);
-extern bool variably_modified_type_p (tree);
+extern bool variably_modified_type_p (tree, tree);
extern int tree_log2 (tree);
extern int tree_floor_log2 (tree);
extern int simple_cst_equal (tree, tree);