A regression from 4.3 for GNU C++ 4.4.0 20090317 (experimental) -PASS: gdb.cp/classes.exp: calling method for small class +XFAIL: gdb.cp/classes.exp: calling method for small class (PRMS 2972) ------------------------------------------------------------------------------- Breakpoint 1, main () at small.C:36 36 return v.x + 5; /* break-here */ (gdb) p v.method() Address requested for identifier "v" which is in register $rbx ------------------------------------------------------------------------------- from gcc-4.3: (gdb) p v.method() $1 = 82 ------------------------------------------------------------------------------- /* from gdb.cp/classes.cc */ /* Try to get the compiler to allocate a class in a register. */ class small { public: int x; int method (); }; int small::method () { return x + 5; } void marker_reg1 () {} int main () { /* We don't call any methods for v, so gcc version cygnus-2.3.3-930220 might put this variable in a register. This is a lose, though, because it means that GDB can't call any methods for that variable. */ register small v; int i; /* Perform a computation sufficiently complicated that optimizing compilers won't optimized out the variable. If some compiler constant-folds this whole loop, maybe using a parameter to this function here would help. */ v.x = 0; for (i = 0; i < 13; ++i) v.x += i; --v.x; /* v.x is now 77 */ marker_reg1 (); return v.x + 5; /* break-here */ } ------------------------------------------------------------------------------- < c> DW_AT_producer : (indirect string, offset: 0x19): GNU C++ 4.4.0 20090317 (experimental) <3><ed>: Abbrev Number: 14 (DW_TAG_variable) <ee> DW_AT_name : v <f2> DW_AT_type : <0x2d> <f6> DW_AT_location : 1 byte block: 53 (DW_OP_reg3) Formerly the class was left in memory: < c> DW_AT_producer : (indirect string, offset: 0x31): GNU C++ 4.3.2 20081105 (Red Hat 4.3.2-7) <2><dc>: Abbrev Number: 13 (DW_TAG_variable) <dd> DW_AT_name : v <e1> DW_AT_type : <0x2d> <e5> DW_AT_location : 2 byte block: 76 6c (DW_OP_breg6: -20) Moreover small::method() expects the object to be in memory so GDB cannot just pass it in the %ebx register as is: < c> DW_AT_producer : (indirect string, offset: 0x19): GNU C++ 4.4.0 20090317 (experimental) <2><45>: Abbrev Number: 4 (DW_TAG_subprogram) <46> DW_AT_external : 1 <47> DW_AT_name : (indirect string, offset: 0xc): method <51> DW_AT_type : <0x5e> <55> DW_AT_declaration : 1 <3><56>: Abbrev Number: 5 (DW_TAG_formal_parameter) <57> DW_AT_type : <0x65> <5b> DW_AT_artificial : 1 <1><6b>: Abbrev Number: 8 (DW_TAG_subprogram) <6c> DW_AT_specification: <0x45> <81> DW_AT_frame_base : 0x0 (location list) <2><89>: Abbrev Number: 9 (DW_TAG_formal_parameter) <8a> DW_AT_name : (indirect string, offset: 0x52): this <8e> DW_AT_type : <0x97> <92> DW_AT_artificial : 1 <93> DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24) GDB could probably use a (trivial=memcpy in this case) copy constructor (+later destructor) from %ebx to a memory location.
Created attachment 17483 [details] gcc44-pr39485.patch Self inflicted pain I'd say, if you don't want something in register, don't use a register keyword. That said, the following patch does that for you. In 4.3 the reason why the above testcase had v stored in memory, not in register, has been just that it has been used in multiple basic blocks and global allocation wasn't performed. If you use a simpler testcase like: struct S { int x; int method (); }; int S::method () { return x + 5; } int main () { register S v; v.x = 0; return v.x + 5; } then even g++ 4.3 and earlier will allocate v in a register and so you won't be able to do v.method () in the debugger (though, with the attached patch you can). With the patch: struct S { int x; }; int main () { register int v; int i; v = 0; for (i = 0; i < 13; ++i) v += i; --v; return v + 5; } will still use a register for v, but that is definitely fine.
Subject: Bug 39485 Author: jakub Date: Wed Mar 18 17:06:15 2009 New Revision: 144939 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=144939 Log: PR debug/39485 * function.c (use_register_for_decl): When not optimizing, disregard register keyword for variables with types containing methods. Modified: trunk/gcc/ChangeLog trunk/gcc/function.c
I see I messed it up, in some way was gcc-4.4 more correct than gcc-4.3 Thanks for the fix although now I would not probably bugreport it at all. It turned PASS->XFAIL. But in fact PASS means SKIP(not-testable) and XFAIL means PASS - for GDB. gdb.cp/classes.exp: # This class is so small that an instance of it can fit in a register. # When gdb tries to call a method, it gets embarrassed about taking # the address of a register. # # TODO: I think that message should be a PASS, not an XFAIL. # gdb prints an informative message and declines to do something # impossible. # # The method call actually succeeds if the compiler allocates very # small classes in memory instead of registers. So this test does # not tell us anything interesting if the call succeeds.
Anyway, I consider this fixed. If gdb wants to test also what happens with such classes in registers, it can always use -O1 or above.