This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch]: Fix Pr 27650: Dllimport of virtual methods


Hello

PR 27650 results from the invalid initialization of a vtable entry with
the address of a dllimported virtual method. The address of a dllimport
is not constant at compile time.

Although we take care not to use dllimport semantics on virtual methods
when we dllimport an entire class in config/1386/winnt-cxx.c, we do not
take care in the less usual case of an explicit dllimport attribute on a
virtual method. If the class has defined a key method then the vtable
will be emitted and it will need the const address of the virtual
method. 

We can't safely disallow the dllimport attribute on virtual methods at
attribute handling time in this case, because when we handle the
attribute we don't know that the method is virtual. One heavy-handed
option is to ignore the attribute for *all* methods, and accept the
small performance hit. Another solution is to unset the dllimport flag
and use "normal" import of the function when we find out that we need a
constant address. Like so:


Changelog

	2006-05-30  Danny Smith  <dannysmith@users.sourceforge.net>

	PR target/27650
	* config/i386/winnt.c (i386_pe_dllimport_p): Check
DECL_DLLIMPORT_P first.
 
cp/Changelog

	* decl2.c (mark_vtable_entries): Unset DECL_DLLIMPORT_P.

testsuite/Changelog

	* g++.dg/ext/dllimport12.C: New file.


Tested on i686-pc-mingw32.

Danny

Index: gcc/config/i386/winnt.c
===================================================================
--- gcc/config/i386/winnt.c	(revision 114164)
+++ gcc/config/i386/winnt.c	(working copy)
@@ -148,9 +148,10 @@
        && TREE_CODE (decl) != FUNCTION_DECL)
     return false;
 
-  /* Lookup the attribute rather than rely on the DECL_DLLIMPORT_P
flag.
+  /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P
flag.
      We may need to override an earlier decision.  */
-  if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
+  if (DECL_DLLIMPORT_P (decl)
+      && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
     return true;
 
   /* The DECL_DLLIMPORT_P flag was set for decls in the class
definition
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 114164)
+++ gcc/cp/decl2.c	(working copy)
@@ -1233,6 +1233,14 @@
 	continue;
 
       fn = TREE_OPERAND (fnaddr, 0);
+
+      if (TARGET_DLLIMPORT_DECL_ATTRIBUTES)
+	/* When we handle the dllimport attribute we don't know
+	   if a function is virtual, so we may have set the dllimport
+	   flag.  However, we can't use dllimport semantics for this
+	   virtual method because we need to initialize the vtable
+	   entry with a constant address.  */
+	DECL_DLLIMPORT_P (fn) = 0;
       TREE_ADDRESSABLE (fn) = 1;
       /* When we don't have vcall offsets, we output thunks whenever
 	 we output the vtables that contain them.  With vcall offsets,
Index: gcc/testsuite/g++.dg/ext/dllimport12.C
===================================================================
--- gcc/testsuite/g++.dg/ext/dllimport12.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/dllimport12.C	(revision 0)
@@ -0,0 +1,22 @@
+// PR target/27650
+// Don't use dllimport semantics on virtual methods
+// { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+
+// Don't import explicitly virtual method.
+struct base
+{
+  virtual void key_method();
+  __attribute__((dllimport)) virtual ~base();
+};
+
+void base::key_method() {};
+
+
+// Nor an implicitly virtual method.
+struct derived : public base
+{
+  void key_method(); 
+  __attribute__((dllimport)) ~derived();
+};
+
+void derived::key_method() {};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]