Bug 17300 - [mingw/cygwin]: dllimport of C++ classes with vtables causes bogus symbol ref
Summary: [mingw/cygwin]: dllimport of C++ classes with vtables causes bogus symbol ref
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.2.2
Assignee: Not yet assigned to anyone
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: patch, wrong-code
Depends on:
Blocks:
 
Reported: 2004-09-02 21:50 UTC by Danny Smith
Modified: 2009-05-08 05:27 UTC (History)
4 users (show)

See Also:
Host: i686-pc-mingw32
Target: i686-pc-mingw32
Build: i686-pc-mingw32
Known to work:
Known to fail:
Last reconfirmed: 2005-07-21 00:30:53


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Danny Smith 2004-09-02 21:50:54 UTC
The dllimport attribute on windows targets does not play nice with the
heuristics used to emit vtables. Example:

==========================================
// dllimport-vtable.C
struct __attribute__((dllimport)) S {
  virtual void f(){};
};

S s;
==========================================

using gcc version 3.5.0 20040901 (experimental)

> g++ -S dllimport-vtable.C

produces:

	.file	"dllimport-vtable.C"
.globl _s
	.bss
	.align 4
_s:
	.space 4
.globl _)
	.section	.rdata$_ZTV1S,"dr"
	.linkonce same_size
	.align 8
_):			<<<< bogus symbol ref for _ZTV1S
	.long	0
	.long	__ZTI1S
	.long	__ZN1S1fEv


< snip >


	.section	.text$_ZN1SC1Ev,"x"
	.linkonce discard
	.align 2
.globl __ZN1SC1Ev
	.def	__ZN1SC1Ev;	.scl	2;	.type	32;	.endef
__ZN1SC1Ev:
LFB6:
	pushl	%ebp
LCFI2:
	movl	%esp, %ebp
LCFI3:
	movl	8(%ebp), %eax
	movl	__imp___ZTV1S, %edx  <<<< winnt.c changed the symbol ref
	addl	$8, %edx
	movl	%edx, (%eax)
	popl	%ebp
	ret
LFE6:


The import status specified by dllimport is ignored because of the
MULTIPLE_SYMBOL_SPACES override in cp/decl2.c:import_export_class.
Consequently, import_export_decl marks the vtable as comdat. However,
the decl also still has the DECL_EXTERNAL flag. When
winnt.c:i386_pe_mark_dllimport sees the DECL_EXTERNAL it thinks it is
okay to honour the dllimport attribute and so replaces the
SYMBOL_REF_DECL with an encoded identifier. 


I don't think this is a new bug, it's just easier to reproduce now.  I
believe that 

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12413

is caused by similar lossage of symbol ref

I see two ways to fix.

1) Removing the MULTIPLE_SYMBOL_SPACES override in import_export_class
works, With #pragma interface deprecated, some of the earlier reasons for
this override are probably gone. However, it means that a new
MULTIPLE_SYMBOL_SPACES guard (or similar) is needed in
import_export_decl when handling tinfo decls. Marking tinfo decls as
dllimport causes problems when a tinfo node needs to be put into a
vtable or tinfo table of a derived class: Dllimported symbols have
DECL_NON_ADDR_CONST_P set (can't treat a pointer to this as a constant
address) since the data is obtained as *__imp___ZTI1S

I'm currently testing a patch along these lines and will submit shortly

2) Change winnt.c so that it never imports vtables.  I tried this once
before and it led to frequent failures with unresolved vtable references
in multiple inheritance case.  So that solution, besides being inefficient, 
needs some work.


Danny
Comment 1 Danny Smith 2004-09-04 00:05:12 UTC
Patch submitted:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00442.html
Danny
Comment 2 Andrew Pinski 2004-09-09 03:42:16 UTC
Confirmed.
Comment 3 Danny Smith 2007-09-21 03:04:02 UTC
The example  produces a correct label for the vtable (_ZTV1S) with 4.2.2 and trunk, so closing as fixed.
However we still emit the definition of the vtable  even though we import it from the dll  as  __imp___ZTV1S when constructing the object s. 

Danny