【问题标题】:Different behaviour between Clang and GCC when performing qualified name lookup执行限定名称查找时 Clang 和 GCC 之间的不同行为
【发布时间】:2015-10-06 12:32:20
【问题描述】:

考虑以下程序:

#include <iostream>

namespace N {
    int j = 1;
}

namespace M {
    typedef int N;
    void f() {
        std::cout << N::j << std::endl;
    }
}

int main() { M::f(); }

使用 clang 编译会出现以下编译错误:

prog.cc:10:22: error: 'N' (aka 'int') is not a class, namespace, or
enumeration
    std::cout << N::j << std::endl;
                 ^ 1 error generated.

GCC 没有给出任何编译器错误。我试图弄清楚我应该为哪个编译器提交错误报告。哪个编译器具有正确的行为以及原因(对 c++ 标准的引用)?

Wandbox - Clang:http://melpon.org/wandbox/permlink/s0hKOxCFPgq5aSmJ

魔杖盒 - GCC:http://melpon.org/wandbox/permlink/i2kOl3qTBVUcJVbZ

【问题讨论】:

    标签: c++ namespaces typedef language-lawyer name-lookup


    【解决方案1】:

    Clang 在这一点上是正确的。引用 C++11、3.4.3/1 [basic.lookup.qual]:

    ...如果:: nested-name-specifier 中的范围解析运算符前面没有 decltype-specifier, 查找 :: 之前的名称仅考虑其特化为类型的名称空间、类型和模板。 如果找到的名称不指定命名空间或类、枚举或依赖类型,则程序 格式不正确。

    根据这个子句,在查找过程中应该考虑类型,所以应该找到 typedef N。而且由于它没有指定命名空间、类、枚举或依赖类型,因此程序是非良构的。

    【讨论】:

    • 但是“格式错误”的程序不是有点像“未定义的行为”吗,它对于编译器来说是完全有效的 a) 不给出错误 b) 生成以某种方式工作的代码 [包括正确或让恶魔飞出你的鼻子](不是说不应该提出一个大问题,只是从技术上讲,让编译器不产生错误并不是错误的]
    • @MatsPetersson 该标准在说“格式错误”时暗示了必需的诊断。当不需要诊断时,它通常会说“程序格式错误,不需要诊断”,而在未定义的情况下会说“行为未定义”。
    • @Mats Petersson:不,除非针对格式错误的程序提到“不需要诊断”,否则编译器必须产生至少一条诊断消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    相关资源
    最近更新 更多