Hi! We get bogus warning on the -1 and -4 testcases. The problem is that we accept without warning an __asm rename like: extern void *baz (void *dest, const void *src, __SIZE_TYPE__ n); extern __typeof (baz) baz __asm("bazfn"); only if it doesn't have DECL_ASSEMBLER_NAME_SET_P yet, after it is set we just warn and ignore the rename.
But for #pragma weak, if there are any pending #pragma weak pragmas, we actually set DECL_ASSEMBLER_NAME right away. Fixed by computing DECL_ASSEMBLER_NAME for the #pragma weak handling just temporarily if it hasn't been set yet (yeah, it is duplicate work then, but hopefully not very common), plus also fixing the early outs - if a decl matching some #pragma weak is found, that vector entry is removed from pending_weaks, but we were only testing if pending_weaks is NULL, which it will never be after it has been allocated once. Thus, for the most common case (well, most code doesn't use #pragma weak at all) where you have #pragma weak followed by corresponding prototype or say a couple of #pragma weak directives followed by corresponding prototypes, there should be either no or just very small amount of extra decl_assembler_name invocations. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2014-03-13 Jakub Jelinek <ja...@redhat.com> PR middle-end/36282 * c-pragma.c (apply_pragma_weak): Only look at TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) if DECL_ASSEMBLER_NAME_SET_P (decl). (maybe_apply_pending_pragma_weaks): Exit early if vec_safe_is_empty (pending_weaks) rather than only when !pending_weaks. (maybe_apply_pragma_weak): Likewise. If !DECL_ASSEMBLER_NAME_SET_P, set assembler name back to NULL afterwards. * c-c++-common/pr36282-1.c: New test. * c-c++-common/pr36282-2.c: New test. * c-c++-common/pr36282-3.c: New test. * c-c++-common/pr36282-4.c: New test. --- gcc/c-family/c-pragma.c.jj 2014-03-06 13:05:17.000000000 +0100 +++ gcc/c-family/c-pragma.c 2014-03-13 14:39:44.200586561 +0100 @@ -263,6 +263,7 @@ apply_pragma_weak (tree decl, tree value if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl) && !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */ + && DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) warning (OPT_Wpragmas, "applying #pragma weak %q+D after first use " "results in unspecified behavior", decl); @@ -280,7 +281,7 @@ maybe_apply_pragma_weak (tree decl) /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed. */ /* No weak symbols pending, take the short-cut. */ - if (!pending_weaks) + if (vec_safe_is_empty (pending_weaks)) return; /* If it's not visible outside this file, it doesn't matter whether it's weak. */ @@ -292,7 +293,13 @@ maybe_apply_pragma_weak (tree decl) if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL) return; - id = DECL_ASSEMBLER_NAME (decl); + if (DECL_ASSEMBLER_NAME_SET_P (decl)) + id = DECL_ASSEMBLER_NAME (decl); + else + { + id = DECL_ASSEMBLER_NAME (decl); + SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE); + } FOR_EACH_VEC_ELT (*pending_weaks, i, pe) if (id == pe->name) @@ -313,7 +320,7 @@ maybe_apply_pending_pragma_weaks (void) pending_weak *pe; symtab_node *target; - if (!pending_weaks) + if (vec_safe_is_empty (pending_weaks)) return; FOR_EACH_VEC_ELT (*pending_weaks, i, pe) --- gcc/testsuite/c-c++-common/pr36282-1.c.jj 2014-03-13 14:31:03.752580696 +0100 +++ gcc/testsuite/c-c++-common/pr36282-1.c 2014-03-13 14:31:56.110270219 +0100 @@ -0,0 +1,12 @@ +/* PR middle-end/36282 */ +/* { dg-do compile } */ + +#pragma weak bar + +extern void *baz (void *dest, const void *src, __SIZE_TYPE__ n); +extern __typeof (baz) baz __asm("bazfn"); /* { dg-bogus "asm declaration ignored due to conflict with previous rename" } */ + +void +foo (void) +{ +} --- gcc/testsuite/c-c++-common/pr36282-2.c.jj 2014-03-13 14:31:03.752580696 +0100 +++ gcc/testsuite/c-c++-common/pr36282-2.c 2014-03-13 14:32:01.264247933 +0100 @@ -0,0 +1,10 @@ +/* PR middle-end/36282 */ +/* { dg-do compile } */ + +extern void *baz (void *dest, const void *src, __SIZE_TYPE__ n); +extern __typeof (baz) baz __asm("bazfn"); /* { dg-bogus "asm declaration ignored due to conflict with previous rename" } */ + +void +foo (void) +{ +} --- gcc/testsuite/c-c++-common/pr36282-3.c.jj 2014-03-13 14:31:03.752580696 +0100 +++ gcc/testsuite/c-c++-common/pr36282-3.c 2014-03-13 14:32:07.243209260 +0100 @@ -0,0 +1,13 @@ +/* PR middle-end/36282 */ +/* { dg-do compile } */ + +void bar (void); +#pragma weak bar + +extern void *baz (void *dest, const void *src, __SIZE_TYPE__ n); +extern __typeof (baz) baz __asm("bazfn"); /* { dg-bogus "asm declaration ignored due to conflict with previous rename" } */ + +void +foo (void) +{ +} --- gcc/testsuite/c-c++-common/pr36282-4.c.jj 2014-03-13 14:31:03.752580696 +0100 +++ gcc/testsuite/c-c++-common/pr36282-4.c 2014-03-13 14:32:12.831177682 +0100 @@ -0,0 +1,13 @@ +/* PR middle-end/36282 */ +/* { dg-do compile } */ + +#pragma weak bar +void bar (void); + +extern void *baz (void *dest, const void *src, __SIZE_TYPE__ n); +extern __typeof (baz) baz __asm("bazfn"); /* { dg-bogus "asm declaration ignored due to conflict with previous rename" } */ + +void +foo (void) +{ +} Jakub