11

Apparently from §3.3.1/4, this snippet doesn't compile because it contains two different entities with the same name A in the global namespace, extern int A; and static int A = 101;. That is, one has external and the other has internal linkage.

live example

#include <iostream>
extern int A;
static int A = 101;
class A{};
int main()
{
    std::cout << A << '\n';
}

Why then, does this code compile?

#include <iostream>
static int A = 101;
extern int A;
class A{};
int main()
{
    std::cout << A << '\n';
}

Edit

I think the accepted answer for the question, of which this one is considered a dup, basically says that in the second snippet, variable A still has internal linkage, despite the extern declaration. But this is in disagreement with paragraph §3.5/4 that I mentioned below in a comment to @dyp.

§3.5/4:

An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of

— a variable; or

...

Edit 1:

The OP uses §3.5/6 to justify his answer to the other question.

§3.5/6 (emphasis mine):

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.

It's clear this answer doesn't apply to the snippets shown on my question, as the declarations of the variable A are not block scope declarations.

Edit 2:

This issue with "ready" status says that §7.1.1/7 should be deleted because it's false.

Wake up Brazil
  • 3,421
  • 12
  • 19
  • *"Why then, does this code compile?"* With which compiler+version? – dyp Sep 28 '14 at 13:36
  • The Standard doesn't require `extern` variables (at namespace scope) to have external linkage, as far as I can see. I think the second declaration "inherits" the linkage of the first declaration in the second example. – dyp Sep 28 '14 at 13:40
  • But then, why the first code doesn't compile? – Wake up Brazil Sep 28 '14 at 13:43
  • I am not entirely certain about what the Standard says here. I think what happens is that in the first example, `A` in the first declaration is not found, and hence a name *with external linkage* is introduced. The `static` in `static int A;` however requires *internal linkage*, hence the error. In the second example, `A` in `extern int A;` finds the existing name with *internal* linkage, and somehow adopts the internal linkage. – dyp Sep 28 '14 at 13:45
  • Possibly related: http://open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1603 – dyp Sep 28 '14 at 13:47
  • I don't think this issue applies here. I'm not using unnamed namespaces and besides that, §3.3.1/4 is not mentioned in there. – Wake up Brazil Sep 28 '14 at 13:51
  • @WakeupBrazil I cited that defect report since there are some known defects related to linkage and `extern`; the specification will most probably change here. – dyp Sep 28 '14 at 14:04
  • I don't like wielding my Mjölnir, but I agree with @remyabel It's a good question, but a duplicate. – dyp Sep 28 '14 at 14:10
  • That's what I think is a problem with SO. The question may be duplicate but AFAICT it still doesn't have a correct answer that is supported by the Standard, simply because §7.1.1/7 is false. – Ayrosa Oct 20 '14 at 12:05

1 Answers1

4

The extern specifier does not require that the name has external linkage.

The first example

extern int A; is a declaration of a name A with external linkage - but the external linkage is implied since it's a declaration at namespace scope (outside of an unnamed namespace).

static int A; declares a name with internal linkage.

The two declarations disagree about the linkage, hence the error.

The second example

Here, we first declare static int A;, i.e. a name A with internal linkage.

The declaration extern int A; doesn't declare A with external linkage, it merely redeclares a name that is found via name lookup.

[dcl.stc]/7

The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope, each declaration declaring the same variable name or the same overloading of a function name shall imply the same linkage. Each function in a given set of overloaded functions can have a different linkage, however.

[ Example:

static char* f(); // f() has internal linkage
char* f() // f() still has internal linkage
{ /* ... */ }

char* g(); // g() has external linkage
static char* g() // error: inconsistent linkage
{ /* ... */ }

// [left out some examples with `inline`]

static void n();
inline void n(); // internal linkage

static int a; // a has internal linkage
int a; // error: two definitions

static int b; // b has internal linkage
extern int b; // b still has internal linkage

int c; // c has external linkage
static int c; // error: inconsistent linkage

extern int d; // d has external linkage
static int d; // error: inconsistent linkage

-- end example ]

dyp
  • 38,334
  • 13
  • 112
  • 177
  • I'm not entirely sure *where* the Standard specifies that the `extern` declaration in the second example adopts the linkage of the first, though. – dyp Sep 28 '14 at 13:58
  • I think 3.5.6: `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.` –  Sep 28 '14 at 13:58
  • `The declaration extern int A; doesn't give A internal linkage, it merely redeclares the name.` This doesn't seem to agree with §3.5/4: `An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of — a variable;` – Wake up Brazil Sep 28 '14 at 13:59
  • @remyabel The OP's example is not about block-scope variables. – dyp Sep 28 '14 at 14:02
  • @WakeupBrazil Yes, I think there is something missing here about redeclarations. I think the examples I quoted in my answer state the intent. – dyp Sep 28 '14 at 14:05