summaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-08 16:33:57 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-08 16:33:57 +0000
commit87ac7f211c08dba84adbd23b1013ef20aa3627f0 (patch)
tree4928e7afc4c094955e19fca3ef23c8bed38d3360 /gcc/ipa.c
parent864ee2c82299fcd8c8e90c1717e346fcd41abcf6 (diff)
downloadgcc-87ac7f211c08dba84adbd23b1013ef20aa3627f0.tar.gz
PR tree-optmization/46469
* ipa.c (function_and_variable_visibility): Clear needed flags on nodes with external decls; handle weakrefs merging correctly. * g++.dg/torture/pr46469.C: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168598 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index cf0a5b3ed7d..fa39f92925d 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -844,16 +844,32 @@ function_and_variable_visibility (bool whole_program)
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
IDENTIFIER_POINTER (p->target));
- if ((node = cgraph_node_for_asm (p->target)) != NULL)
+ if ((node = cgraph_node_for_asm (p->target)) != NULL
+ && !DECL_EXTERNAL (node->decl))
{
+ /* Weakrefs alias symbols from other compilation unit. In the case
+ the destination of weakref became available because of LTO, we must
+ mark it as needed. */
+ if (in_lto_p
+ && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
+ && !node->needed)
+ cgraph_mark_needed_node (node);
gcc_assert (node->needed);
pointer_set_insert (aliased_nodes, node);
if (dump_file)
fprintf (dump_file, " node %s/%i",
cgraph_node_name (node), node->uid);
}
- else if ((vnode = varpool_node_for_asm (p->target)) != NULL)
+ else if ((vnode = varpool_node_for_asm (p->target)) != NULL
+ && !DECL_EXTERNAL (vnode->decl))
{
+ /* Weakrefs alias symbols from other compilation unit. In the case
+ the destination of weakref became available because of LTO, we must
+ mark it as needed. */
+ if (in_lto_p
+ && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
+ && !vnode->needed)
+ varpool_mark_needed_node (vnode);
gcc_assert (vnode->needed);
pointer_set_insert (aliased_vnodes, vnode);
if (dump_file)
@@ -867,6 +883,8 @@ function_and_variable_visibility (bool whole_program)
for (node = cgraph_nodes; node; node = node->next)
{
int flags = flags_from_decl_or_type (node->decl);
+
+ /* Optimize away PURE and CONST constructors and destructors. */
if (optimize
&& (flags & (ECF_CONST | ECF_PURE))
&& !(flags & ECF_LOOPING_CONST_OR_PURE))
@@ -875,6 +893,13 @@ function_and_variable_visibility (bool whole_program)
DECL_STATIC_DESTRUCTOR (node->decl) = 0;
}
+ /* Frontends and alias code marks nodes as needed before parsing is finished.
+ We may end up marking as node external nodes where this flag is meaningless
+ strip it. */
+ if (node->needed
+ && (DECL_EXTERNAL (node->decl) || !node->analyzed))
+ node->needed = 0;
+
/* C++ FE on lack of COMDAT support create local COMDAT functions
(that ought to be shared but can not due to object format
limitations). It is neccesary to keep the flag to make rest of C++ FE