Workaround for virtual function/dllimport bug, also patch guidance request

Mumit Khan khan@NanoTech.Wisc.EDU
Fri Dec 31 23:54:00 GMT 1999


Jason Merrill <jason@cygnus.com> writes:
> 
>  > Because of the usual `can't take the address of imported symbol' crap. 
> 
> Does that apply to all non-functions?  Why?  How do we import vtables, then?

It was my mistake in looking at the symbol table instead of the assembler.
Following is an annotated example of what MSVC does.

> I'd prefer to spend the time to get it right.

So would I of course.

Quick summary: It does indeed look like MSVC is generating vtables and RTTI
for *all* imported classes, but it's hiding the vtables for imported classes 
in something called ``local vftable''. It's essentially the same behavior
as the MULTIPLE_SYMBOL_SPACES case.

Take the following code:

  struct __declspec(dllimport)
  Base 
  {
    Base ();
    virtual ~Base ();
    virtual void vf1 ();
  };

  struct 
  Derived : public Base
  {
    Derived () { }
    virtual ~Derived () { }
    virtual void vf1 ();
  };

  static void f1 (Base*);

  void
  Derived::vf1 () {
    f1 (new Base);
    f1 (new Derived);
  }

  static void 
  f1 (Base* b)
  {
    b->vf1 ();
    delete b;
  }

Now look at the symbols, especially the ones marked with '<<':
(fyi type 'R' is COMDAT)

  00000000 T ??0Derived@@QAE@XZ
  00000000 T ??1Derived@@UAE@XZ
	   U ??2@YAPAXI@Z
	   U ??3@YAXPAX@Z
  00000004 R ??_7Derived@@6B@			<< Derived::vtable
	   U ??_7type_info@@6B@			<< type_info::vtable
	   U ??_EBase@@UAEPAXI@Z
	   U ??_EDerived@@UAEPAXI@Z
  00000000 T ??_GBase@@UAEPAXI@Z
	   U ??_GBase@@UAEPAXI@Z
  00000000 T ??_GDerived@@UAEPAXI@Z
	   U ??_GDerived@@UAEPAXI@Z
  00000000 D ??_R0?AUBase@@@8			<< Begin RTTI syms ...
  00000000 D ??_R0?AUDerived@@@8
  00000000 R ??_R1A@?0A@A@Base@@8
  00000000 R ??_R1A@?0A@A@Derived@@8
  00000000 R ??_R2Base@@8
  00000000 R ??_R2Derived@@8
  00000000 R ??_R3Base@@8
  00000000 R ??_R3Derived@@8
  00000000 R ??_R4Base@@6B@
  00000000 R ??_R4Derived@@6B@			<< ... end RTTI syms
  00000004 R ??_SBase@@6B@			<< Base::`local vtable'
  00000080 t ?f1@@YAXPAUBase@@@Z
	   U ?vf1@Base@@UAEXXZ
  00000000 T ?vf1@Derived@@UAEXXZ
  000b1fe8 a @comp.id
	   U __imp_??0Base@@QAE@XZ
	   U __imp_??1Base@@UAE@XZ

Note how it does indeed emit vtable for imported class, Base, but under
a different name which I had missed before -- ??_SBase@@6B@. And it of
course emits RTTI for imported classes as well.

I'm attaching the .asm generated as well as the output of dumbin, which
is sometimes quite useful.

Wish I'd done this earlier.

With this, I believe the solution is the following:

1. Restore the older behavior in import_export_class, ie., the same as
   MULTIPLE_SYMBOL_SPACES case, and don't import vtables and RTTI nodes
   or functions.

2. Fix the remaining issue with check_for_override in tsubst_decl. I'll
   get an updated patch out today.
  
Regards,
Mumit



More information about the Gcc mailing list