Use of extern in block scope - c++

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 ]

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.

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.

Related

why a structured binding does not potentially conflict with a variable

The newest standard has been modified to add the content of P1787. One rule about two declarations that potentially conflict is:
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]).
I don't know the meaning of wording "different entities" here. Does it mean these entities that has different kinds or mean that they are different entities determined by basic.link#8? The entities have these kinds:
An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.
Such for a example,
void fun(); //#1
extern int fun; //#2
int main(){}
If the wording "different entities" means the former, then #1 denotes a function and #2 denotes a variable, they're different kind of entities. And such two declaration are in the same scope, Hence they are ill-formed per:
The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other
However, if the differenct entities should be determined by [basic.link#8] instead of determing it according to kind of entities. Then, it also makes sense. Because, per [basic.link#8]
Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]), they correspond ([basic.scope.scope]), have the same target scope that is not a function or template parameter scope, and either
they appear in the same translation unit, or
they both declare names with module linkage and are attached to the same module, or
they both declare names with external linkage.
Since they're corresponding and have the same target scope, and also bullet 1 or bullet 3 is satisfied. So, #1 and #2 are the same entity. However, they violate the following rule:
For any two declarations of an entity E:
If one declares E to be a variable or function, the other shall declare E as one of the same type.
So, Regardless of how to understand "different entities", the first example is always ill-formed. These compilers indeed give a right dignosis.
However, consider the second example
#include <iostream>
struct D{
int m;
};
auto [x] = D{0}; //#1
void show(){
std::cout<<&x<<"\n";
}
int main(){
extern int x; //#2
std::cout<<&x<<"\n";
}
GCC prints the same address. Instead, Clang reports a link error.
Similarly, if "different entities" is the former opinion. Then #1 is a structured binding while #2 is a variable. According to this rule:
if the declaration inhabits a block scope S and declares a function ([dcl.fct]) or uses the extern specifier, the declaration shall not be attached to a named module ([module.unit]); its target scope is the innermost enclosing namespace scope, but the name is bound in S.
So, such two declarations has the same target scope. Hence, they should potentially conflict. If "different entities" is determined by [basic.link]. According to [basic.link#8], they are the same entity. However, it also violates
If one declares E to be a variable or function, the other shall declare E as one of the same type.
So, anyhow, the second example should be ill-formed. Why GCC gives the result that such two entity has the same address. Rather, Clang only gives a link error?
In addition, Is it necessary to add a precondition for [basic.link#8], that is, two entities should be first have the same kind?

what are lookup rules when a name occured before function's declarator-id?

#include <iostream>
typedef int Name;
Name func(int){
return 0;
}
int main(){
}
Consider the above code, I can't find a bullet in [basic.lookup.unqual] that can interpret how to lookup Name for definition of func. I will cite some potential rules here:
A name used in global scope, outside of any function, class or user-declared namespace, shall be declared before its use in global scope.
A name used in a user-declared namespace outside of the definition of any function or class shall be declared before its use in that namespace or before its use in a namespace enclosing its namespace.
In the definition of a function that is a member of namespace N, a name used after the function's declarator-id shall be declared before its use in the block in which it is used or in one of its enclosing blocks ([stmt.block]) or shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N's enclosing namespaces
Please note the emphasized parts, it seems that my case does not satisfy these bullets, because Function definitions have the form
function-definition:
attribute-specifier-seq(opt) decl-specifier-seq(opt) declarator virt-specifier-seq(opt) function-body
Let me analyze the first bullet. It says outside of any function,but according to the Function definitions rule, I think that Name is within the function(definition), bullet 1 isn't satisfied. Bullet 2 is similar with that of bullet 1. Bullet 3 says that the name used after the function's declarator-id, in my case, the Name is used before the function's declarator-id. So what's the rule about this case to find the unqualified name Name?
My confusions:
In my example ,the Name,func ,(int) and { return 0;}(function body) are all parts of that function definition,So:
what is outside of any function,such as the func in my example,where's area of outside of that function?
what is outside of the definition of any function,such as the func definition in my example,where's area of outside of the definition of that function?
I think that Name is within the function(definition), bullet 1 isn't satisfied.
Bullet 1 didn't say "function(definition)". It said "outside of any function". It doesn't specify declaration or definition; merely "outside of any function".
Since being inside or outside of a "function" is not a defined concept, it must be read as plain English. Is a function prototype "outside of the function"? Visually speaking, there's nothing special about a function prototype that is suggestive of an inside/outside distinction. By contrast, the function body's block scope does suggest an inside/outside distinction.
The intent of the text of course is quite obvious; it's talking about the function body. The rule equates "function", "class" and "namespace", all of which have a block that defines scoping for names. That is the most logical place for any inside/outside distinction, so it seems pretty obvious that it's saying that the global scope consists of everything that isn't in the scope of a function body, the scope of a class definition, or the scope of a namespace body.
So this can be easily handled with an editorial change.
Note that the committee recognizes the wording of this section (among others in that area) as somewhat defective, and there's a proposal for rewriting it into something more coherent in C++23. The new wording from the proposal completely rewrites this section.

Non-overloadable non-inline function definitions in different translation units

Let's say I have 2 TUs with 2 non-inline function definitions with external linkage which differ only in their return types.
Which paragraph(s) my program violates?
[basic.def.odr]/4 says:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required.
But
This paragraph says "that is odr-used" which may or may not be the case.
How do I tell if I define the same non-inline function in different TUs, after all? [over.dcl]/1 speaks about the same scope.
I believe you're looking for: [basic.link]/9:
Two names that are the same ([basic.pre]) and that are declared in different scopes shall denote the same variable, function, type, template or namespace if
both names have external or module linkage and are declared in declarations attached to the same module, or else both names have internal linkage and are declared in the same translation unit; and
both names refer to members of the same namespace or to members, not by inheritance, of the same class; and
when both names denote functions or function templates, the signatures ([defns.signature], [defns.signature.templ]) are the same.
If multiple declarations of the same name with external linkage would declare the same entity except that they are attached to different modules, the program is ill-formed; no diagnostic is required. [ Note: using-declarations, typedef declarations, and alias-declarations do not declare entities, but merely introduce synonyms. Similarly, using-directives do not declare entities. — end note ]
And [basic.link]/11:
After all adjustments of types (during which typedefs are replaced by their definitions), the types specified by all declarations referring to a given variable or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound ([dcl.array]). A violation of this rule on type identity does not require a diagnostic.
And [defns.signature]:
⟨function⟩ name, parameter-type-list ([dcl.fct]), and enclosing namespace (if any)
The return type isn't part of the signature, so you're violating the rule that same signature means same entity.
Generally speaking, all discussions of scope and name lookup in the standard are pretty broken until Davis "The Hero We Don't Deserve" Herring's work goes through.

Why does c++'s namespace scope also include file scope(in c)?

C(ISO/IEC 9899:2011) has no concept of namespace, when referring global variable's scope, the standard use file scope:
Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. If the declarator or type specifier that declares the identifier appears within the list of parameter declarations in a function prototype (not part of a function definition), the identifier has function prototype scope, which terminates at the end of the function declarator. If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
However, in c++(at least ISO/IEC 14882:2011), file scope is never used and use namespace scope instead:
The declarative region of a namespace-definition is its namespace-body. Entities declared in a namespace-body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace. A namespace member name has namespace scope. Its potential scope includes its namespace from the name's point of declaration onwards; and for each using-directive ([namespace.udir]) that nominates the member's namespace, the member's potential scope includes that portion of the potential scope of the using-directive that follows the member's point of declaration.
As we know, c++ is inspired a lot from C, so many definitions of terms also derive from c, though they are virtually two different languages now. IMO, there should be a reason that c++ use namespace scope instead of file scope, but I don't know. What's behind it?
The C++ standard doesn't mention file scope because it isn't trying to explain things in C terms. It defines and uses its own terms. In this case, it is under the definition of namespaces:
[basic.namespace]
2 The outermost declarative region of a translation unit is a
namespace; see [basic.scope.namespace].
This declarative region, in C++ terms, is the equivalent of C's file scope. The C++ standard uses these definitions because it intends to support namespace declarations, that allow us to partition this scope into smaller pieces.
C has no such feature, so it speaks only of things at file scope as the its outermost scope, because said definition is enough.
You're asking about file scope, not function scope.
The reason that C++ instead talks about namespace scope, is that it has namespaces. C doesn't. So of course C wouldn't have namespace scope.
C and C++ are different languages. C++ doesn't change things to "not be C", it changes things because its designers consider the changes to make the language inherently "better", either directly, or by consequence of the existence of some C++-only feature that in turn makes the language "better" than C.

Static and anonymous namespace [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unnamed/anonymous namespaces vs. static functions
Is this completely redundant, or may there be a reason to do this?
namespace {
static void f() {
...
}
}
It looks redundant to me -- either being declared static or being in an anonymous namespace means it has internal linkage.
§3.5/3:
A name having namespace scope (3.3.6) has internal linkage if it is the name of:
— a variable, function or function template that is explicitly declared static;
§3.5/4:
[...] An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal 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
So, as it is right now, it has internal linkage because it's explicitly declared static. If it wasn't explicitly declared static, it would have internal linkage because it's declared inside an unnamed namespace. Same effect either way.
Note that here I'm replying specifically about a function -- there are a few obscure cases where there's a difference when you're dealing with the name of a type (e.g., class/struct/union), but I don't know of any such thing that applies in the case of a function.
As far as what internal linkage really means, that's one of those places the standard is actually quite direct and clear. It's probably best to quote the definitions of all three possibilities (§3.5/2):
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.
When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
Note that the italics above match those in the standard, which is its way of saying that these sentences define what those phrases mean throughout the rest of the standard.