【问题标题】:How to make Clang to ignore specific warning in specific block?如何让 Clang 忽略特定块中的特定警告?
【发布时间】:2013-06-16 20:11:18
【问题描述】:

我正在使用类型特征检查数值范围,无符号类型会生成警告。

Comparison of unsigned expression >= 0 is always true

如何在特定代码范围内禁用某些警告?我将 GCC 样式 #pragma 与 Clang 一起使用,但这不起作用。 这是我的代码。

template<typename originT, typename destinationT>
void
assertForNumericRange(const originT value)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored  "-Wtype-limits"
    assertWithReason(value >= std::numeric_limits<destinationT>::min());
    assertWithReason(value <= std::numeric_limits<destinationT>::max());
#pragma GCC diagnostic pop
}

注意

目前,我将断言分为三组,浮点数、无符号整数、有符号整数。但如果可能的话,我希望将它们合二为一。

我正在使用 Xcode 5.0 测试版。在命令行中,它会报告以下内容: 苹果 LLVM 版本

5.0 (clang-500.1.58) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix

【问题讨论】:

  • 我认为你应该改变你的问题的标题,因为现在你正在寻找一个不同的答案(如何检查一个变量的值是否可以适合另一个可能不同类型的变量而不生成编译警告)
  • @Antonio 我仍在寻找一种抑制警告的方法。如果我必须要求它,我将发布一个新问题。谢谢。
  • 你得到的警告是正确的,让你发现了一些令人讨厌的问题,不应该通过一些 pragma 定义来删除。在你身上,我会尝试向你的函数添加更多逻辑(if 语句),如果在编译器知道永远不会执行的某些代码中,不确定它是否会删除警告。
  • @Antonio 实际上,我尝试输入一些if (std::is_signed&lt;T&gt;::value) ... ,但编译器仍然会根据子表达式生成警告。因为抑制警告不是一个好的设计。所以也许我会使用单独的断言方法。

标签: c++ clang suppress-warnings


【解决方案1】:

首先,请注意对于浮点类型,例如

std::numeric_limits<float>::min()

返回minimum positive normalized value (>0),而对于整数类型

std::numeric_limits<T>::min()

返回最小的非正数 (

浮点类型的最小负数是:

-std::numeric_limits<T>::max()

我认为你必须结合不同的numeric_limits methods/members(如is_integeris_signed)和if 语句,也可以摆脱你的警告。 (从效率的角度来看)你不必担心得到一个过于复杂的函数,因为大多数检查将在编译时进行评估,并且不会影响执行时间。事实上,如果你可以避免在运行时进行一些不必要的检查,因为在编译时进行了一些检查,你的程序会更快。

您还应该使用std::is_same&lt;T,U&gt;::value,并避免进一步检查是否属实。

【讨论】:

  • 感谢您选择这个!我不知道这些东西。现在我想我应该使用std::numeric_limits&lt;T&gt;::lowest()
  • 据说依赖于实现,我不相信。当std::numeric_limits&lt;T&gt;::is_integer 为假时,最安全的是使用-std::numeric_limits&lt;T&gt;::max()
【解决方案2】:

检查this Q&A I just posted。对我来说,它编译时没有警告,你应该在 Clang 上检查它。可以扩展到浮点类型。

【讨论】:

    【解决方案3】:

    您使用的是哪个版本的 Clang?从the Clang User Manual 开始,它应该可以按照您的方式工作。但是您的范围断言不会按照您可能希望的方式工作:

    如果destinationT 是无符号的,那么第一个断言本身没有多大意义,所以 min 给出 0。originT 也是无符号的,那么它显然不是负数,这是编译器警告你的。或者originT 是有符号的,比较会将一个或两个操作数转换为其他类型,例如可能将value 转换为无符号(因此为正)表示。

    例如考虑

     assertForNumericRange<signed char, unsigned long>( (signed char)-1);  
    

    (signed char)-1unsigned long 之间的比较会将 -1 提升为 unsigned long,有效地给出以下 32 位长的断言:

    assertWithReason((unsigned long)0xFFFFFFFF >= std::numeric_limits<destinationT>::min());
    assertWithReason((unsigned long)0xFFFFFFFF <= std::numeric_limits<destinationT>::max());
    

    两个比较结果都为真,而 -1 显然 不在unsigned long 的值范围内。

    【讨论】:

    • 谢谢,这是唯一真正回答问题的答案,但这只是因为它链接到 Clang 用户手册中的答案。
    猜你喜欢
    • 2014-03-15
    • 1970-01-01
    • 2011-12-15
    • 2015-10-10
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    相关资源
    最近更新 更多