2
votes

In the C Standard (6.2.2 Linkages of identifiers) there is written enough clear

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.

However I can not find a similar statement in the C++ Standard looking through its section 6.5 Program and linkage.

The question arises due to the following quote from the C++ 17 Standard

3 A name having namespace scope (6.3.6) has internal linkage if it is the name of

(3.2) — a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or

Now consider the following declarations

const int x = 100;
extern const int x;

So it is unclear whether the code is ill-formed or the constant x has internal linkage though it is declared with the specifier extern or the Standard has a defect in the description of this paragraph or I missed the quote in the C++ Standard similar to the quote from the C Standard.

1
If you look at section 10.1.1 Storage Class Specifiers, paragraph 6, there are a few examples. There isn't one that matches your case, but there is a static int b; // b has internal linkage extern int b; // b still has internal linkage one that comes close.1201ProgramAlarm
@1201ProgramAlarm Examples are not the description.:) Apart from example there must be a description saying that these examples are valid.Vlad from Moscow
Wow. I wasn't aware of this subtlety (i.e. that the order I always used "intuitively" is that important). I made a sample on coliru to illustrate this.Scheff's Cat
Well, [dcl.stc]/6 does contain normative sentence saying that the linkages must agree.cpplearner
@cpplearner Again the quote does not say about using the specifier extern in a latter declaration. It assumes that this was already described.Vlad from Moscow

1 Answers

0
votes

Maybe a defective in basic.link#6, After looking at the dcl.stc#5, it says:

For the linkage of a name declared with an extern specifier, see [basic.link].

However, the rule about declaration declared with a extern specifier is mostly in [basic.link#6], which is:

The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage. If such a declaration is attached to a named module, the program is ill-formed. If there is a visible declaration of an entity with linkage, ignoring entities declared outside the innermost enclosing namespace scope, such that the block scope declaration would be a (possibly ill-formed) redeclaration if the two declarations appeared in the same declarative region, the block scope declaration declares that same entity and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage. If, within a translation unit, the same entity is declared with both internal and external linkage, the program is ill-formed.

It sounds like that these rules only applies to block scope declaration instead of applying to namespace scope declaration that declared with extern specifier. Except for this paragraph, there is no more rule in section [basic.link] that indicates what the linkage of a name declared by extern specifier. Unlike what says in C standard, the rules apply to whatever declarations declared with extern specifier(regardless of what kind of scopes where the declarations declared).