Bug 13041 - Virtual base class botch
Summary: Virtual base class botch
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-29 08:10 UTC by Dennis
Modified: 2022-08-10 17:09 UTC (History)
3 users (show)

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


Attachments
GDB log (10.21 KB, text/plain)
2011-08-04 15:03 UTC, Dennis
Details
test program that compiles ok (398 bytes, text/plain)
2012-12-19 21:58 UTC, Tom Tromey
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dennis 2011-07-29 08:10:43 UTC
Hello,

First of all I'd like to say I do use a library (SystemC and TLM)and alot of classes in it use virtual inherintance. So I cannot ignore the virtual inheritance. My program uses GDB MI and it really depends on SystemC/TLM so I can hardly make a program which can construct the realy problem, but i try to explain the bug I think it is.

When I do use "-var-list-children --all-values VARNAME" on a var where VARNAME is of an object derived from 2 class in a particular order everything goes ok(like Example01), but when a switch them I get a virtual base class botch so I think it's a bug?
Example 01 Everything is ok:

class CPU: public tlm_bw_transport_if<>, public sc_module
{
public:
	tlm_initiator_socket<> socket;

	SC_CTOR(CPU): //constructor 
	socket("CPUSocketNAME")
	{
		socket.bind(*this);
	}
	virtual ~CPU(){} //Destructor
//.......
//....... etc
};

tlm_bw_transport_if is out of the TLM source and this class is declared as:
template <typename TYPES = tlm_base_protocol_types>
class tlm_bw_transport_if
  : public virtual tlm_bw_nonblocking_transport_if<typename TYPES::tlm_payload_type,
                                                   typename TYPES::tlm_phase_type>
  , public virtual tlm_bw_direct_mem_if
{};

And those base classes are inherited from some other virtual base classes etc.

With this example it goed wrong:
class CPU: public sc_module, public tlm_bw_transport_if<>
{
public:
	tlm_initiator_socket<> socket;

	SC_CTOR(CPU): //constructor 
	socket("CPUSocketNAME")
	{
		socket.bind(*this);
	}
	virtual ~CPU(){} //Destructor
//.......
//....... etc
};

void main()
{
   CPU cpu01("myCPU");
}

The think my program does is setting a breakpoint in the sc_module constructor So that's the point my program stays when I do try to get the varname where the CPU object is stored in(that's cpu01). When I do have it, I use the command 
"-var-list-children --all-values VARNAME" to get all the base classes of CPU object cpu. But when i try this in the first example everything is OK and I can get the base classes of tlm_bw_transport_if<>, but when I use the GDB MI command with example 2 on the variabele it sais "virtual base class botch"

var01 is a gdb variabele on cpu01.
the gdb command I use, is like "-var-list-children --all-values var01.tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>"

I hope I am clear about the problem and you can understand the problem. Sorry if my english or explaination is a bit bad.
Comment 1 Tom Tromey 2011-08-03 20:36:39 UTC
It would be most helpful if you could construct a simple,
self-contained test case so we can reproduce the bug.
Your compiler info probably also matters.

If you can't do this, then maybe some more info from debugging
gdb itself would be useful.  That is really not as good though.
Comment 2 Pedro Alves 2011-08-04 09:47:02 UTC
You could/should try a recent gdb (7.3 or mainline cvs) too.  The "Virtual base class botch" umbrella error is gone, and the error you'll get with a more recent gdb, if you get any, should be a bit more descriptive of what gdb thinks is wrong, I think.  With luck, you'll find the bug has already been fixed.
Comment 3 Dennis 2011-08-04 10:42:02 UTC
Error isn't fixed in GDB 7.3 as far as I still get the error now. I'll try to explain what the real problem is but a example is hard to make, because I use a wrapper around the GDB commands that are used, and the wrapper isn't made by me.. So I cannot exactly see what the commands are that are send to GDB MI. Only if it fails.

Example code:

#include <iostream>

using namespace std;
using namespace sc_core;

class sc_module
{
public:
	sc_module()
	{
		sc_module_init();
	}
	void
	sc_module_init()
	{
		int a = 0;
		a++;
		a += 4;
	}
};

class sc_interface{};
class tlm_bw_nonblocking_transport_if : public virtual sc_interface{};
class tlm_bw_direct_mem_if : public virtual sc_interface{};

class tlm_bw_transport_if: public virtual tlm_bw_nonblocking_transport_if, public virtual tlm_bw_direct_mem_if{};

class CPU: public tlm_bw_transport_if, public sc_module
{
public:
	CPU(){}
	virtual ~CPU(){} //Destructor
};

class tlm_fw_nonblocking_transport_if : public virtual sc_interface {};
class tlm_blocking_transport_if : public virtual sc_interface {};
class tlm_fw_direct_mem_if : public virtual sc_interface{};
class tlm_transport_dbg_if : public virtual sc_interface{};

class tlm_fw_transport_if
  : public virtual tlm_fw_nonblocking_transport_if
  , public virtual tlm_blocking_transport_if
  , public virtual tlm_fw_direct_mem_if
  , public virtual tlm_transport_dbg_if
{};

class RAM: public sc_module, public tlm_fw_transport_if
{
public:
	RAM(){}
	virtual ~RAM(){} //Destructor
};

class Top: public sc_module
{
public:
	Top(){};

	CPU cpu;
	RAM ram;
};

int main( int argc , char **argv )
{
	Top top();
	cout << "Done" << endl;
	return 0;
}


I run:

