Bug 14769 (cwg426) - [DR 426] Block extern incorrectly resolved to file-scope internal linkage object
Summary: [DR 426] Block extern incorrectly resolved to file-scope internal linkage object
Status: NEW
Alias: cwg426
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.3.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
: 94764 (view as bug list)
Depends on:
Blocks: c++-core-issues 94764
  Show dependency treegraph
 
Reported: 2004-03-29 11:59 UTC by algrant
Modified: 2021-12-17 11:40 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-10-02 20:56:31


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description algrant 2004-03-29 11:59:01 UTC
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;
}
Comment 1 Andrew Pinski 2004-03-29 12:15:10 UTC
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.
Comment 2 algrant 2004-03-29 14:31:08 UTC
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.

Comment 3 Andrew Pinski 2004-03-30 18:07:38 UTC
This looks related to DR 426: <http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#426>.
so confirming to ...
Comment 4 Andrew Pinski 2004-03-30 18:09:16 UTC
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".
Comment 5 Nan Wang 2009-11-26 03:31:29 UTC
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;
}
Comment 6 Andrew Pinski 2021-12-17 11:38:59 UTC
> [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.
Comment 7 Andrew Pinski 2021-12-17 11:40:42 UTC
*** Bug 94764 has been marked as a duplicate of this bug. ***