aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-12-05 17:58:46 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-12-05 17:58:46 +0000
commit95fabfd362052e8daf18ec525935e4c5c03ae94a (patch)
tree1eccbfde182d3affc92d416e43991a58f82fb813
parent3a8c995be7629b05f71e5e0d0afb1bd4e7bb6176 (diff)
downloadgcc-95fabfd362052e8daf18ec525935e4c5c03ae94a.zip
gcc-95fabfd362052e8daf18ec525935e4c5c03ae94a.tar.gz
gcc-95fabfd362052e8daf18ec525935e4c5c03ae94a.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/optimize.c37
4 files changed, 58 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5176865..01ee076 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d31a6ce..7410a82 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 2091557..031e666 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 8e474a8..dbbda79 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);
+}
+