为什么唯一的带符号整数类型会在clang中导致溢出警告

用户名

以下最简单的代码示例将导致一个警告:

#include <iostream>
#include <climits>

int b = INT_MAX + 1; //warning: overflow in expression; result is -2147483648 
                     //with type 'int' [-Winteger-overflow]

unsigned int a = INT_MAX + 1; //OK
int main()
{
    std::cout << b << std::endl << a;
}

演示

为什么第二行溢出不会引起任何警告?这是一个错误,还是我听不懂?

马特·彼得森

这是一个错误,尽管结果是“正确的”。据我所知,似乎该操作实际上在添加操作之前变成了无符号的。

该代码将生成警告,该代码显然会检查未签名的内容并跳过溢出检查(明确打算并在注释中提及):

/// Perform the given integer operation, which is known to need at most BitWidth
/// bits, and check for overflow in the original type (if that type was not an
/// unsigned type).
template<typename Operation>
static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
                                   const APSInt &LHS, const APSInt &RHS,
                                   unsigned BitWidth, Operation Op) {
  if (LHS.isUnsigned())
    return Op(LHS, RHS);

  APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false);
  APSInt Result = Value.trunc(LHS.getBitWidth());
  if (Result.extend(BitWidth) != Value) {
    if (Info.checkingForOverflow())
      Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
        diag::warn_integer_constant_overflow)
          << Result.toString(10) << E->getType();
    else
      HandleOverflow(Info, E, Value, E->getType());
  }
  return Result;
}

如我们所见,unsigned没有给出警告:

  if (LHS.isUnsigned())
    return Op(LHS, RHS);

