Question

clang, gcc and VS2013 all complain about redefinition of w in main(), but I couldn't find in the Standard anything disallowing this.

namespace N {
    extern int j;
    int j;
}

int main()
{
    extern int w;
    int w;
}

These paragraphs say something about the use of an extern declaration in block scope, but they don't seem to justify the error message:

§3.3.1/4

Given a set of declarations in a single declarative region, ...

[ Note: These restrictions apply to the declarative region into which a name is introduced, which is not necessarily the same as the region in which the declaration occurs. In particular, elaborated-type-specifiers (7.1.6.3) and friend declarations (11.3) may introduce a (possibly not visible) name into an enclosing namespace; these restrictions apply to that region. Local extern declarations (3.5) may introduce a name into the declarative region where the declaration appears and also introduce a (possibly not visible) name into an enclosing namespace; these restrictions apply to both regions. —end note ]

§3.3.2/10

[ Note: Friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace (7.3.1.2). Function declarations at block scope and variable declarations with the extern specifier at block scope refer to declarations that are members of an enclosing namespace, but they do not introduce new names into that scope. —end note ]

Was it helpful?

Solution

I believe this is mostly covered by §3.5/6.

In particular:

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 there is a visible declaration of an entity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, 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.

So, the extern int w; declares a w that has linkage (external linkage, in this case, since no matching entity is visible at that point).

Then you attempt to define a local w which has no linkage (by §3.5/8).

That gives two declarations of the same name at the same scope, but with different linkages. That's prohibited by §3.3.1/4:

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,

  • they shall all refer to the same entity, or all refer to functions and function templates; or
  • exactly one declaration shall declare a class name or enumeration name that is not a typedef name and the other declarations shall all refer to the same variable or enumerator, or all refer to functions and function templates; in this case the class name or enumeration name is hidden (3.3.10).

Neither refers to a function, function template, class name, or enumeration name, so none of these "escape clauses" applies. The two declarations must refer to the same entity, which must have both external linkage and no linkage. Since that's impossible, the code is ill-formed.

OTHER TIPS

Here is my interpretation: In §3.3.1/3 the standard says:

The names declared by a declaration are introduced into the scope in which the declaration occurs, except that the presence of a friend specifier (11.3), certain uses of the elaborated-type-specifier (7.1.6.3), and using-directives (7.3.4) alter this general behavior.

As extern declarations are not listed as exception, the name is introduced in the block scope, which is why you get the error when you try to redeclare it.

The paragraph you quoted says

but they do not introduce new names into that scope.

which is a bit ambiguous, as both block scope and namespace scope are mentioned. The standard would contradict itself if it referred to block scope, so I assume that namespace scope is meant.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top