+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
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;
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 *'. */
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);
+}
+