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.