cp-tree.h (calls_setjmp_p): Declare.

* 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
This commit is contained in:
Mark Mitchell 1999-12-05 17:58:46 +00:00 committed by Mark Mitchell
parent 3a8c995be7
commit 95fabfd362
4 changed files with 58 additions and 0 deletions

View 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

View 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));

View 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;

View 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);
}