Bug 46815 - Invalid DW_AT_location for a retval instance of a class that has a virtual function
Summary: Invalid DW_AT_location for a retval instance of a class that has a virtual fu...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 4.5.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-12-06 08:10 UTC by Siddhesh Poyarekar
Modified: 2010-12-15 22:01 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Reproducer program to run under gdb (179 bytes, text/x-c++src)
2010-12-06 08:10 UTC, Siddhesh Poyarekar
Details
gcc46-pr46815.patch (572 bytes, patch)
2010-12-06 15:39 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Siddhesh Poyarekar 2010-12-06 08:10:00 UTC
Created attachment 22649 [details]
Reproducer program to run under gdb

Problem Description:

When a local object is created from a class with a virtual function and that object is also the retval for the function it is the local variable in, the debuginfo generated for the object indicates that it is located in a register, while in reality, its address is located in the register.

Steps to Reproduce:

$ cat > rep.cpp
class Sequence {
public:
  virtual void foo(void);
};

Sequence getSequence()
{
  Sequence data;
  return data;
}

$ g++ -g -c rep.cpp
$ objdump -W rep.o | less
...
 <3><c4>: Abbrev Number: 13 (DW_TAG_variable)
    <c5>   DW_AT_name        : (indirect string, offset: 0x43): data    
    <c9>   DW_AT_decl_file   : 1        
    <ca>   DW_AT_decl_line   : 8        
    <cb>   DW_AT_type        : <0x31>   
    <cf>   DW_AT_location    : 1 byte block: 53         (DW_OP_reg3)
...

Additional Information:

Attached reproducer fullrep.cpp can be used to demonstrate this problem as seen in gdb.

1) Build fullrep.cpp: gcc -g fullrep.cpp
2) Run under gdb:

[siddhesh@spoyarek gcc-foo]$ gdb -q ./a.out
Reading symbols from /home/siddhesh/gcc-foo/a.out...done.
(gdb) break getSequence
Breakpoint 1 at 0x4007e0: file fullrep.cpp, line 14.
(gdb) r
Starting program: /home/siddhesh/gcc-foo/a.out 

Breakpoint 1, getSequence () at fullrep.cpp:14
14	  Sequence data;
(gdb) p data
$1 = {_vptr.Sequence = 0x7fffffffdfd0, i = 4}
(gdb) p &data
Address requested for identifier "data" which is in register $rbx
(gdb) p *((Sequence *)$rbx)
$2 = {_vptr.Sequence = 0x7fffffffe0c0, i = 0}
(gdb)
Comment 1 Jakub Jelinek 2010-12-06 15:39:51 UTC
Created attachment 22660 [details]
gcc46-pr46815.patch

Ugh.  So what happens is that we set DECL_VALUE_EXPR of the NRV optimized var to RESULT_DECL, but then in cp_genericize as it is addressable change the RESULT_DECL into DECL_BY_REFERENCE decl and convert_from_reference whenever it is seen in the stmts (but don't adjust the DECL_VALUE_EXPR of the var).
Which means we end up using DW_OP_reg3 instead of DW_OP_breg3 0.

Either we can do something like this patch, i.e. replace DECL_VALUE_EXPR during genericization, or we could do something similar, but faster by saving pointer to the NRV optimized VAR_DECL somewhere in the lang specific stuff for the FUNCTION_DECL, or, if we can be 100% sure by finalize_nrv time that non-addressable RESULT_DECL isn't ever going to turn into TREE_ADDRESSABLE RESULT_DECL, we could assume early what cp_genericize will do and set DECL_VALUE_EXPR in finalize_nrv to INDIRECT_REF of the RESULT_DECL (which would mean somewhat invalid tree until cp_genericize is run, but perhaps nothing would notice), or we could teach dwarf2out.c if it uses DECL_VALUE_EXPR and it points to DECL_BY_REFERENCE decl that it should add indirection automatically (but then, the question is what all will actually break by that).

Jason, any preferences?
Comment 2 Jason Merrill 2010-12-13 16:03:22 UTC
Let's go ahead with this patch.
Comment 3 Jakub Jelinek 2010-12-15 17:50:40 UTC
Author: jakub
Date: Wed Dec 15 17:50:34 2010
New Revision: 167865

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=167865
Log:
	PR debug/46815
	* cp-gimplify.c (cp_genericize): When changing RESULT_DECL
	into invisible reference, change also DECL_VALUE_EXPR of
	NRV optimized variable.

	* g++.dg/guality/pr46815.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/guality/pr46815.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-gimplify.c
    trunk/gcc/testsuite/ChangeLog
Comment 4 Jakub Jelinek 2010-12-15 22:01:34 UTC
Fixed.