From 95fabfd362052e8daf18ec525935e4c5c03ae94a Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sun, 5 Dec 1999 17:58:46 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 12 ++++++++++++ gcc/cp/optimize.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5176865f1df..01ee07692fc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +1999-12-05 Mark Mitchell + + * 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 * optimize.c (expand_call_inline): Wrap the expanded call in an diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d31a6ce8963..7410a821420 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 20915577f89..031e6669433 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 8e474a81a77..dbbda797bcc 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -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); +} + -- 2.30.2