This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch] Fix PR/17300: dllimport of C++ classes with vtables causes bogus symbol ref
- From: Danny Smith <danny_smith_0000 at yahoo dot co dot nz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 4 Sep 2004 12:00:52 +1200 (NZST)
- Subject: [Patch] Fix PR/17300: dllimport of C++ classes with vtables causes bogus symbol ref
PR 17300 results from a loss of the symbol ref for vtables that are marked as
dllimport and also emitted as comdat symbols
In cp/decl2.c: import_export_class, the import status specified by dllimport
is ignored because of the MULTIPLE_SYMBOL_SPACES override,.
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. The tinfo object is emitted
because of the comdat, but its symbol ref has been lost.
Removing the MULTIPLE_SYMBOL_SPACES override in import_export_class is
one way to fix, With pragma interface deprecated, some of the earlier
reasons for this override are probably gone. Losing this override lets
dllimport actually means what it says: we know that this an
interface_only class. We leave it to target-specific code to do any
encoding to translate to the dllimport symbol space
However, doing this 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 the class'
vtable or the 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). This is how we get a dllimported object:
extern long* _imp___ZTI1S;
long _ZTI1S = *_imp___ZTI1S;
We can't do that when, eg, initializing the (static) vtable for S.
This is proposed fix. It works for me on i686-pc-mingw32 on my projects
that use dllimport of polymorphic classes. It fixes PR 12413. If this is
not right, I have an alternative patch that leaves the
MULTIPLE_SYMBOL_SPACES define alone, but removes the comdat flag from
vtables of dllimported classes. *iff* they have a key method
Although, MULTIPLE_SYMBOL_SPACES is almost synonymomous with
TARGET_DLLIMPORT_DECL_ATTRIBUTES, one target (sh/symbian) defines
the latter, but not the former, so I check for both when handling
typeinfo decls. Perhaps, I misunderstand the sh/symbian dllimport rules,
but I think that since symbian also sets DECL_NON_ADDR_CONST_P on
dllimports, it should also be using this for dllimported RTTI objects.
Danny
2004-09-04 Danny Smith <dannysmith@users.sourceforge.net>
* defaults.h (MULTIPLE_SYMBOL_SPACES): Define to 0 by default.
* config/i386/cygming.h (MULTIPLE_SYMBOL_SPACES): Define to 1;
* config/i386/i386-interix.h (MULTIPLE_SYMBOL_SPACES): Likewise.
* config/arm/pe.h (MULTIPLE_SYMBOL_SPACES): Likewise.
* config/i386/beos-elf.h (MULTIPLE_SYMBOL_SPACES): Likewise.
* cp/decl2.c (import_export_class): Don't override class
import status because of MULTIPLE_SYMBOL_SPACES.
(import_export_decl): Do override import status of typeinfo
nodes for dllimported classes if MULTIPLE_SYMBOL_SPACES.
Index: defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.151
diff -c -3 -p -r1.151 defaults.h
*** defaults.h 25 Aug 2004 07:34:49 -0000 1.151
--- defaults.h 2 Sep 2004 20:55:25 -0000
*************** do { fputs (integer_asm_op (POINTER_SIZE
*** 794,797 ****
--- 794,804 ----
#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
#endif
+ /* Define this macro to 1 if in some cases global symbols from one translation
+ 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). */
+ #ifndef MULTIPLE_SYMBOL_SPACES
+ #define MULTIPLE_SYMBOL_SPACES 0
+ #endif
#endif /* ! GCC_DEFAULTS_H */
Index: config/arm/pe.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/pe.h,v
retrieving revision 1.28
diff -c -3 -p -r1.28 pe.h
*** config/arm/pe.h 18 Aug 2004 16:22:05 -0000 1.28
--- config/arm/pe.h 2 Sep 2004 20:56:10 -0000
***************
*** 78,88 ****
call_used_regs [11] = 1;
! /* Define this macro if in some cases global symbols from one translation
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
#define TARGET_ASM_UNIQUE_SECTION arm_pe_unique_section
#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
--- 78,88 ----
call_used_regs [11] = 1;
! /* Define this macro to 1 if in some cases global symbols from one translation
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 1
#define TARGET_ASM_UNIQUE_SECTION arm_pe_unique_section
#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
Index: config/i386/beos-elf.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/beos-elf.h,v
retrieving revision 1.22
diff -c -3 -p -r1.22 beos-elf.h
*** config/i386/beos-elf.h 4 Aug 2004 19:37:18 -0000 1.22
--- config/i386/beos-elf.h 2 Sep 2004 20:56:10 -0000
*************** Boston, MA 02111-1307, USA. */
*** 235,242 ****
/* BeOS headers are C++-aware (and often use C++). */
#define NO_IMPLICIT_EXTERN_C
! /* Define this macro if in some cases global symbols from one translation
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
--- 235,242 ----
/* BeOS headers are C++-aware (and often use C++). */
#define NO_IMPLICIT_EXTERN_C
! /* Define this macro to 1 if in some cases global symbols from one translation
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 1
Index: config/i386/cygming.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/cygming.h,v
retrieving revision 1.20
diff -c -3 -p -r1.20 cygming.h
*** config/i386/cygming.h 19 Aug 2004 20:47:12 -0000 1.20
--- config/i386/cygming.h 2 Sep 2004 20:56:11 -0000
*** 258,268 ****
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
! /* Define this macro if in some cases global symbols from one translation
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
--- 258,268 ----
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
! /* Define this macro to 1 if in some cases global symbols from one translation
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 1
extern void i386_pe_unique_section (TREE, int);
#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
Index: config/i386/i386-interix.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-interix.h,v
retrieving revision 1.50
diff -c -3 -p -r1.50 i386-interix.h
*** config/i386/i386-interix.h 12 Aug 2004 13:56:59 -0000 1.50
--- config/i386/i386-interix.h 2 Sep 2004 20:56:11 -0000
*************** while (0)
*** 337,347 ****
.data$ sections correctly. See corresponding note in i386/interix.c.
MK. */
! /* Define this macro if in some cases global symbols from one translation
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
--- 337,347 ----
.data$ sections correctly. See corresponding note in i386/interix.c.
MK. */
! /* Define this macro to 1 if in some cases global symbols from one translation
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 1
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.741
diff -c -3 -p -r1.741 decl2.c
*** cp/decl2.c 31 Aug 2004 20:29:26 -0000 1.741
--- cp/decl2.c 2 Sep 2004 20:57:00 -0000
*************** import_export_class (tree ctype)
*** 1472,1482 ****
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
- #ifdef MULTIPLE_SYMBOL_SPACES
- if (import_export == -1)
- import_export = 0;
- #endif
-
/* Allow backends the chance to overrule the decision. */
if (targetm.cxx.import_export_class)
import_export = targetm.cxx.import_export_class (ctype, import_export);
--- 1472,1477 ----
*************** import_export_decl (tree decl)
*** 1830,1845 ****
if (CLASS_TYPE_P (type))
{
import_export_class (type);
! if (CLASSTYPE_INTERFACE_KNOWN (type)
! && TYPE_POLYMORPHIC_P (type)
! && CLASSTYPE_INTERFACE_ONLY (type)
! /* If -fno-rtti was specified, then we cannot be sure
! that RTTI information will be emitted with the
! virtual table of the class, so we must emit it
! wherever it is used. */
! && flag_rtti)
import_p = true;
! else
{
comdat_p = true;
if (CLASSTYPE_INTERFACE_KNOWN (type)
--- 1825,1849 ----
if (CLASS_TYPE_P (type))
{
import_export_class (type);
!
! /* Do not import tinfo nodes if the class has dllimport attribute.
! Dllimports do not have a constant address at compile time, so
! static initialization of tables with RTTI fields is a problem.
! Set to comdat instead. */
! if (MULTIPLE_SYMBOL_SPACES
! && TARGET_DLLIMPORT_DECL_ATTRIBUTES
! && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (type)))
! comdat_p = true;
! else if (CLASSTYPE_INTERFACE_KNOWN (type)
! && TYPE_POLYMORPHIC_P (type)
! && CLASSTYPE_INTERFACE_ONLY (type)
! /* If -fno-rtti was specified, then we cannot be sure
! that RTTI information will be emitted with the
! virtual table of the class, so we must emit it
! wherever it is used. */
! && flag_rtti)
import_p = true;
! else
{
comdat_p = true;
if (CLASSTYPE_INTERFACE_KNOWN (type)
Find local movie times and trailers on Yahoo! Movies.
http://au.movies.yahoo.com