llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.85k stars 11.47k forks source link

An extern declaration in block scope refers to an incorrect variable. #18926

Open e48d0f12-b0d3-485a-93ce-75b823b0ccac opened 10 years ago

e48d0f12-b0d3-485a-93ce-75b823b0ccac commented 10 years ago
Bugzilla Link 18552
Version unspecified
OS All
CC @DougGregor,@zygoloid,@stbergmann

Extended Description

I think that the following sample code should return 4, but clang returns 1.

// --- main.cc begin ---
static int i = 1;       // #​1 i has internal linkage
int g() {
    int i = 2;          // #​2 i has no linkage
    {
        extern int i;   // #​3
        return i;
    }
}

int main()
{
    return g();
}
// --- main.cc end ---
// --- sub.cc begin ---
int i = 4;              // #​4 i has external linkage
// --- sub.cc end ---

According to C++11 standard 3.5 p6, #3 should refer to #4 because #1 is not visible from the point #3.

stbergmann commented 8 years ago

Some random related findings:

e48d0f12-b0d3-485a-93ce-75b823b0ccac commented 10 years ago

How about the sample code below? ICBW, I think that the following sample code is compiled incorrectly with clang 3.4 or later.

#include <iostream>

namespace NS {
    int i = 1;                          // #&#8203;1 has external linkage
}

static int i = 2;                       // #&#8203;2 has internal linkage

int main()
{
    using NS::i;                        // It refers to #&#8203;1, has external linkage.
    //extern int i;
    std::cout << i << std::endl;        // It refers to #&#8203;1, of course.
    {
        extern int i;                   // I think it should refer to #&#8203;1,
        std::cout << i << std::endl;    //  but it refers to #&#8203;2.
    }
}

Acoording to 7.3.3 p1, a using-declaration introduces a name as a synomym. And, according to 3.5 p6, if an declaration is visible and the declared entity has a linkage, an extern declaration refers to the entity, and it only ignores entities declared outside the innermost enclosing namespace scope. NS::i has external linkage, So I think that the extern int i; should refer to #1.

FYI, if a comment //extern int i; is uncommented, it refers to #1.

http://melpon.org/wandbox/permlink/vOM0nOdK36djcCHY

e48d0f12-b0d3-485a-93ce-75b823b0ccac commented 10 years ago

Oh... I cannot understand why the issue #426 is disregarded.

In addition, I found 3.3.1 p4's note. I think that it considers main.cc as ill-formed because #1 (has internal linkage) and #3 (has external linkage) refer to the different entities (3.5 p9) but has same name in a single declarative region (global namespace).

ec04fc15-fa35-46f2-80e1-5d271f2ef708 commented 10 years ago

Per the current resolution of http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#426, we should reject this code. (Per the former resolution, the example has undefined behavior.)