tree-nested.c (check_for_nested_with_variably_modified): New.
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>
Mon, 29 Nov 2004 01:03:15 +0000 (01:03 +0000)
committerRichard Kenner <kenner@gcc.gnu.org>
Mon, 29 Nov 2004 01:03:15 +0000 (20:03 -0500)
* tree-nested.c (check_for_nested_with_variably_modified): New.
(create_nesting_tree): Call it.

From-SVN: r91449

gcc/ChangeLog
gcc/tree-nested.c

index 87d29bc7e01be7bb1b1158227683f599b783fa4e..38eb985f09f26ed31d3f2e329d657591822317ac 100644 (file)
@@ -1,5 +1,8 @@
 2004-11-28  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
+       * tree-nested.c (check_for_nested_with_variably_modified): New.
+       (create_nesting_tree): Call it.
+
        * tree-ssa-alias.c (compute_points_to_and_addr_escapes): Remove
        special code for assigning to non-pointer.
        (is_escape_site): If RHS is a conversion between pointer and integer
index 3f500f6f138914fcae2f05c2316735ce8ce0cedb..76396ca96f82430dd7e2f051bca84a30eeeb70e9 100644 (file)
@@ -612,8 +612,49 @@ walk_all_functions (walk_tree_fn callback, struct nesting_info *root)
     }
   while (root);
 }
-
 \f
+/* 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;
 }