【问题标题】:Can clang warn about undefined behavior at compile-time?clang 可以在编译时警告未定义的行为吗?
【发布时间】:2014-10-23 07:28:25
【问题描述】:
#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 的编译时等价物是什么?

【问题讨论】:

  • 这似乎是 GCC 的一个最近的特性(它在 4.9 中,但不是 4.8)。如果 Clang 还没有它,我不会感到惊讶。当然,很多这样的实例不能在运行时被捕获;这只有效,因为n 的值在编译期间是已知的。
  • -Wall 会在编译时捕获导致 UB 的内容作为警告。
  • @Rapptz 但它不适用于这种情况,这是一个公认的非常具体的问题。
  • @simpleBob:我敢肯定,这个特别的人可能会被抓到。但是,是的,跟踪所有这些事情确实变得非常复杂。

标签: c++ clang undefined-behavior


【解决方案1】:

标准中经常这样描述未定义的行为,因为编译器很难在所有情况下都检查这一点。

您只是遇到了一种由 GCC 而不是 Clang 处理的情况。如果您查看,您将能够找到由一个编译器而不是另一个编译器处理的案例。那是因为它们不是同一个编译器,并且它们执行的分析不同。

【讨论】:

  • 这确实是使用多个编译器编译代码以便在编译时发现更多问题的好理由。
【解决方案2】:

Clang 还不能捕捉到这个,至少不能作为编译的一部分(我没有检查过 clang 静态分析器,如果它也不能,请提交一个错误)。

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 构建时会错过警告,或者在几天后进行发布构建时会发现新的错误。其次,优化器的设计方式是,它可以在任何时间点保留程序的一种表示形式,并将其从说一件事转换为另一件事,而不保留它所做的事情与原始代码中的内容的历史记录。这个LLVM blog article 谈到了这个问题。 Clang 的警告建立在 clang 的 AST 之上,该 AST 具有原始源代码的完整表示,包括模板和宏历史记录,因此我们始终可以指向正确的代码并过滤诸如“是否为模板参数”之类的属性。

也许可以将它添加到 clang,我只考虑了 30 秒后还没有找到一种有效的方法来做到这一点。问题是我们愿意花更多的时间在优化器中证明事情,而不是作为警告生成的一部分。我们不想支付两次编译时间。另一方面,静态分析器没有这个限制,并且很乐意做非常昂贵的工作来发现你的错误。

最后,您提出问题的方式听起来像是您认为 clang 在编译时捕获或没有捕获所有未定义的行为。我们确实有效地捕获了as much as we can,并为尽可能多的其余部分提供了动态检查器,但是 gcc 和 clang 都不会承诺在编译时或运行时捕获所有未定义的行为。它太多了,并且没有列出所有内容(有些操作在标准中明确是 UB,有些是 UB,因为标准未能定义行为是什么!)。

【讨论】:

  • Waggressive-loop-optimizations 在这里确实很挑剔is a question 代码的结构与我们是否收到警告有关。
  • 那太糟糕了。如果编译器有时可以告诉我我的代码中有错误,我希望它这样做,即使它不能总是告诉我。
猜你喜欢
  • 2020-05-15
  • 1970-01-01
  • 2011-09-28
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 2010-11-28
相关资源
最近更新 更多