Standards N3242 (C++ 11 draft) and N3797 (C++ 14 draft) both have the same paragraph.
§ 3.5 Program and linkage [basic.link]
¶ 6
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. [ Example:
static void f();
static int i = 0; // #1
void g() {
extern void f(); // internal linkage
int i; // #2 i has no linkage
{
extern void f(); // internal linkage
extern int i; // #3 external linkage
}
}
There are three objects named i
in this program. The object with internal linkage introduced by the
declaration in global scope (line #1), the object with automatic storage duration and no linkage introduced by the declaration on line #2
, and the object with static storage duration and external linkage introduced by the declaration on line #3.
— end example
]
I feel something is wrong with the i object example, it does not support what is said in the paragraph before, right?
In my opinion it must be two i objects, one with internal linkage (#1 and #3) and one with no linkage (#2).
Am I correct? Is it a mistake in the standard, the example is wrong?
In contrast, standard N4659 (C++ 17 draft) put it more correctly, in my opinion.
§ 6.5 Program and linkage [basic.link]
¶ 6
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. If, within a translation unit, the same entity is declared with both internal and
external linkage, the program is ill-formed. [ Example:
static void f();
static int i = 0; // #1
void g() {
extern void f();
// internal linkage
int i; // #2: i has no linkage
{
extern void f(); // internal linkage
extern int i; // #3: external linkage, ill-formed
}
}
Without the declaration at line #2, the declaration at line #3 would link with the declaration at line #1.
Because the declaration with internal linkage is hidden, however, #3 is given external linkage, making the
program ill-formed.
— end example
]
Some testing
static void f();
static int i = 10; // #1
void g() {
extern void f(); // internal linkage
std::cout << i << std::endl;
int i = 2; // #2 i has no linkage
std::cout << i << std::endl;
{
extern void f(); // internal linkage
std::cout << i << std::endl;
extern int i; // #3 external linkage
std::cout << i << std::endl;
}
}
int main() {
g();
return 0;
}
This code produces 10 2 2 10 in clang-5.0 with any of -std value from c++-11, c++-14, c++17.
What basically support the wording of C++ 11 and 14 drafts.
Apparently, this did not change to a compilation error with c++17 value. Is clang not compliant with C++ 17 on this point?
That was issue 426:
Is this really what we want? C99 has 6.2.2.7/7, which gives undefined behavior for having an identifier appear with internal and external linkage in the same translation unit. C++ doesn't seem to have an equivalent.
[…] The CWG decided that it would be better to make a program with this kind of linkage mismatch ill-formed instead of having undefined behavior.
That is, it was decided that if a name has linkage, it shall be consistent. Implementations probably haven't implemented this yet.
Related
I compile this program by g++ and clang++. There has a difference:
g++ prints 1, but clang++ prints 2.
It seems that
g++: the extern varible is defined in the shortest scope.
clang++: the extern varible is defined in the shortest global scope.
Does C++ spec has any specification about that?
main.cpp
#include <iostream>
static int i;
static int *p = &i;
int main() {
int i;
{
extern int i;
i = 1;
*p = 2;
std::cout << i << std::endl;
}
}
other.cpp
int i;
version: g++: 7.4.0/ clang++:10.0.0
compilation: $(CXX) main.cpp other.cpp -o extern.exe
[basic.link/7] should be the relevant part of the Standard. In the current draft, it says:
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.
Note that the subsequent example almost exactly matches your case:
static void f();
extern "C" void h();
static int i = 0; // #1
void g() {
extern void f(); // internal linkage
extern void h(); // C language linkage
int i; // #2: i has no linkage
{
extern void f(); // internal linkage
extern int i; // #3: external linkage, ill-formed
}
}
So, the program should be ill-formed. The explanation is below the example:
Without the declaration at line #2, the declaration at line #3 would link with the declaration at line #1. Because the declaration with internal linkage is hidden, however, #3 is given external linkage, making the program ill-formed.
Clang gives a right result. Even though per the rule of the current standard, the program shouldn't be ill-formed. Note the emphasized wording:
If, within a translation unit, the same entity is declared with both internal and external linkage, the program is ill-formed.
The entity declared at #3 and the entity declared at #1 are not the same entity, because of the below rule:
Two names that are the same and that are declared in different scopes shall denote the same variable, function, type, template or namespace if
both names have external linkage or else both names have internal linkage and are declared in the same translation unit; and
[...]
They're not, one has internal linkage and the other has external linkage, so they do not denote the same entity, hence the code does not violate the [basic.link#6]. Moreover, the example follows [basic.link#6] remains a wrong interpretation about variable i.
P1787 has clarified this example. It says:
static void f();
extern "C" void h();
static int i = 0; // #1
void gq() {
extern void f(); // internal linkage
extern void g(); // ::g, external linkage
extern void h(); // C language linkage
int i; // #2: i has no linkage
{
extern void f(); // internal linkage
extern int i; // #3: <del>ex</del>internal linkage
}
}
Without Even though the declaration at line #2 hides the declaration at line #1, the declaration at line #3 would link with thestill redeclarationes at line #1. Because the declaration with and receives internal linkage is hidden, however, #3 is given external linkage, making the program ill-formed.
That means, In your example, the variable i introduced by declaration extern int i will link with the variable i declared by static int i. So, print 2 is the right behavior.
Is this program well-formed according to the c++ standard?
namespace X { int i = 1; }
using namespace X;
int main() {
extern int i;
i = 2;
}
I get different results with different compilers:
GCC and Clang gives a linker error: Undefined reference to i.
Visual c++ accepts the program.
[basic.link]/p6:
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.
X::i was declared outside the innermost enclosing namespace of the extern declaration (i.e the global namespace) so it is ignored. This means no declaration was found for i and therefore extern int i is a declaration of a new variable named i with external linkage.
Your program will compile, but will not link if the block-scope i is odr-used.
If there is multiple declarations possible and only one definition is allowed (ref), then why does the code below give me an error as multiple declaration for i in Turbo C++ compiler?
int main()
{
extern int i;
int i;
printf("The value of i is %d",i);
return 0;
}
Names either have linkage or they do not. Names with linkage can have either external or internal linkage.
"Linkage" is how the standard refers to the visibility of a name within a translation unit (a "translation unit" is simply the contents of a source file after preprocessing):
[basic.link]
(2.1) — When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
(2.2) — When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit.
(2.3) — When a name has no linkage , the entity it denotes cannot be referred to by names from other scopes
The linkage of declarations has to match, you are trying to redeclare (and define) a variable previously declared with external linkage as a variable with no linkage.
[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. [...]
int main()
{
extern int i; // declare i with external linkage
int i; // define i with no linkage **ERROR**
}
As the standard implies, if the declarations are in different scopes this isn't an issue as they refer to different names:
int main()
{
extern int i; // declare i with external linkage
{
int i; // define i with no linkage (shadows the previous declaration)
}
}
This also works fine at global scope because variables and functions at (non-anonymous) namespace scope without an explicit static declaration have external linkage:
extern int i; // declare i with external linkage
int i; // define i with external linkage
extern int j; // declare j with external linkage
static int j; // define j with internal linkage **ERROR**
static int k; // define k with internal linkage
extern int k; // declare k with internal linkage (!!)
int main()
{
}
The example with k is a little counterintuitive: a name declared with extern will only have external linkage if no previous declarations of the same name exist in the same scope, otherwise the linkage will be unchanged. This isn't an error, unless the name was previously declared with no linkage, which is why you cannot redeclare local variables for instance.
You can find a quick summary of the linkage rules on cppreference.
#user657267 has given a good answer, however, as your comment to his/her answer suggests, you are even more confused and you want a less technical answer. I will give it a try...
extern int i; says i is a 'global' variable defined somewhere else.
int i; says i is a 'local' variable defined in side the function.
The first statement is a declaration and the second is a declaration as well as a definition. The former statement says that i lives in the world named global and the other says that the i lives in the world named local. Even though they are from different worlds and thus different entities, inside function main() i.e. in side the local world their same names create confusion and thus the compiler complains about multiple declaration.
Imagine your school having two students with the same full name! One is from a different state/country. Wouldn't the principal complain about duplicate entries for the same person?
This question already has answers here:
Can a variable be declared both static and extern?
(4 answers)
Closed 8 years ago.
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.
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 ]
Given the statements below (emphasis mine) in §3.5/4 and in the Note [94] in §7.3.1.1/1, I'd like to have one single example of an entity declared in a unnamed namespace that has external linkage.
§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
a function; or
a named class (Clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage
purposes (7.1.3); or
a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for
linkage purposes (7.1.3); or
an enumerator belonging to an enumeration with linkage; or
a template.
Note [94] on §7.3.1.1/1:
Although entities in an unnamed namespace might have external linkage,
they are effectively qualified by a name unique to their translation
unit and therefore can never be seen from any other translation unit.
You are looking at a defect in the standard.
The change that makes unnamed namespace members have internal linkage happened fairly late in the C++11 standardization process, in November 2010 (CWG issue 1113). As a result, a number of places in the standard needs to be changed, but weren't. One of which is the footnote you quoted.
CWG issue 1603, currently in "ready" status (read: the resolution is likely to be adopted at the next committee meeting), will fix this and a number of other issues related to giving internal linkage to unnamed namespace members.
It's a good question because it's difficult to demonstrate. We can take advantage of other rules in the C++ Standard to show that a variable in an anonymous namespace can have external linkage.
Templating on an int* with external linkage will succeed while templating on an int* with internal linkage will fail.
#include <iostream>
namespace {
// not externally linked, won't compile
// const int i = 5;
// external linkage, compiles
extern int i;
int i = 5;
}
template<int* int_ptr>
struct temp_on_extern_linked_int {
temp_on_extern_linked_int() {
std::cout << *int_ptr << std::endl;
}
};
int main() {
temp_on_extern_linked_int<&i>();
}
As shown the program compiles and runs.
$ g++-4.8 main.cpp -o main
$ ./main
5
Uncommenting the other definition of i causes the compile to fail.
$ g++-4.8 main.cpp -o main
main.cpp: In function 'int main()':
main.cpp:17:30: error: '& {anonymous}::i' is not a valid template argument of
type 'int*' because '{anonymous}::i' does not have external linkage
temp_on_extern_linked_int<&i>();
^
The compiler is quite helpful. It explicitly states that because i doesn't have external linkage the compile failed.
The commented definition of i has internal linkage because it is qualified const without extern. (§3.4.6)
Variables at namespace scope that are declared const and not extern have internal linkage.
Part of the trick is not compiling as C++11.
Why did C++03 require template parameters to have external linkage?
For example
#include <iostream>
namespace
{
extern int x = 10;
void f( int y )
{
extern int x;
std::cout << x + y << std::endl;
}
}
int main()
{
int y = 15;
f( y );
return 0;
}
According to the C++ Standard
6 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