Bug 8698 - Problem with nested namespaces
Summary: Problem with nested namespaces
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-03-23 16:48 UTC by klaas.gadeyne
Modified: 2010-01-22 21:07 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description klaas.gadeyne 2004-03-23 16:48:01 UTC
[Converted from Gnats 1593]

Consider the following code, consisting of 3 files
=========================================================================
=========================================================================
[klaas@c014 /tmp]$ cat wrapper_object.h
#include <vector>

namespace BASE
{
  class Foo
  {
  public:
    Foo(){};
    virtual ~Foo(){};
    virtual void Method();
  };

}
=========================================================================
[klaas@c014 /tmp]$ cat wrapper_object.cpp
#include "wrapper_object.h"

namespace BASE
{
  void
  Foo::Method(){};
}
==========================================================================
[klaas@c014 /tmp]$ cat wrapper.cpp
#include "wrapper_object.h"

namespace WRAPPED
{
  class Foo : public BASE::Foo
  {
  public:
    Foo() : BASE::Foo(){};
    virtual ~Foo(){};
  };
}

using namespace WRAPPED;

int main()
{
  Foo mywrapped;
  return 0;
}
==========================================================================
==========================================================================

(gdb) break wrapper.cpp:17
Breakpoint 1 at 0x80484f4: file wrapper.cpp, line 17.
(gdb) run
Starting program: /tmp/a.out

Breakpoint 1, main () at wrapper.cpp:17
17        Foo mywrapped;
(gdb) next
18        return 0;
(gdb) display mywrapped
1: mywrapped = {<> = {<No data fields>}, <No data fields>}
======================================================================

So mywrapped is now reported to be empty, where I expected to see
something like

1: mywrapped = {<Foo> = {<No data fields>}, <No data fields>}

