diff options
author | Jan Hubicka <jh@suse.cz> | 2016-04-21 11:05:07 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2016-04-21 09:05:07 +0000 |
commit | a2b056a364e622aac29160bb21fe637d5f6c9519 (patch) | |
tree | dd1fa989c4b9cbacc321b6ccd5f44964b611f58f /gcc/cgraph.c | |
parent | 9b7924dd177330167865a83f5696a9ae34554972 (diff) | |
download | gcc-a2b056a364e622aac29160bb21fe637d5f6c9519.zip gcc-a2b056a364e622aac29160bb21fe637d5f6c9519.tar.gz gcc-a2b056a364e622aac29160bb21fe637d5f6c9519.tar.bz2 |
re PR c++/70018 (Possible issue around IPO and C++ comdats discovered as pure/const)
PR ipa/70018
* cgraph.c (cgraph_set_nothrow_flag_1): Rename to ...
(set_nothrow_flag_1): ... this; handle interposition correctly;
recurse on aliases and thunks.
(cgraph_node::set_nothrow_flag): New.
* ipa-pure-const.c (ignore_edge_for_nothrow): Ignore calls to
functions compiled with non-call exceptions that binds to current
def.
(propagate_nothrow): Be safe WRT interposition.
* cgraph.h (set_nothrow_flag): Update prototype.
* g++.dg/ipa/nothrow-1.C: New testcase.
From-SVN: r235318
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 63 |
1 files changed, 50 insertions, 13 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index d8cb526..d93a939 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2358,27 +2358,65 @@ cgraph_node::make_local (void) /* Worker to set nothrow flag. */ -static bool -cgraph_set_nothrow_flag_1 (cgraph_node *node, void *data) +static void +set_nothrow_flag_1 (cgraph_node *node, bool nothrow, bool non_call, + bool *changed) { cgraph_edge *e; - TREE_NOTHROW (node->decl) = data != NULL; - - if (data != NULL) - for (e = node->callers; e; e = e->next_caller) - e->can_throw_external = false; - return false; + if (nothrow && !TREE_NOTHROW (node->decl)) + { + /* With non-call exceptions we can't say for sure if other function body + was not possibly optimized to stil throw. */ + if (!non_call || node->binds_to_current_def_p ()) + { + TREE_NOTHROW (node->decl) = true; + *changed = true; + for (e = node->callers; e; e = e->next_caller) + e->can_throw_external = false; + } + } + else if (!nothrow && TREE_NOTHROW (node->decl)) + { + TREE_NOTHROW (node->decl) = false; + *changed = true; + } + ipa_ref *ref; + FOR_EACH_ALIAS (node, ref) + { + cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); + if (!nothrow || alias->get_availability () > AVAIL_INTERPOSABLE) + set_nothrow_flag_1 (alias, nothrow, non_call, changed); + } + for (cgraph_edge *e = node->callers; e; e = e->next_caller) + if (e->caller->thunk.thunk_p + && (!nothrow || e->caller->get_availability () > AVAIL_INTERPOSABLE)) + set_nothrow_flag_1 (e->caller, nothrow, non_call, changed); } /* Set TREE_NOTHROW on NODE's decl and on aliases of NODE if any to NOTHROW. */ -void +bool cgraph_node::set_nothrow_flag (bool nothrow) { - call_for_symbol_thunks_and_aliases (cgraph_set_nothrow_flag_1, - (void *)(size_t)nothrow, nothrow == true); + bool changed = false; + bool non_call = opt_for_fn (decl, flag_non_call_exceptions); + + if (!nothrow || get_availability () > AVAIL_INTERPOSABLE) + set_nothrow_flag_1 (this, nothrow, non_call, &changed); + else + { + ipa_ref *ref; + + FOR_EACH_ALIAS (this, ref) + { + cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); + if (!nothrow || alias->get_availability () > AVAIL_INTERPOSABLE) + set_nothrow_flag_1 (alias, nothrow, non_call, &changed); + } + } + return changed; } /* Worker to set_const_flag. */ @@ -2517,8 +2555,7 @@ cgraph_node::set_const_flag (bool set_const, bool looping) /* Info used by set_pure_flag_1. */ -struct -set_pure_flag_info +struct set_pure_flag_info { bool pure; bool looping; |