https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111708

--- Comment #4 from Kirill Frolov <k.frolov at samsung dot com> ---
With updated source ICC still gives an error. 
MSVC works from my point of view correcly, same as Clang.

Lets see to a C-standard
(https://files.lhmouse.com/standards/ISO%20C%20N2176.pdf),
section 6.2.2 states that:

| 4) For an identifier declared with the storage-class specifier extern
| in a scope in which a prior declaration of that identifier is visible [31]
| if the prior declaration specifies internal or external linkage,
| the linkage of the identifier at the later declaration is the same as
| the linkage specified at the prior declaration. If no prior declaration
| _is_ _visible_, or if the prior declaration specifies no linkage, then the
| identifier has external linkage.

| [31] As specified in 6.2.1, the later declaration might hide the
| prior declaration.

Lets see section 6.2.1:

| 4) ... Within the inner scope, the identifier designates the entity
|   declared in the inner scope; the entity declared in the outer scope
|   is hidden (and _not_ _visible_) within the inner scope.

As a result, I must conclude that GCC generates code right, but
Clang, MSVC and ICC works incorrectly. But this happens with "-Os"
options.

With "-O0" option GCC generates _wrong_ _code_, as it avoids calling
of _external_ function (https://godbolt.org/z/6GbPdc9vT):

main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], edi
        mov     QWORD PTR [rbp-16], rsi
        mov     eax, DWORD PTR [rbp-4]
        mov     edi, eax
        call    f
        leave
        ret
f:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     DWORD PTR [rbp-20], edi
        mov     eax, DWORD PTR [rbp-20]
        mov     DWORD PTR [rbp-4], eax
        cmp     DWORD PTR [rbp-4], 0
        jg      .L4
        mov     eax, 0
        jmp     .L5
.L4:
        mov     eax, DWORD PTR [rbp-4]
        sub     eax, 1
        mov     edi, eax
        call    f
.L5:
        leave
        ret

In any case, GCC generated different code with -O0 and -Os, and such behaviour
is definitely a bug.

Reply via email to