The problem does not exist when:
- The code is compiled with g++ 2.95.4
- All code is inlined in 1 file (yes, that's why there are 3 files above :)
- I omit the member function method and put the constructor implementation
  in the cpp file.
- When Foo in namespace WRAPPED is renamed into Boo

Release:
GNU gdb 2004-03-23-cvs

Environment:
uname: tested on

Linux c014 2.6.4 #1 Mon Mar 22 13:40:45 CET 2004 i686 GNU/Linux
Linux f012 2.4.24-adeos #1 Mon Jan 26 10:44:59 CET 2004 i686 GNU/Linux


GDB

$ gdb --version
GNU gdb 2004-03-23-cvs
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".

also tested with gdb versions in debian (5.3 and 6.0)


GCC

[klaas@f012 /usr/src/rtnet-cvs/driver]$
$ g++ --version
g++ (GCC) 3.3.3 (Debian 20040320)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[klaas@f012 /usr/src/rtnet-cvs/driver]$
$ g++-3.4 --version
g++-3.4 (GCC) 3.4.0 20040320 (prerelease) (Debian)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Comment 1 drow@false.org 2004-03-23 16:59:57 UTC
From: Daniel Jacobowitz <drow@false.org>
To: klaas.gadeyne@mech.kuleuven.ac.be
Cc: gdb-gnats@sources.redhat.com
Subject: Re: c++/1593: Problem with nested namespaces
Date: Tue, 23 Mar 2004 11:59:57 -0500

 On Tue, Mar 23, 2004 at 04:44:06PM -0000, klaas.gadeyne@mech.kuleuven.ac.be wrote:
 > namespace WRAPPED
 > {
 >   class Foo : public BASE::Foo
 >   {
 >   public:
 >     Foo() : BASE::Foo(){};
 >     virtual ~Foo(){};
 >   };
 > }
 
 > So mywrapped is now reported to be empty, where I expected to see
 > something like
 > 
 > 1: mywrapped = {<Foo> = {<No data fields>}, <No data fields>}
 
 > The problem does not exist when:
 > - The code is compiled with g++ 2.95.4
 > - All code is inlined in 1 file (yes, that's why there are 3 files above :)
 > - I omit the member function method and put the constructor implementation
 >   in the cpp file.
 > - When Foo in namespace WRAPPED is renamed into Boo
 
 Yes.  Unfortunately, this isn't a bug in GDB - there just isn't enough
 information in the object files.  If you try a prerelease snapshot of
 GCC 3.4, I believe it will work OK.
 
 The basic problem is that by explicitly providing a constructor and
 destructor, you've suppressed the implicit operator=.  In GCC 3.x (but
 not in 2.95.4, to explain the first bullet above), this is the only
 default method whose full mangled name appears in the debug
 information - constructors and destructors don't.  We use it to infer
 the correct name of the type.
 
 The other things just tweak the search order.  We're looking up the
 type Foo by name and finding the wrong one - we don't realize it's
 really WRAPPED::Foo.
 
 -- 
 Daniel Jacobowitz
 MontaVista Software                         Debian GNU/Linux Developer

Comment 2 David Carlton 2004-03-23 17:31:23 UTC
From: David Carlton <carlton@kealia.com>
To: Daniel Jacobowitz <drow@false.org>
Cc: GNATS Filer <gdb-gnats@sources.redhat.com>
Subject: Re: c++/1593: Problem with nested namespaces
Date: Tue, 23 Mar 2004 09:31:23 -0800

 On 23 Mar 2004 17:08:02 -0000, Daniel Jacobowitz <drow@false.org> said:
  
 >  The basic problem is that by explicitly providing a constructor and
 >  destructor, you've suppressed the implicit operator=.
 
 Now I'm confused.  Looking at the assembly file, you're quite right:
 there isn't an operator= listed in the class definition.  But I think
 there should be one - a user-defined constructor/destructor doesn't
 suppress a compiler-defined operator=.  So, for example, if you
 replace his main() by this:
 
 int main()
 {
   Foo mywrapped;
   Foo mywrapped2;
 
   mywrapped2 = mywrapped;
 
   return 0;
 }
 
 then you'll see operator= in the class definition in the debug info.
 
 Which suggests to me that GCC (I used Red Hat's 3.2, but it must also
 be the case for the GCC 3.3 that he used) doesn't emit identical debug
 info for the definition of the same class in different translation
 units.  Which really sucks, from GDB's point of view.

Comment 3 drow@false.org 2004-03-23 17:46:06 UTC
From: Daniel Jacobowitz <drow@false.org>
To: David Carlton <carlton@kealia.com>
Cc: GNATS Filer <gdb-gnats@sources.redhat.com>
Subject: Re: c++/1593: Problem with nested namespaces
Date: Tue, 23 Mar 2004 12:46:06 -0500

 On Tue, Mar 23, 2004 at 09:31:23AM -0800, David Carlton wrote:
 > On 23 Mar 2004 17:08:02 -0000, Daniel Jacobowitz <drow@false.org> said:
 >  
 > >  The basic problem is that by explicitly providing a constructor and
 > >  destructor, you've suppressed the implicit operator=.
 > 
 > Now I'm confused.  Looking at the assembly file, you're quite right:
 > there isn't an operator= listed in the class definition.  But I think
 > there should be one - a user-defined constructor/destructor doesn't
 > suppress a compiler-defined operator=.  So, for example, if you
 > replace his main() by this:
 > 
 > int main()
 > {
 >   Foo mywrapped;
 >   Foo mywrapped2;
 > 
 >   mywrapped2 = mywrapped;
 > 
 >   return 0;
 > }
 > 
 > then you'll see operator= in the class definition in the debug info.
 > 
 > Which suggests to me that GCC (I used Red Hat's 3.2, but it must also
 > be the case for the GCC 3.3 that he used) doesn't emit identical debug
 > info for the definition of the same class in different translation
 > units.  Which really sucks, from GDB's point of view.
 
 OK, now I'm _really_ confused.  I think that I said the wrong thing in
 the first place, and then both you and I have arranged to see what we
 expected to see since.  In particular:
 
  GDB 6.0 goes into an infinite loop
  GDB 6.1 works as described in the report
    $1 = {<> = {<No data fields>}, <No data fields>}
 
 (gdb) ptype mywrapped
 type = class WRAPPED::Foo : public Foo {
   public:
     void Foo(void);
     ~Foo(int);
 }
 
 So it's the base type whose name we got wrong.
 
 BASE::Foo in wrapper_object.o has an operator= and we infer its name.
 BASE::Foo in wrapper.o is just a declaration.  So it has nothing from
 which to infer its name, and we lose.  If we had DW_TAG_namespace, we
 would still get the right results.  I see the operator= for
 WRAPPED::Foo with both versions of main(); could you recheck?
 
 -- 
 Daniel Jacobowitz
 MontaVista Software                         Debian GNU/Linux Developer

Comment 4 David Carlton 2004-03-23 19:03:12 UTC
From: David Carlton <carlton@kealia.com>
To: Daniel Jacobowitz <drow@false.org>
Cc: GNATS Filer <gdb-gnats@sources.redhat.com>
Subject: Re: c++/1593: Problem with nested namespaces
Date: Tue, 23 Mar 2004 11:03:12 -0800

 On 23 Mar 2004 17:48:01 -0000, Daniel Jacobowitz <drow@false.org> said:
 
 >   GDB 6.0 goes into an infinite loop
 >   GDB 6.1 works as described in the report
 >     $1 = {<> = {<No data fields>}, <No data fields>}
  
 >  (gdb) ptype mywrapped
 >  type = class WRAPPED::Foo : public Foo {
 >    public:
 >      void Foo(void);
 >      ~Foo(int);
 >  }
  
 >  So it's the base type whose name we got wrong.
  
 >  BASE::Foo in wrapper_object.o has an operator= and we infer its
 >  name.  BASE::Foo in wrapper.o is just a declaration.
 
 That's what I was missing - I had just assumed that, since there were
 methods mentioned in the debug info for BASE::Foo, that it was a
 definition, but it is in fact a declaration.  And it's fine for
 declarations to contain different amounts of information in different
 translation units, of course.
 
 >  So it has nothing from which to infer its name, and we lose.
 
 >  If we had DW_TAG_namespace, we would still get the right results.
 
 That should be the case.  Though, unfortunately, it isn't so simple;
 when I used my hacked GCC 3.2 that generates DW_TAG_namespace, things
 work fine:
 
 (gdb) p mywrapped
 $1 = {<BASE::Foo> = {_vptr.Foo = 0x80496c0}, <No data fields>}
 
 But when I use "g++ (GCC) 3.5.0 20040119", we're back to our old
 behavior:
 
 (gdb) p mywrapped
 $1 = {<> = {<No data fields>}, <No data fields>}
 
 I'll have to look into that further.
 
 (Hmm: should determine_class_name restore processing_current_prefix if
 it has to change it?  Probably, but looking at the callers, we're
 currently safe, so that's not the issue here.)
Comment 5 Tom Tromey 2010-01-22 21:07:24 UTC
With a recent (F11) gcc and CVS head gdb, I get:

(gdb) p mywrapped
$1 = (WRAPPED::Foo) {
  <BASE::Foo> = {
    _vptr.Foo = 0x8048730
  }, <No data fields>}

This looks correct to me.
Given the age of the reported GCC, I am closing this as fixed.