------- Additional Comments From dannysmith at gcc dot gnu dot org 2004-01-19 21:35 ------- Hello.
This bug is caused by the way vtable are handled in cp/decl2.c (import_export_vtable) vs the need for the dllimport marking mechanism to avoid marking defined data as dllimport. The vtable may be first marked as DECL_EXTERNAL when import_export_vtable is called by maybe_emit_vtables() and then later (when final == 1), the DECL_EXTERNAL is removed. This change in storage class causes the problems. When config/i386/winnt.c (i386_pe_dllimport_p) sees the DECL_EXTERNAL on a vtable symbol from a dllimported class, it tells i386_pe_mark_dllimport() to decorate the symbol with _imp_ prefix, and to pass it through get_identifier. When the DECL_EXTERNAL is later removed by import_export_vtable, the vtable definition is emitted, but with a bogus identifier. Here is one way to fix: Patch (1) cp/ChangedLog decl2.c (import_export_vtable): Always set DECL_EXTERNAL for vtables of dllimported classes. Index: decl2.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v retrieving revision 1.695 diff -c -3 -p -r1.695 decl2.c *** decl2.c 13 Jan 2004 23:59:19 -0000 1.695 --- decl2.c 18 Jan 2004 02:45:21 -0000 *************** import_export_vtable (tree decl, tree ty *** 1447,1453 **** if (DECL_INTERFACE_KNOWN (decl)) return; ! if (TYPE_FOR_JAVA (type)) { TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; --- 1447,1454 ---- if (DECL_INTERFACE_KNOWN (decl)) return; ! if (TYPE_FOR_JAVA (type) ! || lookup_attribute ("dllimport", TYPE_ATTRIBUTES (type))) { TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; Following is another way to fix, that is more intrusive. but by removing all the MULTIPLE_SYMBOL_SPACE business, we also get a fix for some problems with #pragma interface when linking against static libs. If we remove the MULTIPLE_SYMBOL_SPACES define for win32 targets. then we set both INTERFACE_ONLY and INTERFACE_KNOWN for dllimported classes. This is the right thing to do for vtables, since (1) vtables are always exported from the dll along with the class as long as the class type definition has the dllexport attribute (or if ld is told to --export-all), and (2) vtables get marked as dllimport when the class is imported. It is also the right thing to do for ordinary class members, since dllimport means the that symbols are defined exterally. However, it is not the right thing to do for type info nodes, since these do not currently inherit the dll attributes of the class (should they?). So rather than tarring the whole class with MULTIPLE_SYMBOL_SPACES protection, we just make a special excption for type info objects, and always emit them even if a class has INTERFACE_ONLY set by virtue of dllimport attribute. I suspect I'm missing something. The problem is I don't really understand the logic behind the MULTIPLE_SYMBOL_SPACES in the first place. Can someone more familiar with the history of this please suggest a testcase that shows why it was/is needed. Jason, since your name appears most often against MULTIPLE_SYMBOL_SPACES in ChangeLogs I've add you to CC. Patch (2): ChangeLog * config/i386/cygming.h (MULTIPLE_SYMBOL_SPACES): Don't define. cp/ChangeLog * decl2.c (import_export_tinfo): Always emit tinfo nodes for dllimported classes. Index: config/i386/cygming.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/i386/cygming.h,v retrieving revision 1.11 diff -c -3 -p -r1.11 cygming.h *** config/i386/cygming.h 2 Jan 2004 15:30:42 -0000 1.11 --- config/i386/cygming.h 19 Jan 2004 21:06:23 -0000 *************** do { \ *** 249,255 **** unit may not be bound to undefined symbols in another translation unit without user intervention. For instance, under Microsoft Windows symbols must be explicitly imported from shared libraries (DLLs). */ ! #define MULTIPLE_SYMBOL_SPACES extern void i386_pe_unique_section (TREE, int); #define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section --- 249,255 ---- unit may not be bound to undefined symbols in another translation unit without user intervention. For instance, under Microsoft Windows symbols must be explicitly imported from shared libraries (DLLs). */ ! #undef MULTIPLE_SYMBOL_SPACES extern void i386_pe_unique_section (TREE, int); #define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section Index: cp/decl2.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v retrieving revision 1.695 diff -c -3 -p -r1.695 decl2.c *** cp/decl2.c 13 Jan 2004 23:59:19 -0000 1.695 --- cp/decl2.c 19 Jan 2004 21:06:30 -0000 *************** import_export_tinfo (tree decl, tree typ *** 1740,1746 **** /* If -fno-rtti, we're not necessarily emitting this stuff with the class, so go ahead and emit it now. This can happen when a class is used in exception handling. */ ! && flag_rtti) { DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type); DECL_COMDAT (decl) = 0; --- 1740,1754 ---- /* If -fno-rtti, we're not necessarily emitting this stuff with the class, so go ahead and emit it now. This can happen when a class is used in exception handling. */ ! && flag_rtti ! #if defined (TARGET_DLLIMPORT_DECL_ATTRIBUTES) ! /* FIXME: Always emit typeinfo for dllimported classes, since we ! don't know if it has been exported from the library. Even if it ! has been exported, we would still need to add the dllimport ! attribute to the typeinfo object to get it to link correctly. */ ! && !lookup_attribute ("dllimport", TYPE_ATTRIBUTES (type)) ! #endif ! ) { DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type); DECL_COMDAT (decl) = 0; Danny -- What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at redhat dot com, | |dannysmith at gcc dot gnu | |dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12413