On Thu, 14 Jun 2018, Richard Biener wrote:
> Can you make sure to add a testcase?
Apologies, I got a bit too excited and forgot that my local testcase had
void *unused_ref = &foo;
which masked another issue: unreferenced declarations won't even appear
in the symtab, even if they have __attribute__((used)).
I took a shot at fixing that. The following patch makes sure the decl
appears in the symtab and is not deleted by ipa-visibility.
However, it is not added to LTO streamed-out symtab, so WPA does not see it.
If the direction looks fine overall, I'll look into getting over this
streaming hurdle (hints much appreciated).
WIP patch (untested), now with a minimal testcase:
* c-family/c-attribs.c (handle_used_attribute): Create a symtab node.
* cgraphunit.c (symtab_node::needed_p): Respect force_output even for
external nodes.
* ipa-visibility.c (function_and_variable_visibility): Do not reset
node->force_output.
* ipa.c (symbol_table::remove_unreachable_nodes): Do not remove nodes
that are needed_p.
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 73901bdf47c..f28bb529092 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -1052,6 +1052,7 @@ handle_used_attribute (tree *pnode, tree name, tree
ARG_UNUSED (args),
DECL_PRESERVE_P (node) = 1;
if (VAR_P (node))
DECL_READ_P (node) = 1;
+ symtab_node::get_create (node);
}
else
{
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 04b6919be48..3931a79aa3d 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -244,16 +244,16 @@ symtab_node::needed_p (void)
(!DECL_ASSEMBLER_NAME_SET_P (decl)
|| !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
+ /* If the user told us it is used, then it must be so. */
+ if (force_output)
+ return true;
+
if (!definition)
return false;
if (DECL_EXTERNAL (decl))
return false;
- /* If the user told us it is used, then it must be so. */
- if (force_output)
- return true;
-
/* ABI forced symbols are needed when they are external. */
if (forced_by_abi && TREE_PUBLIC (decl))
return true;
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 907dc9d0e2b..3e167567b45 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -668,10 +668,7 @@ function_and_variable_visibility (bool whole_program)
is finished. We may end up marking as node external nodes
where this flag is meaningless strip it. */
if (DECL_EXTERNAL (node->decl) || !node->definition)
- {
- node->force_output = 0;
- node->forced_by_abi = 0;
- }
+ node->forced_by_abi = 0;
/* C++ FE on lack of COMDAT support create local COMDAT functions
(that ought to be shared but can not due to object format
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 82fc334ec0b..8e011d00cc4 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -507,7 +507,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
next = next_function (node);
/* If node is not needed at all, remove it. */
- if (!node->aux)
+ if (!node->aux && !node->needed_p ())
{
if (file)
fprintf (file, " %s", node->dump_name ());
diff --git a/gcc/testsuite/gcc.dg/lto/tlasm_0.c
b/gcc/testsuite/gcc.dg/lto/tlasm_0.c
index e69de29bb2d..ba31c01e17c 100644
--- a/gcc/testsuite/gcc.dg/lto/tlasm_0.c
+++ b/gcc/testsuite/gcc.dg/lto/tlasm_0.c
@@ -0,0 +1,19 @@
+/* { dg-lto-do link } */
+/* { dg-require-effective-target gas } */
+
+/* Test that __attribute__((used)) can be used to preserve definitions of
+ * symbols referenced in toplevel asm even when the definition is provided
+ * in another translation unit, i.e. the attribute is not lost before WPA. */
+
+__attribute__ ((used))
+void foo (void);
+
+#if __SIZEOF_POINTER__ == 64
+asm (".quad foo");
+#else
+asm (".long foo");
+#endif
+
+int main ()
+{
+}
diff --git a/gcc/testsuite/gcc.dg/lto/tlasm_1.c
b/gcc/testsuite/gcc.dg/lto/tlasm_1.c
index e69de29bb2d..a4b7f5afa52 100644
--- a/gcc/testsuite/gcc.dg/lto/tlasm_1.c
+++ b/gcc/testsuite/gcc.dg/lto/tlasm_1.c
@@ -0,0 +1,3 @@
+void foo (void)
+{
+}