summaryrefslogtreecommitdiff
path: root/gcc/tree-nested.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-29 01:03:15 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-29 01:03:15 +0000
commit7e3365b7cc2a685c5191b755964ac5db75469ee6 (patch)
tree27de2755d3124d876ba5e82bd25a3c692922dafa /gcc/tree-nested.c
parent444a2eaf3f56be85b47f5645a87e736527294edf (diff)
downloadgcc-7e3365b7cc2a685c5191b755964ac5db75469ee6.tar.gz
* tree-nested.c (check_for_nested_with_variably_modified): New.
(create_nesting_tree): Call it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@91449 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-nested.c')
-rw-r--r--gcc/tree-nested.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 3f500f6f138..76396ca96f8 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -612,8 +612,49 @@ walk_all_functions (walk_tree_fn callback, struct nesting_info *root)
}
while (root);
}
-
+/* We have to check for a fairly pathalogical case. The operands of function
+ nested function are to be interpreted in the context of the enclosing
+ function. So if any are variably-sized, they will get remapped when the
+ enclosing function is inlined. But that remapping would also have to be
+ done in the types of the PARM_DECLs of the nested function, meaning the
+ argument types of that function will disagree with the arguments in the
+ calls to that function. So we'd either have to make a copy of the nested
+ function corresponding to each time the enclosing function was inlined or
+ add a VIEW_CONVERT_EXPR to each such operand for each call to the nested
+ function. The former is not practical. The latter would still require
+ detecting this case to know when to add the conversions. So, for now at
+ least, we don't inline such an enclosing function.
+
+ We have to do that check recursively, so here return indicating whether
+ FNDECL has such a nested function. ORIG_FN is the function we were
+ trying to inline to use for checking whether any argument is variably
+ modified by anything in it.
+
+ It would be better to do this in tree-inline.c so that we could give
+ the appropriate warning for why a function can't be inlined, but that's
+ too late since the nesting structure has already been flattened and
+ adding a flag just to record this fact seems a waste of a flag. */
+
+static bool
+check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
+{
+ struct cgraph_node *cgn = cgraph_node (fndecl);
+ tree arg;
+
+ for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
+ {
+ for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = TREE_CHAIN (arg))
+ if (variably_modified_type_p (TREE_TYPE (arg), 0), orig_fndecl)
+ return true;
+
+ if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl))
+ return true;
+ }
+
+ return false;
+}
+
/* Construct our local datastructure describing the function nesting
tree rooted by CGN. */
@@ -632,6 +673,11 @@ create_nesting_tree (struct cgraph_node *cgn)
info->inner = sub;
}
+ /* See discussion at check_for_nested_with_variably_modified for a
+ discussion of why this has to be here. */
+ if (check_for_nested_with_variably_modified (info->context, info->context))
+ DECL_UNINLINABLE (info->context) = true;
+
return info;
}