OK, I've submitted #83271 on this [1]. Thanks for the standard reference, it turns out I've been looking into the wrong chapter. Alexey [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83271 On Mon, Dec 4, 2017 at 5:02 PM, Jonathan Wakely <jwakely.gcc@xxxxxxxxx> wrote: > On 3 December 2017 at 21:36, Alexey Salmin wrote: >> Hello! >> >> I'm a bit puzzled with the g++ behavior which looks inconsistent. >> Consider the following C++ code: >> >> extern const int x; // typically comes from a header file >> const int x = 0; >> >> It produces a global symbol with g++ even though in C++ "const" on >> variables implies "static". The definition inherits the "extern" >> specifier from the declaration. So far so good. > > Right, it only implies static if it hasn't been explicitly declared with extern. > >> Now if you need to provide a weak definition it won't compile: >> >> extern const int x; >> const int __attribute__((weak)) x = 0; >> >> error: weak declaration of ‘x’ must be public >> >> Adding "extern" to the second line fixes it. It's not clear why g++ >> considers the definition to be public in the first case (strong def) >> and private in the second (weak def). Both cases work fine in clang++. >> >> Is it a bug in g++? > > Yes, I think so. > >> Another question: even with a strong symbol, it's not completely clear >> whether omitting "extern" on the second line produces a valid C++ code >> (it certainly does for plain C). Standard states that using "extern" >> and "static" in different declarations of the same symbol is an error. >> However, there's no mention of "const" in that section, so I'm not >> sure how these two work together. > > The standard is clear, see [basic.link] > > "A name having namespace scope (6.3.6) has internal linkage if it is > the name of [...] a non-inline variable of non-volatile > const-qualified type that is neither explicitly declared extern nor > previously declared to have external linkage; or [...]" > > It has been previously declared extern, so it doesn't have internal linkage.