Can't understand the declaration #3 in the Exa

2019-01-26 05:05发布

问题:

[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 have two comments about this paragraph:

  1. The static int i = 0;declaration in the global scope is not visible inside the block containing the declaration extern int i; (#3). Therefore we can only say that this latter declaration has external linkage, i.e., we can't associate it with declaration #1.
  2. Otherwise, if the declaration static int i; is considered visible by the declaration #3, than according to the text in the paragraph, the block scope declaration declares the same entity and receives the linkage of the previous declaration, that is, internal linkage, and not external linkage, as stated in the Example.

What am I missing here?

回答1:

This is subject to active issue 426 which says:

An example in 3.5 [basic.link] paragraph 6 creates two file-scope variables with the same name, one with internal linkage and one with external.

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
      }
}  

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 original proposal was to make it undefined behavior:

We agree that this is an error. We propose to leave the example but change the comment to indicate that line //3 has undefined behavior, and elsewhere add a normative rule giving such a case undefined behavior.

but the last two comments say:

According to 3.5 [basic.link] paragraph 9, the two variables with linkage in the proposed example are not “the same entity” because they do not have the same linkage. Some other formulation will be needed to describe the relationship between those two variables.

and:

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.

The latest comments did not propose a new wording and it has not been updated since 2006, so at best we can say the current thinking is that this is ill-formed.

For reference the draft C99 standard 6.2.2.7/7 says:

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.