C++ block scope extern declaration linkage,混淆C++标准解释

标签 c++ clang c++14 language-lawyer c++17

标准 N3242 (C++ 11 草案)和 N3797 (C++ 14 draft) 两者有相同的段落。

§ 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对象的例子有问题,它不支持前面段落说的,对吧? 在我看来,它必须是两个 i 对象,一个具有内部链接(#1 和 #3),另一个没有链接(#2)。 我对么?是不是标准有误,例子有误?

相比之下,标准N4659 (C++ 17 草案)在我看来更正确。

§ 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 ]

一些测试

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

此代码在 clang-5.0 中使用 c++-11、c++-14、c++17 中的任何 -std 值生成 10 2 2 10 。 什么基本上支持C++ 11和14草案的写法。 显然,这并没有改变为 c++17 值的编译错误。 clang 在这一点上不符合 C++ 17 吗?

最佳答案

那是第 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.

也就是说,如果一个名称有链接,那么它应该是一致的。实现可能还没有实现这一点。

关于C++ block scope extern declaration linkage,混淆C++标准解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51444584/

相关文章:

c++ - 成员函数模板不在 clang 上编译,但在 GCC 上编译

clang - 编写 AST 匹配器以查找所有没有 break 语句的 case 语句

c++ - Xcode C++ 中文件流/fstream 的问题

c++ - 哪里有好的 DirectX (3D) DirectWrite 教程?

C++ 逐字符比较字符串

docker - 如何通过 LLVM build_docker_image.sh 默认使用 libc++ 构建 clang?

C++异常设计

c++ - 为什么我们应该使用带有唯一指针的 std::move 语义?

c++ - 按类型构造一个 std::mem_fn

c++ - 为什么这个 for 循环不停止?