gdb -n -readnow --interpreter=mi --args ../../Example

-break-insert sc_module::sc_module_init


If it's hit the first time, cpu is made, that's no problem.
But second time it hits ram is made, then I get a virtual base class botch.

What I do when sc_module_init is hit for the second time(so ram is made):
I go up the stacklevel so I am in main.
Then I create the var named var24 and I go look what the childs of it are if i check var24.public.ram.tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>

with the command "-var-list-children --all-values \"var24.public.ram.tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>\""
I get the error.

I hope the problem is more clear now.
Ask if it isn't, please.
Comment 4 Pedro Alves 2011-08-04 14:09:34 UTC
>g++ example.cc -o example 
example.cc:4:17: error: ‘sc_core’ is not a namespace-name
example.cc:4:24: error: expected namespace-name before ‘;’ token

Removing the using sc_core statement, the example compiles.

> -break-insert sc_module::sc_module_init

In your example, there are no instances of sc_module, so
sc_module::sc_module_init was optimized out.

Please make sure you only attach/post examples that compile and work.  If you can reproduce the issue with that example code, then please attach the compiled binary.

> Error isn't fixed in GDB 7.3 as far as I still get the error now.

The "virtual base class botch" error is no longer present on 7.3.
What error did you get exactly?

> I hope the problem is more clear now.
> Ask if it isn't, please.

Can you try issuing "set logging on" and "set trace-commands on"?  That'll generate a gdb.txt file with the log of all the gdb commands.

A gdb backtrace would also be useful.
Comment 5 Dennis 2011-08-04 15:03:56 UTC
Created attachment 5874 [details]
GDB log
Comment 6 Dennis 2011-08-04 15:29:46 UTC
Sorry.
I made some mistakes in my example.

I added a GDB log. The virtual base class botch is popping up between de run command and all the warnings.(almost at the end of the file.)
But it isn't stored in the file.

(In reply to comment #4)
> >g++ example.cc -o example 
> example.cc:4:17: error: ‘sc_core’ is not a namespace-name
> example.cc:4:24: error: expected namespace-name before ‘;’ token
> 
> Removing the using sc_core statement, the example compiles.
> 
> > -break-insert sc_module::sc_module_init
> 
> In your example, there are no instances of sc_module, so
> sc_module::sc_module_init was optimized out.
> 
Sorry real stupid piece of code.
It should be Top top; and not Top top();

> Please make sure you only attach/post examples that compile and work.  If you
> can reproduce the issue with that example code, then please attach the compiled
> binary.
> 
> > Error isn't fixed in GDB 7.3 as far as I still get the error now.
> 
> The "virtual base class botch" error is no longer present on 7.3.
> What error did you get exactly?

I am really sure my program gives the error: "virtual base class botch"  but if you say it doesn't excist anymore. I should better start looking GDB is installed like it should....

> 
> > I hope the problem is more clear now.
> > Ask if it isn't, please.
> 
> Can you try issuing "set logging on" and "set trace-commands on"?  That'll
> generate a gdb.txt file with the log of all the gdb commands.
> 
> A gdb backtrace would also be useful.

Attached with this report
Comment 7 Pedro Alves 2011-08-04 15:56:39 UTC
> I am really sure my program gives the error: "virtual base class botch"  but if
> you say it doesn't excist anymore. I should better start looking GDB is
> installed like it should....

We're probably both right and wrong.  I deleted 6 instances of that error recently, but I now see there were two left behind.  My grepping failed to find them before
because it's actually:

  "virtual baseclass botch"

note no space.

Please attach the fixed example source that one can use to reproduce this, plus the resulting compiled binary.
Comment 8 Tom Tromey 2012-12-19 21:56:14 UTC
I can definitely make this test case do something wrong-ish.

First, I removed the bad "using" and changed the line to "Top top;".
I'll attach mine in a bit.

Then I set a breakpoint in sc_module_init and ran.
(Making sure to use gdb -nx...)
Then:

(gdb) up
#1  0x0000000000400a5e in sc_module::sc_module (this=0x7fffffffe3c0)
    at pr.cc:10
10	        sc_module_init();
(gdb) 
#2  0x0000000000400eda in Top::Top (this=0x7fffffffe3c0) at pr.cc:57
57	    Top(){};
(gdb) p *this
$4 = {<sc_module> = {<No data fields>}, cpu = warning: can't find linker symbol for virtual table for `CPU' value

{<tlm_bw_transport_if> = {<tlm_bw_nonblocking_transport_if> = <invalid address>, <tlm_bw_direct_mem_if> = <invalid address>, <No data fields>}, <sc_module> = {<No data fields>}, <No data fields>}, ram = warning: can't find linker symbol for virtual table for `RAM' value

{<sc_module> = {<No data fields>}, <tlm_fw_transport_if> = {<tlm_fw_nonblocking_transport_if> = <invalid address>, <tlm_blocking_transport_if> = <invalid address>, <tlm_fw_direct_mem_if> = <invalid address>, <tlm_transport_dbg_if> = <invalid address>, <No data fields>}, <No data fields>}}


It seems like gdb is confused by a partially-construct object.

It isn't totally clear to me whether this is related to the original
bug, but I'm reopening nonetheless.
Comment 9 Tom Tromey 2012-12-19 21:58:11 UTC
Created attachment 6785 [details]
test program that compiles ok
Comment 10 Tom Tromey 2022-08-10 17:09:24 UTC
I think this is more of a C++ problem than an MI problem.