无法理解[basic.link]/6 C++ 14的例子中的声明#3

Leo*_*eon 13 c++ declaration extern language-lawyer c++14

[basic.link]/6

在块作用域中声明的函数的名称和由块作用域extern声明声明的变量的名称具有链接.如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接.如果存在多个这样的匹配实体,则该程序是不正确的.否则,如果未找到匹配的实体,则块范围实体将接收外部链接.[示例:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

i此程序中有三个对象.具有内部链接的对象由全局范围内的声明引入(第1行),具有自动存储持续时间的对象并且没有由第2行上的声明引入的链接,以及具有静态存储持续时间和由声明引入的外部链接的对象在第3行. - 末端的例子]

我对这一段有两点评论:

  1. static int i = 0;全局范围内的声明在包含声明的块(#3)中可见extern int i;.因此,我们只能说后一种宣言具有外部联系,即我们不能将其与宣言#1联系起来.
  2. 否则,如果声明static int i;被声明#3视为可见,则根据段落中的文本,块作用域声明声明相同的实体并接收前一声明的链接,即内部链接,而不是外部链接,如实施例中所述.

我在这里错过了什么?

Sha*_*our 9

这取决于活跃的问题426,其中说:

3.5 [basic.link]第6段中的示例创建了两个具有相同名称的文件范围变量,一个具有内部链接,另一个具有外部.

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
      }
}  
Run Code Online (Sandbox Code Playgroud)

这真的是我们想要的吗?C99具有6.2.2.7/7,其给出了在同一翻译单元中具有内部和外部链接的标识符的未定义行为.C++似乎没有等价物.

最初的提议是将其定义为未定义的行为:

我们同意这是一个错误.我们建议保留示例,但更改注释以指示第//行具有未定义的行为,并在其他地方添加规范规则,给出这种情况未定义的行为.

但最后两条评论说:

根据3.5 [basic.link]第9段,在拟议的例子中带有联系的两个变量不是"同一个实体",因为它们没有相同的联系.将需要一些其他表述来描述这两个变量之间的关系.

和:

CWG决定最好使这种链接不匹配的程序形成错误而不是具有未定义的行为.

最新的评论没有提出新的措辞,自2006年以来一直没有更新,所以最多我们可以说当前的想法是这是不正确的.

作为参考,C99标准草案6.2.2.7/7说:

如果在翻译单元内,同一标识符同时出现内部和外部链接,则行为未定义.