#include <iostream>
int main()
{
int n = -1000;
for (int i(0); i != n; ++i)
{
}
}
在gcc中,在编译时捕获以下错误:
main.cpp:6:5: warning: iteration 2147483647u invokes undefined behavior [-Waggressive-loop-optimizations]
for (int i(0); i != n; ++i)
Clang的-fsanitize=undefined
是一种运行时机制。 clang的编译时间等价是什么?
答案 0 :(得分:6)
标准中经常会描述未定义的行为,因为编译器在所有情况下都很难检查这一点。
你刚遇到一个由GCC而不是Clang处理的案例。如果你看,你将能够找到由一个而不是另一个编译器处理的案例。那是因为他们不是同一个编译器,并且他们执行的分析不同。
答案 1 :(得分:4)
Clang还不能抓住这个,至少不是编译的一部分(我还没有检查过clang静态分析仪,如果它也不能,请提交一个bug)。
GCC已经决定从优化器中间发出警告:
$ g++ -Waggressive-loop-optimizations a.cc
$ g++ -Waggressive-loop-optimizations a.cc -O2
a.cc: In function ‘int main()’:
a.cc:6:5: warning: iteration 2147483647u invokes undefined behavior [-Waggressive-loop-optimizations]
for (int i(0); i != n; ++i)
^
a.cc:6:5: note: containing loop
这实际上非常棘手且可能很挑剔。 clang开发人员认为,根据优化级别更改您发出的警告是不良行为,我们认为用户不希望在构建-O0时错过警告,或者在发布版本后几天发现新错误。其次,优化器的设计方式是在任何时间点保持程序的一个表示,并将其从一个事物转换为另一个事物,而不保留其完成的内容与## 39; s在原始代码中。这LLVM blog article讨论了这个问题。 Clang的警告建立在clang的AST之上,它完整地代表了原始源代码,包括模板和宏历史,因此我们总能指向正确的代码并过滤属性,如&#34 ;它是一个模板参数&#34;。
也许有可能将它添加到clang中,我还没有想出一个有效的方法,只需30秒就可以做到这一点。问题在于,我们愿意花费更多时间来证明优化器中的内容,而不是作为警告生成的一部分。我们不想两次支付编译时间。另一方面,静态分析仪没有这个限制,并且很乐意为找到你的bug而做非常昂贵的工作。
最后,你表达问题的方式使得听起来像你认为clang在编译时捕获所有未定义的行为或者没有捕获所有未定义的行为。我们有效地捕获as much as we can,并为尽可能多的其余部分提供动态检查器,但gcc和clang都不会承诺在编译时或运行时捕获所有未定义的行为。它有太多的东西,而且没有列出它的全部内容(某些操作在标准中明确是UB,有些是UB,因为标准无法定义行为是什么!)。