cp-tree.h (calls_setjmp_p): Declare.
authorMark Mitchell <mark@codesourcery.com>
Sun, 5 Dec 1999 17:58:46 +0000 (17:58 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 5 Dec 1999 17:58:46 +0000 (17:58 +0000)
* cp-tree.h (calls_setjmp_p): Declare.
* decl.c (finish_function): Mark functions that call setjmp as
uninlinable.
* optimize.c (calls_setjmp_r): New function.
(calls_setjmp_p): Likewise.

From-SVN: r30789

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/optimize.c

index 5176865..01ee076 100644 (file)
@@ -1,3 +1,11 @@
+1999-12-05  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (calls_setjmp_p): Declare.
+       * decl.c (finish_function): Mark functions that call setjmp as
+       uninlinable.
+       * optimize.c (calls_setjmp_r): New function.
+       (calls_setjmp_p): Likewise.
+
 1999-12-04  Mark Mitchell  <mark@codesourcery.com>
 
        * optimize.c (expand_call_inline): Wrap the expanded call in an
index d31a6ce..7410a82 100644 (file)
@@ -3777,6 +3777,7 @@ extern tree get_id_2                              PROTO((const char *, tree));
 
 /* In optimize.c */
 extern void optimize_function                   PROTO((tree));
+extern int calls_setjmp_p                       PROTO((tree));
 
 /* in pt.c */
 extern void init_pt                             PROTO ((void));
index 2091557..031e666 100644 (file)
@@ -13664,6 +13664,18 @@ finish_function (lineno, flags)
   if (!expanding_p && !processing_template_decl)
     save_function_data (fndecl);
 
+  /* If this function calls `setjmp' it cannot be inlined.  When
+     `longjmp' is called it is not guaranteed to restore the value of
+     local variables that have been modified since the call to
+     `setjmp'.  So, if were to inline this function into some caller
+     `c', then when we `longjmp', we might not restore all variables
+     in `c'.  (It might seem, at first blush, that there's no way for
+     this function to modify local variables in `c', but their
+     addresses may have been stored somewhere accessible to this
+     function.)  */
+  if (!expanding_p && !processing_template_decl && calls_setjmp_p (fndecl))
+    DECL_UNINLINABLE (fndecl) = 1;
+
   if (expand_p)
     {
       int returns_null;
index 8e474a8..dbbda79 100644 (file)
@@ -77,6 +77,7 @@ static int inlinable_function_p PROTO((tree, inline_data *));
 static tree remap_decl PROTO((tree, inline_data *));
 static void remap_block PROTO((tree, tree, inline_data *));
 static void copy_scope_stmt PROTO((tree *, int *, inline_data *));
+static tree calls_setjmp_r PROTO((tree *, int *, void *));
 
 /* Remap DECL during the copying of the BLOCK tree for the function.
    DATA is really an `inline_data *'.  */
@@ -720,3 +721,39 @@ optimize_function (fn)
       VARRAY_FREE (id.fns);
     }
 }
+
+/* Called from calls_setjmp_p via walk_tree.  */
+
+static tree
+calls_setjmp_r (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
+{
+  int setjmp_p;
+  int longjmp_p;
+  int malloc_p;
+  int alloca_p;
+
+  /* We're only interested in FUNCTION_DECLS.  */
+  if (TREE_CODE (*tp) != FUNCTION_DECL)
+    return NULL_TREE;
+
+  special_function_p (*tp, &setjmp_p, &longjmp_p, &malloc_p, &alloca_p);
+
+  return setjmp_p ? *tp : NULL_TREE;
+}
+
+/* Returns non-zero if FN calls `setjmp' or some other function that
+   can return more than once.  This function is conservative; it may
+   occasionally return a non-zero value even when FN does not actually
+   call `setjmp'.  */
+
+int
+calls_setjmp_p (fn)
+     tree fn;
+{
+  return (walk_tree (&DECL_SAVED_TREE (fn), calls_setjmp_r, NULL) 
+         != NULL_TREE);
+}
+