https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106399
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|WAITING |NEW CC| |jakub at gcc dot gnu.org --- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I can reproduce it, but it was actually wrong-debug before that case. Consider: void baz (void) {} int foo(int a) { int a2 (void) { a++; return a * a; } baz (); int x = a2 (); baz (); return x; } int main () { return foo (3) - 16; } As a is used by nested function, what we actually compile this into (at -O0) is: _3 = __builtin_dwarf_cfa (0); FRAME.0.FRAME_BASE.PARENT = _3; FRAME.0.a = a_5(D); baz (); x_9 = a2 (); [static-chain: &FRAME.0] baz (); _11 = x_9; return _11; Where FRAME.0 is an artificial structure that contains some pointer and the a parameter. For -O0, there are 2 copies of a in the foo function's stack. One is that holds the a_5(D) SSA_NAME, i.e. the value of the argument that was passed to the function. And then inside of the FRAME.0 artificial var there is another copy of it. Before Eric's change (i.e. GCC 8 and earlier), the former has been declared as the location holding a in debug info, while after it it is the FRAME.0.a member. The former is incorrect, if you put a breakpoint say on the line with second call to baz () when compiled by GCC 8 and print a, it will print 3, even when a is actually 4 (a2 has incremented it). The latter is correct, but it is initialized slightly later. At -O0 we don't do (expensive) variable tracking, so we just indicate a single memory location for the parameter in debug info. So, unless we there enable the var tracking too, we would need to arrange for the breakpoint on foo to be added not just after the normal prologue, but also after initialization of the FRAME.0 variable. If you in the debugger stepi a few times or just step, you'll see correct value of a eventually. E.g. with current trunk, the foo assembly starts with: pushq %rbp movq %rsp, %rbp subq $48, %rsp movl %edi, -36(%rbp) leaq 16(%rbp), %rax movq %rax, -24(%rbp) movl -36(%rbp), %eax movl %eax, -32(%rbp) call baz and breakpoint on foo is put by the debugger after the movl %edi, -36(%rbp) instruction, so after the a parameter is stored from %edi register into the first stack location. FRAME.0 is at %rbp - 24, so the stores to it are only completed right before call baz.