Hello! It is certainly true that debugging an optimized code is an inherently difficult task. Though, I wonder if the compiler could make such debugging experience slightly less surprising.
Consider the following example: 1 extern void bar(int *i1, int *i2, int *i3); 2 3 int __attribute__((noinline)) foo(int i1, int i2) { 4 int a, b, c; 5 a = i1 << i2; 6 b = (i1 + i2) * i1; 7 c = (b + i1); 8 bar(&a, &b, &c); 9 } 10 11 int main() { 12 foo(42, 12); 13 } Let's compile it: $ gcc-trunk tst.c -g -fvar-tracking-uninit -O2 After hitting a breakpoint at line 8 (the last line of the function foo) I have some random (and very confusing) values displayed in gdb for all three variables a, b and c. This is because GCC allocates these three variables on the stack (their addresses are taken) and creates for them DWARF entries like this: <2><a8>: Abbrev Number: 8 (DW_TAG_variable) <a9> DW_AT_name : a <ab> DW_AT_decl_file : 1 <ac> DW_AT_decl_line : 4 <ad> DW_AT_type : <0x64> <b1> DW_AT_location : 2 byte block: 91 64 (DW_OP_fbreg: -28) That is, actual values for variables are supposed to reside in fixed stack slots throughout the whole function. But in fact, by the time the breakpoint is hit none of the values is stored on the stack (the last line of the function, evaluation of the first argument for the call): Dump of assembler code for function foo: 0x00000000004004c0 <+0>: mov %esi,%ecx 0x00000000004004c2 <+2>: add %edi,%esi 0x00000000004004c4 <+4>: sub $0x18,%rsp 0x00000000004004c8 <+8>: imul %edi,%esi 0x00000000004004cb <+11>: mov %edi,%eax => 0x00000000004004cd <+13>: lea 0xc(%rsp),%rdx 0x00000000004004d2 <+18>: shl %cl,%eax 0x00000000004004d4 <+20>: mov %eax,0x4(%rsp) 0x00000000004004d8 <+24>: mov %esi,0x8(%rsp) 0x00000000004004dc <+28>: add %edi,%esi 0x00000000004004de <+30>: lea 0x4(%rsp),%rdi 0x00000000004004e3 <+35>: mov %esi,0xc(%rsp) 0x00000000004004e7 <+39>: lea 0x8(%rsp),%rsi 0x00000000004004ec <+44>: callq 0x4004f6 <bar> 0x00000000004004f1 <+49>: add $0x18,%rsp 0x00000000004004f5 <+53>: retq End of assembler dump. By contrast, If I didn't take addresses of these variables, they would be <optimized out> until we can determine their correct values. I believe that such behavior is much better than displaying wrong values for variables. Also, GCC seems to be able to produce DW_OP_GNU_uninit operations to mark uninitialized variables (when -fvar-tracking-uninit is used) but I've never seen it in generated debug info. At first glance the problem seems to have something to do with the fact that there's no gimple_debug/BIND and debug_insn/var_location instructions for such stack variables in internal representation. There are only statements like this: gimple_assign <lshift_expr, a.0_3, i1_1(D), i2_2(D), NULL> # .MEM_5 = VDEF <.MEM_4(D)> gimple_assign <ssa_name, a, a.0_3, NULL, NULL> and *no* BIND statement like gimple_debug BIND <a, a.0_3> Furthermore, in dwarf2out.c there are a lot of calls to mem_loc_descriptor where var_init_status is unconditionally set to VAR_INIT_STATUS_INITIALIZED. And it looks like currently all values in memory are considered to be initialized by default. And only in few places NOTE_VAR_LOCATION_STATUS is taken into account (anyway, there's no such notes for variables a, b, c in this case). So, here are my questions: 1) Wouldn't it be nice if GCC marked such stack variables either as uninitialized (with DW_OP_GNU_uninit) or as <optimized out>? 2) Is it feasible to implement such tracking for variables? 3) What exactly is GCC supposed to track with -fvar-tracking-uninit option? Thanks, Nikolai