In the following it is clear from the example in the C++ Standard 3.5.#6 that the block extern declaration refers to a separate object, i.e. that there is an internal-linkage i and an external-linkage i in the same TU. As in C a block extern that does not 'see' an internal-linkage declaration (as in this case where hidden by the formal) gets external linkage; C 6.2.2#7 says that having internal and external linkage for the same name is UB but no such prohibition applies in C++. G++ incorrectly resolves the block extern to the file-scope object (which in C++ is internal linkage) but should instead generate an external reference for the i object that is declared in the block extern. #include <stdio.h> const int i = 123; int main(int i, char **) { { extern int i; printf("i = %u\n", i); } return 0; }
It seems to work correctly for me (for -fPIC and without I will only show with): (without the extern int i;): main: pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp call .LPR3 addl $_GLOBAL_OFFSET_TABLE_, %ebx andl $-16, %esp movl $0, %eax subl %eax, %esp movl 8(%ebp), %eax movl %eax, 4(%esp) leal .LC0@GOTOFF(%ebx), %eax movl %eax, (%esp) call printf@PLT movl $0, %eax movl -4(%ebp), %ebx leave ret See how there is no reference to i, meaning that i is already "inlined". Here are the asm for with the "extern int i;": main: pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp call .LPR3 addl $_GLOBAL_OFFSET_TABLE_, %ebx andl $-16, %esp movl $0, %eax subl %eax, %esp movl i@GOT(%ebx), %eax movl (%eax), %eax movl %eax, 4(%esp) leal .LC0@GOTOFF(%ebx), %eax movl %eax, (%esp) call printf@PLT movl $0, %eax movl -4(%ebp), %ebx leave ret See how it goes through GOT,meaning it will pick up the extern one and not really always the local one.
1) add a second translation unit extern int i = 5; 2) compile, link, and run the two translation units. If it prints 5 it's ok, if it prints 123 it's broken. For me it prints 123.
This looks related to DR 426: <http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#426>. so confirming to ...
Suspended as it is still active (because they are drafting the resulotion) but it looks like it is going to be undefined behavior so GCC is "right".
How about the below C++ program? According to recent draft, the func() in //2: is clearly "internal linkage", but g++ resolve it as external linkage. static void func() { } int main() { extern void func(); func(); // 1: { extern void func(); func(); //2: } return 0; }
> [Adopted at the February/March, 2017 meeting.] The defect report has now been adopted for C++20, and the code is illformed (invalid). I don't know if this is illformed with no diagnostic required or not but I suspect it requires a diagnostic. So now this is an accepts invalid. Also note clang rejects the example program in comment #0 as illformed already as the types are different const int vs int.
*** Bug 94764 has been marked as a duplicate of this bug. ***