gcc trunk, rev 255537, x86_64. Not sure if this is duplicate of #42145 or not, so filing as a separate bug. The issue goes away if either sanitizer flags removed, "extern" removed from tf_0_var_14 definition, or "const" removed from the same definition. Though it points to different variable. So, something fishy is going on here. You may argue that this analysis is inexact and I shouldn't rely on that, but it's definitely usability bug, when unrelated things are causing troubles. And it stops me from using -Werror=uninitialized in test case reduction, where it really does useful job. > cat f.cpp int tf_0_var_36; signed char tf_0_var_58; extern const int tf_0_var_14; int *tf_0_ptr_8; void tf_0_foo() { tf_0_var_36 >> ((!0 || tf_0_var_58) && (0 ? tf_0_var_14 : *tf_0_ptr_8)); } > g++ -std=c++11 -fsanitize=undefined -Werror=uninitialized -o ubsan_gcc_o2_func.o -c f.cpp f.cpp: In function ‘void tf_0_foo()’: f.cpp:6:72: error: ‘tf_0_ptr_8.1’ is used uninitialized in this function [-Werror=uninitialized] tf_0_var_36 >> ((!0 || tf_0_var_58) && (0 ? tf_0_var_14 : *tf_0_ptr_8)); ^ cc1plus: some warnings being treated as errors
The interaction between sanitizers and middle-end emitted warnings is difficult at best. Can you avoid -Werror when sanitizing?
(In reply to Richard Biener from comment #1) > The interaction between sanitizers and middle-end emitted warnings is > difficult at best. Can you avoid -Werror when sanitizing? I can, if it's absolutely needed. But it's convenient. I use it in creduce as a criteria that reduction haven't introduced undefined behavior. UBSAN doesn't catch uninitialized variables, so I have to add this switch. An alternative is to have two separate runs.
Reconfirmed with GCC 11. The warning sees the IL below and triggers for the call to .UBSAN_NULL() after the CFG pass has removed the initialization of p.1. A simple way to avoid it is to suppress warnings for calls to the sanitizer internal functions. Interestingly, this bug is only reproducible with C++, not when the same code is compiled as C. $ gcc -O0 -S -Wall -fsanitize=undefined -fdump-tree-cfg-details=/dev/stdout -xc++ pr83382.c pr83382.c: In function ‘void f()’: pr83382.c:6:5: warning: value computed is not used [-Wunused-value] 6 | i >> ((!0 || c) && (0 ? j : *p)); | ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;; Function f (_Z1fv, funcdef_no=0, decl_uid=2788, cgraph_uid=1, symbol_order=5) Scope blocks: { Scope block #0 } Removing basic block 3 ;; basic block 3, loop depth 0 ;; pred: p.1 = p; <<< initialization removed .UBSAN_NULL (p.1, 2B, 4); _1 = MEM[(const int &)p.1]; _2 = _1 != 0; _3 = (int) _2; _4 = (unsigned long) _3; _5 = (unsigned long) i.0; __builtin___ubsan_handle_shift_out_of_bounds (&*.Lubsan_data0, _5, _4); ;; succ: 4 ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 3 ;; 2 succs { 3 } ;; 3 succs { 1 } void f () { int * p.1; <<< not initialized int i.0; <bb 2> : i.0 = i; <bb 3> : .UBSAN_NULL (p.1, 2B, 4); <<< -Wuninitialized _6 = MEM[(const int &)p.1]; _7 = _6 != 0; _8 = (int) _7; return; } pr83382.c:6:25: warning: ‘p.1’ is used uninitialized [-Wuninitialized] 6 | i >> ((!0 || c) && (0 ? j : *p)); | ~~~^~~~~~~~~ pr83382.c:6:25: note: ‘p.1’ was declared here 6 | i >> ((!0 || c) && (0 ? j : *p)); | ~~~^~~~~~~~~