缩减程序(删除#includes#define INT_MAX ...从相关标头复制a ),然后使用运行clang clang++ -Xclang -ast-dump ...,将得到以下输出:

TranslationUnitDecl 0x4ca2830 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x4ca2d70 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
|-TypedefDecl 0x4ca2dd0 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
|-TypedefDecl 0x4ca3190 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
|-VarDecl 0x4ca31f0 <of.cpp:3:1, col:19> col:5 b 'int' cinit
| `-BinaryOperator 0x4ca3288 <line:1:19, line:3:19> 'int' '+'
|   |-IntegerLiteral 0x4ca3248 <line:1:19> 'int' 2147483647
|   `-IntegerLiteral 0x4ca3268 <line:3:19> 'int' 1
|-VarDecl 0x4ce2280 <line:6:1, col:28> col:14 a 'unsigned int' cinit
| `-ImplicitCastExpr 0x4ce2340 <line:1:19, line:6:28> 'unsigned int' <IntegralCast>
|   `-BinaryOperator 0x4ce2318 <line:1:19, line:6:28> 'int' '+'
|     |-IntegerLiteral 0x4ce22d8 <line:1:19> 'int' 2147483647
|     `-IntegerLiteral 0x4ce22f8 <line:6:28> 'int' 1
`-FunctionDecl 0x4ce23b0 <line:7:1, line:10:1> line:7:5 main 'int (void)'
  `-CompoundStmt 0x4ce24a8 <line:8:1, line:10:1>

我们可以清楚地看到它是整数:

|   `-BinaryOperator 0x4ce2318 <line:1:19, line:6:28> 'int' '+'
|     |-IntegerLiteral 0x4ce22d8 <line:1:19> 'int' 2147483647
|     `-IntegerLiteral 0x4ce22f8 <line:6:28> 'int' 1

因此,编译器必须先转换为unsigned,然后再应用+强制转换的含义是:

| `-ImplicitCastExpr 0x4ce2340 <line:1:19, line:6:28> 'unsigned int' <IntegralCast>

我将再看看是否可以弄清楚这实际上是哪里出了问题。但这需要等待一段时间...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

带符号的整数乘法溢出

来自分类Dev

为什么这会在这个 while 循环中导致一个恒定的“真”?

来自分类Dev

为什么MIPS架构不区分存储的带符号和无符号类型数据?

来自分类Dev

为什么在C中递增到整数会导致溢出?

来自分类Dev

为什么带符号整数的/ = 2与>> = 1不同,并且编译为不同的asm?

来自分类Dev

为什么检查对象是否为null会在编译时发出警告?

来自分类Dev

为什么每次未定义有符号整数溢出时,turbo c环绕符号有整数溢出?

来自分类Dev

为什么此代码给出警告?

来自分类Dev

为什么rbind会发出警告

来自分类Dev

为什么这会在requireJS中导致“不匹配的匿名define()”?

来自分类Dev

为什么F#中的orderBy不会在SQL中导致ORDER BY?

来自分类Dev

为什么添加onClick方法会在我的react render方法中导致无限循环

来自分类Dev

为什么32位带符号整数最大值在c#中增加1后变为最小值?

来自分类Dev

导致溢出的混合整数类型的C ++算法

来自分类Dev

导致溢出的混合整数类型的C ++算法

来自分类Dev

为什么在许多情况下,无符号类型更合适,BCL为什么对许多方法都使用带符号的int?

来自分类Dev

是否可以在Visual C ++中很好地定义带符号整数溢出的选项?

来自分类Dev

SSE2带符号整数溢出是否未定义?

来自分类Dev

带符号字符的整数转换

来自分类Dev

Rust:如何从有符号整数类型转换为更大的带符号整数类型(不带*符号扩展名)

来自分类Dev

为什么此代码为什么在Visual Studio 2012上的代码分析中发出缓冲区溢出警告(C6385 / C6386)?

来自分类Dev

无符号类型与带符号类型的比较

来自分类Dev

在Go中检测带符号的int溢出

来自分类Dev

为什么GHC仅对部分实现的类发出警告,而不对错误发出警告?

来自分类Dev

更改一个类属性的数据类型会在构造子类对象的过程中导致段错误

来自分类Dev

为什么这会导致C堆栈溢出?

来自分类Dev

为什么这会导致C堆栈溢出?

来自分类Dev

为什么内容会导致列溢出?

来自分类Dev

为什么我会在返回float :: PositiveInfinity时收到警告C4756:常数算术溢出?

Related 相关文章

  1. 1

    带符号的整数乘法溢出

  2. 2

    为什么这会在这个 while 循环中导致一个恒定的“真”?

  3. 3

    为什么MIPS架构不区分存储的带符号和无符号类型数据?

  4. 4

    为什么在C中递增到整数会导致溢出?

  5. 5

    为什么带符号整数的/ = 2与>> = 1不同,并且编译为不同的asm?

  6. 6

    为什么检查对象是否为null会在编译时发出警告?

  7. 7

    为什么每次未定义有符号整数溢出时,turbo c环绕符号有整数溢出?

  8. 8

    为什么此代码给出警告?

  9. 9

    为什么rbind会发出警告

  10. 10

    为什么这会在requireJS中导致“不匹配的匿名define()”?

  11. 11

    为什么F#中的orderBy不会在SQL中导致ORDER BY?

  12. 12

    为什么添加onClick方法会在我的react render方法中导致无限循环

  13. 13

    为什么32位带符号整数最大值在c#中增加1后变为最小值?

  14. 14

    导致溢出的混合整数类型的C ++算法

  15. 15

    导致溢出的混合整数类型的C ++算法

  16. 16

    为什么在许多情况下,无符号类型更合适,BCL为什么对许多方法都使用带符号的int?

  17. 17

    是否可以在Visual C ++中很好地定义带符号整数溢出的选项?

  18. 18

    SSE2带符号整数溢出是否未定义?

  19. 19

    带符号字符的整数转换

  20. 20

    Rust:如何从有符号整数类型转换为更大的带符号整数类型(不带*符号扩展名)

  21. 21

    为什么此代码为什么在Visual Studio 2012上的代码分析中发出缓冲区溢出警告(C6385 / C6386)?

  22. 22

    无符号类型与带符号类型的比较

  23. 23

    在Go中检测带符号的int溢出

  24. 24

    为什么GHC仅对部分实现的类发出警告,而不对错误发出警告?

  25. 25

    更改一个类属性的数据类型会在构造子类对象的过程中导致段错误

  26. 26

    为什么这会导致C堆栈溢出?

  27. 27

    为什么这会导致C堆栈溢出?

  28. 28

    为什么内容会导致列溢出?

  29. 29

    为什么我会在返回float :: PositiveInfinity时收到警告C4756:常数算术溢出?

热门标签

归档