Open ec04fc15-fa35-46f2-80e1-5d271f2ef708 opened 6 years ago
@zygoloid, is there wording in the C++ standard that specifies clear intent for case 1? I've been looking, but I haven't been able to find wording that states whether explicit specializations inherit the linkage of the primary template.
Thanks to Stack Overflow user user17732522 for directing me to the following wording in their comment on https://stackoverflow.com/questions/78956038/why-does-specialization-of-a-static-variable-template-result-in-multiple-definit/78956833.
Per [temp.expl.spec]p4:
An explicit specialization does not introduce a name ([basic.scope.scope]). ...
Per [basic.link]p2:
A name can have external linkage, module linkage, internal linkage, or no linkage, as determined by the rules below.
That supports the claim that Clang (and GCC) are (still) not treating explicit specializations of variable templates correctly as demonstrated at https://godbolt.org/z/h4a6e6Mhb (that link also tries to demonstrate MSVC behavior but fails to do so because of https://github.com/compiler-explorer/compiler-explorer/issues/6742); as reported, Clang (and GCC) emit the symbol for the explicit specialization with external linkage. I manually tested MSVC and found that it is doing something I find quite surprising; it emits the explicit specialization symbol as COMDAT and fails the second assert.
Right. Linkage is a property of names, so while templates have a notion of linkage, their specializations do not, and two specializations are the same if their templates are the same (taking the linkage of the template into account) and the template arguments are the same (taking the linkage of the template arguments into account). For case 1, n
has internal linkage, so its specializations should not be visible outside that translation unit, which we should implement by giving the corresponding symbols internal linkage.
For reference, here are related bug reports filed against gcc and MSVC:
Extended Description
Case 1:
Case 2:
Case 3:
For case 1, clang should treat
n<0>
as being an internal-linkage variable, but it actually gives it external linkage.For case 2 and 3, clang should reject ([dcl.stc]p3: A
storage-class-specifier
other thanthread_local
shall not be specified in an explicit specialization).We appear to get this right for function templates and for explicit instantiations of variable templates.