为什么唯一的带符号整数类型会导致clang中的溢出警告
Why does the only signed integer type causes overflow warning in 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 ...
),并使用clang++ -Xclang -ast-dump ...
运行clang,会得到以下输出:
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>
我会再看一眼,看看我是否能弄清楚到底哪里出了问题。但这还需要等待一段时间。。。
相关文章:
- 奇怪的结构&GCC&clang(void*返回类型)
- 'short int'持有的值溢出,但"自动"不会溢出?
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 大于65535的C++数组[size]引发不一致的溢出
- 数据成员SFINAE的C++17测试:gcc vs clang
- 当我编译webrtc服务器时,Windows上只支持clang-cl
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- Clang bug?使用指针作为模板参数
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- C++中无符号字符溢出
- clang整洁10忽略了我的NOLINT命令
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在clang++预处理器中确定gcc工具链版本
- 为什么 Clang 不允许"and"作为函数名称?
- 带有 -stdlib=libc++ 的 clang++ 9.0.1 找不到<optional>
- clang格式:宏的缩进
- 优化正在杀死我在 clang 6 中的整数溢出检查
- 仅当当前行溢出clang格式时,才能在新线路上支撑
- 为什么唯一的带符号整数类型会导致clang中的溢出警告