This code test1.cc #include <iostream> #include <climits> wchar_t g_wchar = 0; int g_int = -1975564288; int l_int = -1227761344; int main () { g_wchar = l_int + g_int; std::cout << g_wchar << std::endl; std::cout << "WCHAR_MIN = " << WCHAR_MIN << std::endl; std::cout << "WCHAR_MAX = " << WCHAR_MAX << std::endl; return 0; } GCC can detect UB correctly $g++ -w -fsanitize=signed-integer-overflow ; ./a.out test1.cc:9:21: runtime error: signed integer overflow: -1227761344 + -1975564288 cannot be represented in type 'int' 1091641664 WCHAR_MIN = -2147483648 WCHAR_MAX = 2147483647 But in this case test2.cc add "const" for int #include <iostream> #include <climits> wchar_t g_wchar = 0; const int g_int = -1975564288; const int l_int = -1227761344; int main () { g_wchar = l_int + g_int; std::cout << g_wchar << std::endl; std::cout << "WCHAR_MIN = " << WCHAR_MIN << std::endl; std::cout << "WCHAR_MAX = " << WCHAR_MAX << std::endl; return 0; } GCC detect nothing. $g++ -w -fsanitize=signed-integer-overflow test2.cc; ./a.out 1091641664 WCHAR_MIN = -2147483648 WCHAR_MAX = 2147483647 My g++ version $g++ --version g++ (GCC) 11.0.0 20200526 (experimental) Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. I have tested them in recent GCC versions including GCC-8, GCC-9, GCC-10, they have the same symptom as well. I also test them in clang-trunk, above two testcases can be detected as "signed integer overflow".
My guess is that G++ folds the constants early and the overflow happens at compile time, so is never seen by UBsan.
I also find these cases test1.cc #include <iostream> bool g_bool = 0; long g_long = -4075183478711827874L; const long l_long = 7122990940771016367L; int main () { g_bool = g_long * l_long; std::cout << g_bool << std::endl; return 0; } GCC detects nothing. $g++ -w -fsanitize=signed-integer-overflow test1.cc 1 But when remove "const" test2.cc #include <iostream> bool g_bool = 0; long g_long = -4075183478711827874L; const long l_long = 7122990940771016367L; int main () { g_bool = g_long * l_long; std::cout << g_bool << std::endl; return 0; } GCC can dectect the signed-integer-overflow. $g++ -w -fsanitize=signed-integer-overflow test2.cc test2.cc:7:21: runtime error: signed integer overflow: -4075183478711827874 * 7122990940771016367 cannot be represented in type 'long int' 1