When an identifier has been used in an inline declaration subsequent renames of it are ignored. That used to work with gcc 3.4 and still works on i386 and ppc at least. This breaks building glibc. $ cat asm.c extern int foo (void); extern inline int bar (void) { return foo (); } extern __typeof (foo) foo __asm__ ("mumble"); int foobar (void) { return bar (); } $ gcc-4.0 -O -S asm.c asm.c:7: warning: asm declaration ignored due to conflict with previous rename $ grep mumble asm.s $ grep foo asm.s .global foobar# .proc foobar# foobar: br.call.sptk.many b0 = foo# .endp foobar#
DECL_ASSEMBLER_NAME_SET_P is true on ia64 for some reason which gets set when we call make_decl_rtl at c-decl.c:1757, why I don't know.
Confirmed.
The RTL is set because IA64 has ASM_OUTPUT_EXTERNAL defined. I think is related to changes which Zack made to c-decl.c.
The call to make_decl_rtl is from assemble_external.
Subject: Re: [4.0 regression] asm declaration ignored due to conflict with previous rename Hmm. Why are we calling assemble_external before EOF? zw
1764 if (!skip_evaluation) 1765 assemble_external (ref); #0 assemble_external (decl=0x41682934) at ../../gcc/varasm.c:1771 #1 0x00043c20 in build_external_ref (id=0x41686ac4, fun=1) at ../../gcc/c-typeck.c:1765 #2 0x0000534c in yyparse () at c-parse.y:626 #3 0x0000ac60 in c_parse_file () at c-parse.y:2903 #4 0x000a0728 in c_common_parse_file (set_yydebug=0) at ../../gcc/c-opts.c:1095 #5 0x0054dc6c in compile_file () at ../../gcc/toplev.c:985 #6 0x00550814 in do_compile () at ../../gcc/toplev.c:2069 #7 0x005508b0 in toplev_main (argc=3, argv=0xbffffd5c) at ../../gcc/toplev.c:2101 #8 0x000c69dc in main (argc=3, argv=0xbffffd5c) at ../../gcc/main.c:35 where the call to build_external_ref: primary: IDENTIFIER { if (yychar == YYEMPTY) yychar = YYLEX; $$.value = build_external_ref ($1, yychar == '('); $$.original_code = ERROR_MARK; }
This is the change that broke this: 2004-06-20 Zack Weinberg <zack@codesourcery.com> * c-common.h (has_c_linkage): New interface. ...
*** Bug 18632 has been marked as a duplicate of this bug. ***
It also happens on x86_64 and i386 if -O1 or -O0 is used. It has nothing to do with function inline.
Actually the example in comment #0 does not fail on x86 or ppc, only ia64 because of the reasons I outlined. Now the testcase in PR 18632 has always failed, we just did not warn about it.
Does this patch --- gcc/c-pragma.c.rename 2004-11-09 12:03:42.000000000 -0800 +++ gcc/c-pragma.c 2004-11-23 13:03:26.020304351 -0800 @@ -473,8 +473,11 @@ maybe_apply_renaming_pragma (tree decl, return asmname; /* If the DECL_ASSEMBLER_NAME is already set, it does not change, - but we may warn about a rename that conflicts. */ - if (DECL_ASSEMBLER_NAME_SET_P (decl)) + but we may warn about a rename that conflicts. + FIXME: the DECL_ASSEMBLER_NAME can be set to DECL_NAME (decl) + without renaming pragma nor asm declaration involved. */ + if (DECL_ASSEMBLER_NAME_SET_P (decl) + && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)) { const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); oldname = targetm.strip_name_encoding (oldname); make any senses? At least, it works with my testcases. -O0 and -O1 still complain with [hjl@gnu-4 gcc]$ ./xgcc -B./ -c x.i x.i:8: warning: foo renamed after being referenced in assembly [hjl@gnu-4 gcc]$ It may be OK since foo has been referenced in assembly. But I am not sure about languanges other than C.
Subject: Re: [4.0 regression] asm declaration ignored due to conflict with previous rename "hjl at lucon dot org" <gcc-bugzilla@gcc.gnu.org> writes: > ------- Additional Comments From hjl at lucon dot org 2004-11-23 21:13 ------- > Does this patch > > --- gcc/c-pragma.c.rename 2004-11-09 12:03:42.000000000 -0800 > +++ gcc/c-pragma.c 2004-11-23 13:03:26.020304351 -0800 > @@ -473,8 +473,11 @@ maybe_apply_renaming_pragma (tree decl, > return asmname; > > /* If the DECL_ASSEMBLER_NAME is already set, it does not change, > - but we may warn about a rename that conflicts. */ > - if (DECL_ASSEMBLER_NAME_SET_P (decl)) > + but we may warn about a rename that conflicts. > + FIXME: the DECL_ASSEMBLER_NAME can be set to DECL_NAME (decl) > + without renaming pragma nor asm declaration involved. */ This will not work. At this point ia64 has already emitted an external-reference directive for the old name into the assembly stream. The necessary fix is to prevent assemble_external from ever being called before EOF. zw
I have verified that my modification works on Linux/ia64, Linux/ia32 and Linux/x86_64.
A patch is posted at http://gcc.gnu.org/ml/gcc-patches/2004-11/msg01956.html
HJ's latest patch probably doesn't fix the problem entirely :-(, but it is certainly correct to allow "renames" which don't change anything.
Subject: Re: [4.0 regression] asm declaration ignored due to conflict with previous rename That's not what HJ's patch does, though. zw
DECL_ASSEMBLER_NAME_SET_P alone is not very reliable to check if a symbol has been renamed or not. There are /* The name of the object as the assembler will see it (but before any translations made by ASM_OUTPUT_LABELREF). Often this is the same as DECL_NAME. It is an IDENTIFIER_NODE. */ #define DECL_ASSEMBLER_NAME(NODE) decl_assembler_name (NODE) /* Returns nonzero if the DECL_ASSEMBLER_NAME for NODE has been set. If zero, the NODE might still have a DECL_ASSEMBLER_NAME -- it just hasn't been set yet. */ #define DECL_ASSEMBLER_NAME_SET_P(NODE) \ (DECL_CHECK (NODE)->decl.assembler_name != NULL_TREE) and /* The name of the object as the assembler will see it (but before any translations made by ASM_OUTPUT_LABELREF). Often this is the same as DECL_NAME. It is an IDENTIFIER_NODE. */ tree decl_assembler_name (tree decl) { if (!DECL_ASSEMBLER_NAME_SET_P (decl)) lang_hooks.set_decl_assembler_name (decl); return DECL_CHECK (decl)->decl.assembler_name; } Simply calling DECL_ASSEMBLER_NAME will make DECL_ASSEMBLER_NAME_SET_P to return TRUE.
Subject: Re: [4.0 regression] asm declaration ignored due to conflict with previous rename You continue not to get it. In this context, DECL_ASSEMBLER_NAME has been set because assemble_external has been called on the symbol. assemble_external is *not* a no-op on ia64. It emits a directive to the assembly output, using the name of the symbol. It is *not* safe to rename the symbol after that has happened. That you are not seeing a problem on ia64-linux is either because GAS isn't as picky as the reference assembler, or because your test case is not stringent enough. zw
But the call to assemble_external has been there since the very beginning.
Subject: Re: [4.0 regression] asm declaration ignored due to conflict with previous rename ... so this has always been broken, is that what you're saying? zw
Before your change it hasn't been a problem, apparently. But if you think it was wrong to begin with then please try to fix it.
Subject: Re: [4.0 regression] asm declaration ignored due to conflict with previous rename I'm hoping to have some time to work on this this week, but no promises. zw
There are only 2 assemblers supported on ia64, GNU assembler and Intel assembler. If GNU assembler is used, assemble_external is a no-op on Linux. On HPUX, the actual undefined symbol references are outputed at the very end. This patch http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02511.html will make Linux + Intel assembler to do the same. So, on ia64, it should be OK to rename a symbol even after assemble_external is called as long as it hasn't been actually used, in which case, you should get x.i:8: warning: foo renamed after being referenced in assembly
Subject: Bug 17982 CVSROOT: /cvs/gcc Module name: gcc Changes by: zack@gcc.gnu.org 2004-12-08 19:13:36 Modified files: gcc : ChangeLog cgraphunit.c tree.h varasm.c gcc/config/h8300: h8300.h Log message: PR 17982 * varasm.c (pending_assemble_externals): New static. (assemble_external_real): Meat of assemble_external split out to this new function. (process_pending_assemble_externals): New function. (assemble_external): Use gcc_assert. If flag_unit_at_a_time is true and the basic test passes, merely cons the decl onto the pending list to be handled later. * tree.h: Declare process_pending_assemble_externals. * cgraphunit.c (cgraph_optimize): Call it. * config/h8300/h8300.h: Do not define ASM_OUTPUT_EXTERNAL. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6750&r2=2.6751 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cgraphunit.c.diff?cvsroot=gcc&r1=1.90&r2=1.91 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree.h.diff?cvsroot=gcc&r1=1.664&r2=1.665 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/varasm.c.diff?cvsroot=gcc&r1=1.466&r2=1.467 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/h8300/h8300.h.diff?cvsroot=gcc&r1=1.179&r2=1.180
Fixed.
Uh, no, it's not fixed. It is, however, papered over adequately for 4.0. I'm turning this into a 4.1 enhancement PR. http://gcc.gnu.org/ml/gcc-patches/2004-12/msg00491.html explains what needs to happen for 4.1.
... and assigning to self.
Unassigning from Zack since he is gone now.
Subject: Bug 17982 Author: hjl Date: Tue Dec 12 03:58:52 2006 New Revision: 119764 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=119764 Log: 2006-12-11 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/17982 PR middle-end/20218 * cgraphunit.c (cgraph_optimize): Remove call to process_pending_assemble_externals. * config/elfos.h (ASM_OUTPUT_EXTERNAL): New. * config/ia64/hpux.h (TARGET_ASM_FILE_END): Removed. * config/ia64/ia64.c (ia64_asm_output_external): Rewritten. (ia64_hpux_add_extern_decl): Removed. (ia64_hpux_file_end): Likewise. (extern_func_list): Likewise. (extern_func_head): Likewise. * output.h (assemble_external): Update comments. (default_elf_asm_output_external): New. (maybe_assemble_visibility): New. * toplev.c (compile_file): Update comment. * varasm.c (assemble_external): Always put it on pending_assemble_externals. (maybe_assemble_visibility): Make it extern and return int. (default_elf_asm_output_external): New. Modified: trunk/gcc/ChangeLog trunk/gcc/cgraphunit.c trunk/gcc/config/elfos.h trunk/gcc/config/ia64/hpux.h trunk/gcc/config/ia64/ia64.c trunk/gcc/output.h trunk/gcc/toplev.c trunk/gcc/varasm.c
Subject: Bug 17982 Author: kazu Date: Sat Dec 16 02:47:27 2006 New Revision: 119959 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=119959 Log: Backport from mainline: gcc/ 2006-12-11 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/17982 PR middle-end/20218 * cgraphunit.c (cgraph_optimize): Remove call to process_pending_assemble_externals. * config/elfos.h (ASM_OUTPUT_EXTERNAL): New. * config/ia64/hpux.h (TARGET_ASM_FILE_END): Removed. * config/ia64/ia64.c (ia64_asm_output_external): Rewritten. (ia64_hpux_add_extern_decl): Removed. (ia64_hpux_file_end): Likewise. (extern_func_list): Likewise. (extern_func_head): Likewise. * output.h (assemble_external): Update comments. (default_elf_asm_output_external): New. (maybe_assemble_visibility): New. * toplev.c (compile_file): Update comment. * varasm.c (assemble_external): Always put it on pending_assemble_externals. (maybe_assemble_visibility): Make it extern and return int. (default_elf_asm_output_external): New. Modified: branches/csl/sourcerygxx-4_1/ChangeLog.csl branches/csl/sourcerygxx-4_1/gcc/cgraphunit.c branches/csl/sourcerygxx-4_1/gcc/config/elfos.h branches/csl/sourcerygxx-4_1/gcc/config/ia64/hpux.h branches/csl/sourcerygxx-4_1/gcc/config/ia64/ia64.c branches/csl/sourcerygxx-4_1/gcc/output.h branches/csl/sourcerygxx-4_1/gcc/toplev.c branches/csl/sourcerygxx-4_1/gcc/varasm.c
Created attachment 16755 [details] testcase.c:10: warning: y renamed after being referenced in assembly Compile test case with -funit-at-a-time gcc -v: Using built-in specs. Target: mingw32 Configured with: ../gcc-4.1.3/configure --prefix=/gcc-4.1.3 --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --build=mingw32 --enable-languages=c,c++ --enable-checking=release --enable-threads=win32 --disable-win32-registry --disable-nls --disable-shared Thread model: win32 gcc version 4.1.3 20071015 (prerelease)
I've been told that this is related to the test case I just attached
(In reply to comment #32) > I've been told that this is related to the test case I just attached Your testcase is more closely related to PR 38054. Danny
The FIXME here is this one in varasm.c: ------------------------------- /* We delay assemble_external processing until the compilation unit is finalized. This is the best we can do for right now (i.e. stage 3 of GCC 4.0) - the right thing is to delay it all the way to final. See PR 17982 for further discussion. */ static GTY(()) tree pending_assemble_externals; ------------------------------- According to http://gcc.gnu.org/ml/gcc-patches/2004-12/msg00491.html: The *proper* solution to this problem is to remove all calls to assemble_external from the front ends and even the RTL expander; it should only be done from final.c and varasm.c as we are emitting assembly. $ grep assemble_external c* */*.[ch] ada/gcc-interface/*.[ch] calls.c: assemble_external (fndecl); calls.c: assemble_external_libcall (fun); cp/cp-tree.h: so that assemble_external will work properly. So we have this flag to objc/objc-act.c: assemble_external (objc_get_class_decl); objc/objc-act.c: assemble_external (func); objc/objc-act.c: assemble_external (objc_assign_global_decl); objc/objc-act.c: assemble_external (objc_assign_strong_cast_decl); objc/objc-act.c: assemble_external (super_class); I think the ones in calls.c are OK. So only ObjC still calls assemble_external. Iain?
(In reply to comment #34) > I think the ones in calls.c are OK. So only ObjC still calls > assemble_external. Iain? AFAICT, assemble_external () [no longer?] emits any assembly nor does it call DECL_ASSEMBLER_NAME: it seems to check for a weak function and add that to the weak functions list and then (if the target defines ASM_OUTPUT_EXTERNAL) adds the decl to the pending list which is output from assemble_pending_externals () called from toplev.c. varasm (assemble variable) says: /* Normally no need to say anything here for external references, since assemble_external is called by the language-specific code when a declaration is first seen. */ if (DECL_EXTERNAL (decl)) return; I would imagine that if this were replaced by: if (DECL_EXTERNAL (decl)) { assemble_external (decl); return; } we should be able to remove the calls in ObjC (I'll try this later). OTOH, I wonder if we have a case of a solved problem with the bug left open....? [BTW, I also have checking the status of 24777 on my TODO.]
This was fixed in 2012.