【问题标题】:Clang (3.6.0) ignores warnings from included header filesClang (3.6.0) 忽略来自包含的头文件的警告
【发布时间】:2015-06-20 22:34:21
【问题描述】:

clang 似乎忽略了包含的头文件中出现的警告:

// what.hpp
class What {
public:
    What() {
        int x = x;
    }
};

// main.cpp
#include <iostream>
#include "what.hpp"
int main()
{
    int y = y;
    std::cout << "y is: " << y << std::endl;
    What w;
}

用 g++ (4.9.2) 编译得到:

$ g++ -dumpversion && g++ -Wall -Wextra main.cpp -o main
4.9.2
In file included from main.cpp:3:0:
what.hpp: In constructor ‘What::What()’:
what.hpp:5:17: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
     int x = x;
             ^
main.cpp: In function ‘int main()’:
main.cpp:5:13: warning: ‘y’ is used uninitialized in this function [-Wuninitialized]
 int y = y;

用clang编译同样的东西:

$ clang++ --version && clang++ -Wall -Wextra main.cpp -o main
Ubuntu clang version 3.6.0-2ubuntu1~trusty1 (tags/RELEASE_360/final) (based on LLVM 3.6.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
main.cpp:5:13: warning: variable 'y' is uninitialized when used within its own initialization [-Wuninitialized]
int y = y;
    ~   ^
1 warning generated.

我不确定,如果我使用 clang 错误或者这确实是一个错误? 有什么提示吗?提前致谢。

【问题讨论】:

  • 这可能取决于x 完全未使用(在任何地方都没有引用它),因此clang 完全忽略了它。尝试在What 构造函数中添加类似的cout
  • @MatteoItalia 确实,正如我在回答中指出的那样,我发现了一个关于这个确切情况的 clang 错误报告,它被认为是一项功能。

标签: c++ clang clang++


【解决方案1】:

这不是 clang 错误,警告正在被抑制,因为 x 随后未被使用,我在下面引用的错误报告解释了这种行为背后的基本原理。

在这种特定情况下,如果变量未被使用,则不产生此警告 (Wuninitialized) 被认为是一种铿锵声功能,尽管大多数人可能会发现这种令人惊讶的行为。

我们可以从以下错误报告中看到原因:No uninitialized warning for self-initialization (e.g., int x = x):

是的,这是故意的,并且被认为是一个功能而不是 比一个错误。我们禁止在 'int x = x;' 上发出警告只有的情况下 其中“x”未被使用。

bug报告中提到这种方式的自初始化是:

考虑了抑制“使用未初始化的 变量”警告

这不取决于有问题的代码是否包含在标头中,我整理了一个live example,显示当代码全部在一个文件中时警告不会出现。

注意,以这种方式初始化变量:

int x = x;

是未定义的行为,参考见:

所以一般来说,我们对结果没有任何期望,编译器没有义务发出诊断,尽管这样做会有所帮助。

【讨论】:

  • Sp 编译器编写者决定不对一个明显的 UB 情况发出警告并称其为功能?我可能没有经验来理解它的用处,但这听起来很愚蠢。
  • @MikeMB 我觉得这很令人惊讶,但这是他们的理由。
【解决方案2】:

有问题的行在语法上是正确的。两者都不是特别有用的代码行——两者都表现出未定义的行为——但它们是合法的 C++ 代码。因此,编译器没有义务发出任何诊断。

这只是实施质量问题 - 在这种情况下,编译器没有义务发出警告,但它在发出警告时非常有用。至于为什么 clang 恰好只对y 发出警告而不对x 发出警告,而 gcc 对两者都发出警告 - 我不确定。它绝对与包含的头文件无关(您可以通过在main.cpp 中定义What 自己查看)并且可能与您正在打印y 并且从不读取x 的事实有关再次。

但您不能依赖这些警告的完全准确性。然而,当你得到它们时,它们总是值得关注的。

【讨论】:

    猜你喜欢
    • 2021-12-06
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2012-04-26
    • 2021-09-19
    • 1970-01-01
    • 2018-03-20
    • 2016-10-15
    相关资源
    最近更新 更多