Hello, Everyone.

Attached patch is just backport from gcc mailine. More correctly: its
backport of these patches:

http://gcc.gnu.org/ml/gcc-cvs/2005-10/msg00474.html
http://gcc.gnu.org/ml/gcc-cvs/2005-10/msg00718.html

The main aim of patches is better handling of dll* attributes especially
set on C++ stuff.

More patches will follow. However, this is the biggest one.

There are 3 files attached: patch against current llvm-gcc sources + 2
new files, which should be placed to gcc/config/i386 directory.

-- 
With best regards, Anton Korobeynikov.

Faculty of Mathematics & Mechanics, Saint Petersburg State University.

diff -r 9a4f61828020 gcc/config.gcc
--- a/gcc/config.gcc	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/config.gcc	Fri Feb 16 00:46:07 2007 +0300
@@ -1209,9 +1209,9 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 	xm_file=i386/xm-cygwin.h
 	tmake_file="i386/t-cygwin i386/t-cygming"
 	target_gtfiles="\$(srcdir)/config/i386/winnt.c"
-	extra_objs=winnt.o
+	extra_objs="winnt.o winnt-stubs.o"
 	c_target_objs=cygwin2.o
-	cxx_target_objs=cygwin2.o
+	cxx_target_objs="cygwin2.o winnt-cxx.o"
 	extra_gcc_objs=cygwin1.o
 	if test x$enable_threads = xyes; then
 		thread_file='posix'
@@ -1222,7 +1222,8 @@ i[34567]86-*-mingw32*)
 	xm_file=i386/xm-mingw32.h
 	tmake_file="i386/t-cygming i386/t-mingw32"
 	target_gtfiles="\$(srcdir)/config/i386/winnt.c"
-	extra_objs=winnt.o
+	extra_objs="winnt.o winnt-stubs.o"
+	cxx_target_objs="winnt-cxx.o"
 	case ${enable_threads} in
 	  "" | yes | win32) thread_file='win32' ;;
 	esac
diff -r 9a4f61828020 gcc/config/i386/cygming.h
--- a/gcc/config/i386/cygming.h	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/config/i386/cygming.h	Thu Feb 15 22:47:25 2007 +0300
@@ -422,6 +422,9 @@ extern int i386_pe_dllimport_p (tree);
 #undef TARGET_USE_LOCAL_THUNK_ALIAS_P
 #define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) (!DECL_ONE_ONLY (DECL))
 
+#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P i386_pe_valid_dllimport_attribute_p
+#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION i386_pe_adjust_class_at_definition
+
 #undef TREE
 
 #ifndef BUFSIZ
diff -r 9a4f61828020 gcc/config/i386/i386-protos.h
--- a/gcc/config/i386/i386-protos.h	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/config/i386/i386-protos.h	Thu Feb 15 23:09:35 2007 +0300
@@ -261,6 +261,13 @@ extern const char *i386_pe_strip_name_en
 extern const char *i386_pe_strip_name_encoding (const char *);
 extern const char *i386_pe_strip_name_encoding_full (const char *);
 extern void i386_pe_output_labelref (FILE *, const char *);
+extern int i386_pe_valid_dllimport_attribute_p (tree);
+
+/* In winnt-cxx.c and winnt-stubs.c  */
+extern void i386_pe_adjust_class_at_definition (tree);
+extern bool i386_pe_type_dllimport_p (tree);
+extern bool i386_pe_type_dllexport_p (tree);
+
 extern rtx maybe_get_pool_constant (rtx);
 
 extern char internal_label_prefix[16];
diff -r 9a4f61828020 gcc/config/i386/i386.c
--- a/gcc/config/i386/i386.c	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/config/i386/i386.c	Thu Feb 15 19:01:42 2007 +0300
@@ -2323,7 +2323,7 @@ ix86_function_ok_for_sibcall (tree decl,
 
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
   /* Dllimport'd functions are also called indirectly.  */
-  if (decl && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
+  if (decl && DECL_DLLIMPORT_P (decl)
       && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
     return false;
 #endif
diff -r 9a4f61828020 gcc/config/i386/t-cygming
--- a/gcc/config/i386/t-cygming	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/config/i386/t-cygming	Thu Feb 15 19:05:50 2007 +0300
@@ -16,4 +16,17 @@ winnt.o: $(srcdir)/config/i386/winnt.c $
 	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	$(srcdir)/config/i386/winnt.c
 
+winnt-cxx.o: $(srcdir)/config/i386/winnt-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+  $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	$(srcdir)/config/i386/winnt-cxx.c
+
+
+winnt-stubs.o: $(srcdir)/config/i386/winnt-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+  $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	$(srcdir)/config/i386/winnt-stubs.c
+
 STMP_FIXINC=stmp-fixinc
diff -r 9a4f61828020 gcc/config/i386/winnt.c
--- a/gcc/config/i386/winnt.c	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/config/i386/winnt.c	Thu Feb 15 23:46:59 2007 +0300
@@ -83,131 +83,64 @@ static tree
 static tree
 associated_type (tree decl)
 {
-  tree t = NULL_TREE;
-
-  /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer
-     to the containing class.  So we look at the 'this' arg.  */
-  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-    {
-      /* Artificial methods are not affected by the import/export status
-	 of their class unless they are COMDAT.  Implicit copy ctor's and
-	 dtor's are not affected by class status but virtual and
-	 non-virtual thunks are.  */
-      if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl))
-	t = TYPE_MAIN_VARIANT
-	  (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
-    }
-  else if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
-    t = DECL_CONTEXT (decl);
-
-  return t;
-}
-
-/* Return nonzero if DECL is a dllexport'd object.  */
+  return  (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+            ?  DECL_CONTEXT (decl) : NULL_TREE;
+}
+
+/* Return true if DECL is a dllexport'd object.  */
 
 int
 i386_pe_dllexport_p (tree decl)
 {
-  tree exp;
-
   if (TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
-  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
-  if (exp)
+
+  if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
     return 1;
 
-  /* Class members get the dllexport status of their class.  */
-  if (associated_type (decl))
-    {
-      exp = lookup_attribute ("dllexport",
-			      TYPE_ATTRIBUTES (associated_type (decl)));
-      if (exp)
-	return 1;
-    }
-
+  /* Also mark class members of exported classes with dllexport.  */
+  if (associated_type (decl)
+      && lookup_attribute ("dllexport",
+                           TYPE_ATTRIBUTES (associated_type (decl))))
+    return i386_pe_type_dllexport_p (decl);
+ 
   return 0;
 }
 
-/* Return nonzero if DECL is a dllimport'd object.  */
+/* Return true if DECL is a dllimport'd object.  */
 
 int
 i386_pe_dllimport_p (tree decl)
 {
-  tree imp;
-  int context_imp = 0;
-
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && TARGET_NOP_FUN_DLLIMPORT)
-    return 0;
-
   if (TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
 
-  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
-
-  /* Class members get the dllimport status of their class.  */
-  if (!imp && associated_type (decl))
-    {
-      imp = lookup_attribute ("dllimport",
-			      TYPE_ATTRIBUTES (associated_type (decl)));
-      if (imp)
-	context_imp = 1;
-    }
-
-  if (imp)
-    {
-      /* Don't mark defined functions as dllimport.  If the definition
-	 itself was marked with dllimport, than ix86_handle_dll_attribute
-	 reports an error. This handles the case when the definition
-	 overrides an earlier declaration.  */
-      if (TREE_CODE (decl) ==  FUNCTION_DECL && DECL_INITIAL (decl)
-	  && !DECL_INLINE (decl))
-	{
-	   /* Don't warn about artificial methods.  */
-	  if (!DECL_ARTIFICIAL (decl))
-	    warning ("%Jfunction '%D' is defined after prior declaration "
-		     "as dllimport: attribute ignored", decl, decl);
-	  return 0;
-	}
-
-      /* We ignore the dllimport attribute for inline member functions.
-	 This differs from MSVC behavior which treats it like GNUC
-	 'extern inline' extension.  */
-      else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
-        {
-	  if (extra_warnings)
-	    warning ("%Jinline function '%D' is declared as dllimport: "
-		     "attribute ignored.", decl, decl);
-	  return 0;
-	}
-
-      /*  Don't allow definitions of static data members in dllimport class,
-	  Just ignore attribute for vtable data.  */
-      else if (TREE_CODE (decl) == VAR_DECL
-	       && TREE_STATIC (decl) && TREE_PUBLIC (decl)
-	       && !DECL_EXTERNAL (decl) && context_imp)
-	{
-	  if (!DECL_VIRTUAL_P (decl))
-            error ("%Jdefinition of static data member '%D' of "
-		   "dllimport'd class.", decl, decl);
-	  return 0;
-	}
-
-      /* Since we can't treat a pointer to a dllimport'd symbol as a
-	 constant address, we turn off the attribute on C++ virtual
-	 methods to allow creation of vtables using thunks.  Don't mark
-	 artificial methods either (in associated_type, only COMDAT
-	 artificial method get import status from class context).  */
-      else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
-	       && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
-	return 0;
-
-      return 1;
-    }
+  /* Lookup the attribute rather than rely on the DECL_DLLIMPORT_P flag.
+     We may need to override an earlier decision.  */
+  if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
+    return 1;
+
+  /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
+     by  targetm.cxx.adjust_class_at_definition.  Check again to emit
+     warnings if the class attribute has been overriden by an
+     out-of-class definition.  */
+  if (associated_type (decl)
+      && lookup_attribute ("dllimport",
+                           TYPE_ATTRIBUTES (associated_type (decl))))
+    return i386_pe_type_dllimport_p (decl);
 
   return 0;
+}
+
+/* Handle the -mno-fun-dllimport target switch.  */
+int
+i386_pe_valid_dllimport_attribute_p (tree decl)
+{
+   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
+     return 0;
+   return 1;
 }
 
 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
@@ -251,10 +184,9 @@ i386_pe_mark_dllexport (tree decl)
   if (i386_pe_dllimport_name_p (oldname))
     {
       warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.",
-	       decl, decl);
+        decl, decl);
      /* Remove DLL_IMPORT_PREFIX.  */
       oldname += strlen (DLL_IMPORT_PREFIX);
-      DECL_NON_ADDR_CONST_P (decl) = 0;
     }
   else if (i386_pe_dllexport_name_p (oldname))
     return;  /*  already done  */
@@ -301,12 +233,13 @@ i386_pe_mark_dllimport (tree decl)
   else if (i386_pe_dllimport_name_p (oldname))
     {
       /* Already done, but do a sanity check to prevent assembler errors.  */
-      if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
-	{
-	  error ("%Jfailure in redeclaration of '%D': dllimport'd "
-		 "symbol lacks external linkage.", decl, decl);
-	  abort();
-	}
+      if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)
+          || !DECL_DLLIMPORT_P (decl))
+        {
+          error ("%Jfailure in redeclaration of '%D': dllimport'd "
+                 "symbol lacks external linkage.", decl, decl);
+          abort();
+        }
       return;
     }
 
@@ -324,8 +257,7 @@ i386_pe_mark_dllimport (tree decl)
   newrtl = gen_rtx_MEM (Pmode,symref);
   XEXP (DECL_RTL (decl), 0) = newrtl;
 
-  /* Can't treat a pointer to this as a constant address */
-  DECL_NON_ADDR_CONST_P (decl) = 1;
+  DECL_DLLIMPORT_P (decl) = 1;
 }
 
 /* Return string which is the former assembler name modified with a
@@ -338,7 +270,7 @@ gen_stdcall_or_fastcall_suffix (tree dec
   int total = 0;
   /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
      of DECL_ASSEMBLER_NAME.  */
-   const char *asmname =  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  const char *asmname =  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   char *newsym;
   char *p;
   tree formal_type;
@@ -351,7 +283,7 @@ gen_stdcall_or_fastcall_suffix (tree dec
   if (formal_type != NULL_TREE)
     {
       /* These attributes are ignored for variadic functions in
-	 i386.c:ix86_return_pops_args. For compatibility with MS
+         i386.c:ix86_return_pops_args. For compatibility with MS
          compiler do not add @0 suffix here.  */ 
       if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
         return DECL_ASSEMBLER_NAME (decl);
@@ -360,17 +292,17 @@ gen_stdcall_or_fastcall_suffix (tree dec
          by convert_arguments in c-typeck.c or cp/typeck.c.  */
       while (TREE_VALUE (formal_type) != void_type_node
 	     && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))	
-	{
-	  int parm_size
-	    = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
-	    /* Must round up to include padding.  This is done the same
-	       way as in store_one_arg.  */
-	  parm_size = ((parm_size + PARM_BOUNDARY - 1)
-		       / PARM_BOUNDARY * PARM_BOUNDARY);
-	  total += parm_size;
-	  formal_type = TREE_CHAIN (formal_type);\
-	}
-     }
+        {
+          int parm_size
+            = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
+          /* Must round up to include padding.  This is done the same
+             way as in store_one_arg.  */
+          parm_size = ((parm_size + PARM_BOUNDARY - 1)
+                       / PARM_BOUNDARY * PARM_BOUNDARY);
+          total += parm_size;
+          formal_type = TREE_CHAIN (formal_type); \
+        }
+    }
 
   /* Assume max of 8 base 10 digits in the suffix.  */
   newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
@@ -392,62 +324,43 @@ i386_pe_encode_section_info (tree decl, 
       tree newid = NULL_TREE;
 
       if (lookup_attribute ("stdcall", type_attributes))
-	newid = gen_stdcall_or_fastcall_suffix (decl, false);
+        newid = gen_stdcall_or_fastcall_suffix (decl, false);
       else if (lookup_attribute ("fastcall", type_attributes))
-	newid = gen_stdcall_or_fastcall_suffix (decl, true);
+        newid = gen_stdcall_or_fastcall_suffix (decl, true);
       if (newid != NULL_TREE) 	
-	{
-	  rtx rtlname = XEXP (rtl, 0);
-	  if (GET_CODE (rtlname) == MEM)
-	    rtlname = XEXP (rtlname, 0);
-	  XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
-	  /* These attributes must be present on first declaration,
-	     change_decl_assembler_name will warn if they are added
-	     later and the decl has been referenced, but duplicate_decls
-	     should catch the mismatch before this is called.  */ 
-	  change_decl_assembler_name (decl, newid);
-	}
+        {
+          rtx rtlname = XEXP (rtl, 0);
+          if (GET_CODE (rtlname) == MEM)
+            rtlname = XEXP (rtlname, 0);
+          XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
+          /* These attributes must be present on first declaration,
+             change_decl_assembler_name will warn if they are added
+             later and the decl has been referenced, but duplicate_decls
+             should catch the mismatch before this is called.  */ 
+          change_decl_assembler_name (decl, newid);
+        }
     }
 
   /* Mark the decl so we can tell from the rtl whether the object is
-     dllexport'd or dllimport'd.  This also handles dllexport/dllimport
-     override semantics.  */
+     dllexport'd or dllimport'd.  tree.c: merge_dllimport_decl_attributes
+     handles dllexport/dllimport override semantics.  */
 
   if (i386_pe_dllexport_p (decl))
     i386_pe_mark_dllexport (decl);
   else if (i386_pe_dllimport_p (decl))
     i386_pe_mark_dllimport (decl);
-  /* It might be that DECL has already been marked as dllimport, but a
-     subsequent definition nullified that.  The attribute is gone but
-     DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
-     that. Ditto for the DECL_NON_ADDR_CONST_P flag.  */
-  else if ((TREE_CODE (decl) == FUNCTION_DECL
-	    || TREE_CODE (decl) == VAR_DECL)
-	   && DECL_RTL (decl) != NULL_RTX
-	   && GET_CODE (DECL_RTL (decl)) == MEM
-	   && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
-	   && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
-	   && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
-    {
-      const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
-
-      /* Remove DLL_IMPORT_PREFIX.  */
-      tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
-      rtx symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-      SYMBOL_REF_DECL (symref) = decl;
-      XEXP (DECL_RTL (decl), 0) = symref;
-      DECL_NON_ADDR_CONST_P (decl) = 0;
-
-      /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
-	 We leave these alone for now.  */
-
-      if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
-	warning ("%J'%D' defined locally after being "
-		 "referenced with dllimport linkage", decl, decl);
-      else
-	warning ("%J'%D' redeclared without dllimport attribute "
-		 "after being referenced with dllimport linkage", decl, decl);
-    }
+  /* It might be that DECL has been declared as dllimport, but a
+     subsequent definition nullified that.  Assert that
+     tree.c: merge_dllimport_decl_attributes has removed the attribute
+     before the RTL name was marked with the DLL_IMPORT_PREFIX.  */
+  else
+    gcc_assert(!((TREE_CODE (decl) == FUNCTION_DECL
+                  || TREE_CODE (decl) == VAR_DECL)
+               && rtl != NULL_RTX
+               && GET_CODE (rtl) == MEM
+               && GET_CODE (XEXP (rtl, 0)) == MEM
+               && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF
+               && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0))));
 }
 
 /* Strip only the leading encoding, leaving the stdcall suffix and fastcall
@@ -595,8 +508,8 @@ i386_pe_section_type_flags (tree decl, c
       flags = SECTION_WRITE;
 
       if (decl && TREE_CODE (decl) == VAR_DECL
-	  && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
-	flags |= SECTION_PE_SHARED;
+          && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
+        flags |= SECTION_PE_SHARED;
     }
 
   if (decl && DECL_ONE_ONLY (decl))
@@ -612,7 +525,7 @@ i386_pe_section_type_flags (tree decl, c
   else
     {
       if (decl && **slot != flags)
-	error ("%J'%D' causes a section type conflict", decl, decl);
+        error ("%J'%D' causes a section type conflict", decl, decl);
     }
 
   return flags;
@@ -751,11 +664,11 @@ i386_pe_file_end (void)
 
       /* Positively ensure only one declaration for any given symbol.  */
       if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
-	{
-	  TREE_ASM_WRITTEN (decl) = 1;
-	  i386_pe_declare_function_type (asm_out_file, p->name,
-					 TREE_PUBLIC (decl));
-	}
+        {
+          TREE_ASM_WRITTEN (decl) = 1;
+          i386_pe_declare_function_type (asm_out_file, p->name,
+                                         TREE_PUBLIC (decl));
+        }
     }
 
   if (export_head)
@@ -763,11 +676,11 @@ i386_pe_file_end (void)
       struct export_list *q;
       drectve_section ();
       for (q = export_head; q != NULL; q = q->next)
-	{
-	  fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
-		   i386_pe_strip_name_encoding (q->name),
-		   (q->is_data) ? ",data" : "");
-	}
+        {
+          fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
+                   i386_pe_strip_name_encoding (q->name),
+                   (q->is_data) ? ",data" : "");
+        }
     }
 }
 
diff -r 9a4f61828020 gcc/target-def.h
--- a/gcc/target-def.h	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/target-def.h	Thu Feb 15 19:29:42 2007 +0300
@@ -416,6 +416,10 @@ Foundation, 59 Temple Place - Suite 330,
 
 #define TARGET_DWARF_HANDLE_FRAME_UNSPEC 0
 
+#ifndef TARGET_VALID_DLLIMPORT_ATTRIBUTE_P
+#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P hook_bool_tree_true
+#endif
+
 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_false
 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_false
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false
@@ -530,6 +534,11 @@ Foundation, 59 Temple Place - Suite 330,
 #endif
 
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */
+
+#ifndef TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
+#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION hook_void_tree
+#endif
+
 #define TARGET_CXX				\
   {						\
     TARGET_CXX_GUARD_TYPE,			\
@@ -543,6 +552,7 @@ Foundation, 59 Temple Place - Suite 330,
     TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY,	\
     TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT,        \
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */ \
+    TARGET_CXX_ADJUST_CLASS_AT_DEFINITION          \
   }
 
 /* The whole shebang.  */
@@ -604,6 +614,7 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_MD_ASM_CLOBBERS,			\
   TARGET_DWARF_CALLING_CONVENTION,              \
   TARGET_DWARF_HANDLE_FRAME_UNSPEC,		\
+  TARGET_VALID_DLLIMPORT_ATTRIBUTE_P,         \
   TARGET_CALLS,					\
   TARGET_CXX,					\
   TARGET_HAVE_NAMED_SECTIONS,			\
diff -r 9a4f61828020 gcc/target.h
--- a/gcc/target.h	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/target.h	Thu Feb 15 19:22:02 2007 +0300
@@ -524,6 +524,11 @@ struct gcc_target
        (set (reg) (unspec_volatile [...] UNSPECV_INDEX))
      to let the backend emit the call frame instructions.  */
   void (* dwarf_handle_frame_unspec) (const char *, rtx, int);
+
+  /* DECL is a variable or function with __attribute__((dllimport))
+     specified.  Use this hook if the target needs to add extra validation
+     checks to  handle_dll_attribute ().  */
+  bool (* valid_dllimport_attribute_p) (tree decl);
 
   /* Functions relating to calls - argument passing, returns, etc.  */
   struct calls {
@@ -628,6 +633,11 @@ struct gcc_target
        only one translation unit will not be COMDAT.  */
     bool (*class_data_always_comdat) (void);
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */
+    /* TYPE is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that
+       has just been defined.  Use this hook to make adjustments to the
+       class  (eg, tweak visibility or perform any other required
+       target modifications).  */  
+    void (*adjust_class_at_definition) (tree type);
   } cxx;
 
   /* Leave the boolean fields at the end.  */
diff -r 9a4f61828020 gcc/tree.c
--- a/gcc/tree.c	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/tree.c	Thu Feb 15 23:55:58 2007 +0300
@@ -1632,7 +1632,7 @@ staticp (tree arg)
     case VAR_DECL:
       return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
 	      && ! DECL_THREAD_LOCAL (arg)
-	      && ! DECL_NON_ADDR_CONST_P (arg)
+	      && ! DECL_DLLIMPORT_P (arg)
 	      ? arg : NULL);
 
     case CONST_DECL:
@@ -3044,34 +3044,34 @@ build_type_attribute_variant (tree ttype
 
       hashcode = iterative_hash_object (code, hashcode);
       if (TREE_TYPE (ntype))
-	hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)),
-					  hashcode);
+        hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)),
+                                          hashcode);
       hashcode = attribute_hash_list (attribute, hashcode);
 
       switch (TREE_CODE (ntype))
-	{
-	case FUNCTION_TYPE:
-	  hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode);
-	  break;
-	case ARRAY_TYPE:
-	  hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
-					    hashcode);
-	  break;
-	case INTEGER_TYPE:
-	  hashcode = iterative_hash_object
-	    (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode);
-	  hashcode = iterative_hash_object
-	    (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
-	  break;
-	case REAL_TYPE:
-	  {
-	    unsigned int precision = TYPE_PRECISION (ntype);
-	    hashcode = iterative_hash_object (precision, hashcode);
-	  }
-	  break;
-	default:
-	  break;
-	}
+        {
+         case FUNCTION_TYPE:
+          hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode);
+          break;
+         case ARRAY_TYPE:
+          hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
+                                            hashcode);
+          break;
+         case INTEGER_TYPE:
+          hashcode = iterative_hash_object
+            (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode);
+          hashcode = iterative_hash_object
+            (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
+          break;
+         case REAL_TYPE:
+           {
+             unsigned int precision = TYPE_PRECISION (ntype);
+             hashcode = iterative_hash_object (precision, hashcode);
+           }
+           break;
+         default:
+          break;
+        }
 
       ntype = type_hash_canon (hashcode, ntype);
       ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
@@ -3113,16 +3113,16 @@ is_attribute_with_length_p (const char *
       gcc_assert (attr[attr_len - 1] == '_');
       gcc_assert (attr[1] == '_');
       if (ident_len == attr_len - 4
-	  && strncmp (attr + 2, p, attr_len - 4) == 0)
-	return 1;
+          && strncmp (attr + 2, p, attr_len - 4) == 0)
+        return 1;
     }
   else
     {
       if (ident_len == attr_len + 4
-	  && p[0] == '_' && p[1] == '_'
-	  && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
-	  && strncmp (attr, p + 2, attr_len) == 0)
-	return 1;
+          && p[0] == '_' && p[1] == '_'
+          && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
+          && strncmp (attr, p + 2, attr_len) == 0)
+        return 1;
     }
 
   return 0;
@@ -3155,7 +3155,7 @@ lookup_attribute (const char *attr_name,
     {
       gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
       if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
-	return l;
+        return l;
     }
 
   return NULL_TREE;
@@ -3178,34 +3178,34 @@ merge_attributes (tree a1, tree a2)
   else if (a2 != 0 && ! attribute_list_contained (a1, a2))
     {
       if (attribute_list_contained (a2, a1))
-	attributes = a2;
+        attributes = a2;
       else
-	{
-	  /* Pick the longest list, and hang on the other list.  */
-
-	  if (list_length (a1) < list_length (a2))
-	    attributes = a2, a2 = a1;
-
-	  for (; a2 != 0; a2 = TREE_CHAIN (a2))
-	    {
-	      tree a;
-	      for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
-					 attributes);
-		   a != NULL_TREE;
-		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
-					 TREE_CHAIN (a)))
-		{
-		  if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
-		    break;
-		}
-	      if (a == NULL_TREE)
-		{
-		  a1 = copy_node (a2);
-		  TREE_CHAIN (a1) = attributes;
-		  attributes = a1;
-		}
-	    }
-	}
+        {
+          /* Pick the longest list, and hang on the other list.  */
+
+          if (list_length (a1) < list_length (a2))
+            attributes = a2, a2 = a1;
+
+          for (; a2 != 0; a2 = TREE_CHAIN (a2))
+           {
+             tree a;
+             for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
+                                        attributes);
+                  a != NULL_TREE;
+                  a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
+                                        TREE_CHAIN (a)))
+              {
+                if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
+                  break;
+              }
+             if (a == NULL_TREE)
+               {
+                 a1 = copy_node (a2);
+                 TREE_CHAIN (a1) = attributes;
+                 attributes = a1;
+               }
+           }
+        }
     }
   return attributes;
 }
@@ -3245,39 +3245,74 @@ merge_dllimport_decl_attributes (tree ol
 merge_dllimport_decl_attributes (tree old, tree new)
 {
   tree a;
-  int delete_dllimport_p;
-
-  old = DECL_ATTRIBUTES (old);
-  new = DECL_ATTRIBUTES (new);
+  int delete_dllimport_p = 1;
 
   /* What we need to do here is remove from `old' dllimport if it doesn't
      appear in `new'.  dllimport behaves like extern: if a declaration is
      marked dllimport and a definition appears later, then the object
-     is not dllimport'd.  */
-  if (lookup_attribute ("dllimport", old) != NULL_TREE
-      && lookup_attribute ("dllimport", new) == NULL_TREE)
-    delete_dllimport_p = 1;
+     is not dllimport'd.  We also remove a `new' dllimport if the old list
+     contains dllexport:  dllexport always overrides dllimport, regardless
+     of the order of declaration.  */     
+  if (!VAR_OR_FUNCTION_DECL_P (new))
+    delete_dllimport_p = 0;
+  else if (DECL_DLLIMPORT_P (new)
+           && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
+    { 
+      DECL_DLLIMPORT_P (new) = 0;
+      warning ("%qD already declared with dllexport attribute: "
+	      "dllimport ignored", new);
+    }
+  else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new))
+    {
+      /* Warn about overriding a symbol that has already been used. eg:
+           extern int __attribute__ ((dllimport)) foo;
+           int* bar () {return &foo;}
+           int foo;
+      */
+      if (TREE_USED (old))
+        {
+          warning ("%qD redeclared without dllimport attribute "
+                   "after being referenced with dll linkage", new);
+          /* If we have used a variable's address with dllimport linkage,
+             keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
+             decl may already have had TREE_INVARIANT and TREE_CONSTANT
+             computed.
+             We still remove the attribute so that assembler code refers
+             to '&foo rather than '_imp__foo'.  */
+          if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
+            DECL_DLLIMPORT_P (new) = 1;
+        }
+
+      /* Let an inline definition silently override the external reference,
+         but otherwise warn about attribute inconsistency.  */ 
+      else if (TREE_CODE (new) == VAR_DECL
+               || !DECL_DECLARED_INLINE_P (new))
+        warning ("%qD redeclared without dllimport attribute: "
+                 "previous dllimport ignored", new);
+    }
   else
     delete_dllimport_p = 0;
 
-  a = merge_attributes (old, new);
+  a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new));
 
   if (delete_dllimport_p)
     {
       tree prev, t;
+      const size_t attr_len = strlen ("dllimport");      
 
       /* Scan the list for dllimport and delete it.  */
       for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
-	{
-	  if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
-	    {
-	      if (prev == NULL_TREE)
-		a = TREE_CHAIN (a);
-	      else
-		TREE_CHAIN (prev) = TREE_CHAIN (t);
-	      break;
-	    }
-	}
+       {
+         if (is_attribute_with_length_p ("dllimport", attr_len,
+                                         TREE_PURPOSE (t)))           
+           {
+             if (prev == NULL_TREE)
+               a = TREE_CHAIN (a);
+             else
+               TREE_CHAIN (prev) = TREE_CHAIN (t);
+             break;
+           }
+       }
     }
 
   return a;
@@ -3298,15 +3333,15 @@ handle_dll_attribute (tree * pnode, tree
     {
       if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
 		   | (int) ATTR_FLAG_ARRAY_NEXT))
-	{
-	  *no_add_attrs = true;
-	  return tree_cons (name, args, NULL_TREE);
-	}
+        {
+          *no_add_attrs = true;
+          return tree_cons (name, args, NULL_TREE);
+        }
       if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
-	{
-	  warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
-	  *no_add_attrs = true;
-	}
+        {
+          warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+          *no_add_attrs = true;
+        }
 
       return NULL_TREE;
     }
@@ -3315,34 +3350,45 @@ handle_dll_attribute (tree * pnode, tree
      any damage.  */
   if (is_attribute_p ("dllimport", name))
     {
+      /* Honor any target-specific overides. */ 
+      if (!targetm.valid_dllimport_attribute_p (node))
+        *no_add_attrs = true;
+
+      else if (TREE_CODE (node) == FUNCTION_DECL
+               && DECL_DECLARED_INLINE_P (node))
+        {
+          warning ("inline function %qD declared as "
+                   " dllimport: attribute ignored", node); 
+          *no_add_attrs = true;
+        }
       /* Like MS, treat definition of dllimported variables and
-	 non-inlined functions on declaration as syntax errors.  We
-	 allow the attribute for function definitions if declared
-	 inline.  */
-      if (TREE_CODE (node) == FUNCTION_DECL  && DECL_INITIAL (node)
-          && !DECL_DECLARED_INLINE_P (node))
-	{
-	  error ("%Jfunction %qD definition is marked dllimport.", node, node);
-	  *no_add_attrs = true;
-	}
+         non-inlined functions on declaration as syntax errors. */
+      else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
+        {
+          error ("%Jfunction %qD definition is marked dllimport.", node, node);
+          *no_add_attrs = true;
+        }
 
       else if (TREE_CODE (node) == VAR_DECL)
-	{
-	  if (DECL_INITIAL (node))
-	    {
-	      error ("%Jvariable %qD definition is marked dllimport.",
-		     node, node);
-	      *no_add_attrs = true;
-	    }
-
-	  /* `extern' needn't be specified with dllimport.
-	     Specify `extern' now and hope for the best.  Sigh.  */
-	  DECL_EXTERNAL (node) = 1;
-	  /* Also, implicitly give dllimport'd variables declared within
-	     a function global scope, unless declared static.  */
-	  if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
-	    TREE_PUBLIC (node) = 1;
-	}
+        {
+          if (DECL_INITIAL (node))
+            {
+              error ("%Jvariable %qD definition is marked dllimport.",
+                     node, node);
+              *no_add_attrs = true;
+            }
+
+          /* `extern' needn't be specified with dllimport.
+             Specify `extern' now and hope for the best.  Sigh.  */
+          DECL_EXTERNAL (node) = 1;
+          /* Also, implicitly give dllimport'd variables declared within
+             a function global scope, unless declared static.  */
+          if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
+            TREE_PUBLIC (node) = 1;
+        }
+
+      if (*no_add_attrs == false)
+        DECL_DLLIMPORT_P (node) = 1;
     }
 
   /*  Report error if symbol is not accessible at global scope.  */
@@ -3351,7 +3397,7 @@ handle_dll_attribute (tree * pnode, tree
 	  || TREE_CODE (node) == FUNCTION_DECL))
     {
       error ("%Jexternal linkage required for symbol %qD because of "
-	     "%qs attribute.", node, node, IDENTIFIER_POINTER (name));
+             "%qs attribute.", node, node, IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
 
diff -r 9a4f61828020 gcc/tree.h
--- a/gcc/tree.h	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/tree.h	Thu Feb 15 20:01:54 2007 +0300
@@ -2375,9 +2375,8 @@ namespace llvm { class Value; }
 #define DECL_LANG_FLAG_6(NODE) (DECL_CHECK (NODE)->decl.lang_flag_6)
 #define DECL_LANG_FLAG_7(NODE) (DECL_CHECK (NODE)->decl.lang_flag_7)
 
-/* Used to indicate that the pointer to this DECL cannot be treated as
-   an address constant.  */
-#define DECL_NON_ADDR_CONST_P(NODE) (DECL_CHECK (NODE)->decl.non_addr_const_p)
+/* Used to indicate that the DECL is a dllimport.  */
+#define DECL_DLLIMPORT_P(NODE) (DECL_CHECK (NODE)->decl.dllimport_flag)
 
 /* Used in a FIELD_DECL to indicate that we cannot form the address of
    this component.  */
@@ -2470,7 +2469,7 @@ struct tree_decl GTY(())
   unsigned artificial_flag : 1;
   unsigned weak_flag : 1;
 
-  unsigned non_addr_const_p : 1;
+  unsigned dllimport_flag : 1; 
   unsigned no_instrument_function_entry_exit : 1;
   unsigned comdat_flag : 1;
   unsigned malloc_flag : 1;
diff -r 9a4f61828020 gcc/varasm.c
--- a/gcc/varasm.c	Tue Feb 13 11:41:51 2007 +0000
+++ b/gcc/varasm.c	Thu Feb 15 23:48:37 2007 +0300
@@ -477,7 +477,7 @@ named_section (tree decl, const char *na
     {
       flags = get_named_section_flags (name);
       if ((flags & SECTION_OVERRIDE) == 0)
-	error ("%J%D causes a section type conflict", decl, decl);
+        error ("%J%D causes a section type conflict", decl, decl);
     }
 
   named_section_real (name, flags, decl);
@@ -943,14 +943,14 @@ make_decl_rtl (tree decl)
       reg_number = decode_reg_name (name);
       /* First detect errors in declaring global registers.  */
       if (reg_number == -1)
-	error ("%Jregister name not specified for %qD", decl, decl);
+        error ("%Jregister name not specified for %qD", decl, decl);
       else if (reg_number < 0)
-	error ("%Jinvalid register name for %qD", decl, decl);
+        error ("%Jinvalid register name for %qD", decl, decl);
       else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
-	error ("%Jdata type of %qD isn%'t suitable for a register",
+        error ("%Jdata type of %qD isn%'t suitable for a register",
 	       decl, decl);
       else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
-	error ("%Jregister specified for %qD isn%'t suitable for data type",
+        error ("%Jregister specified for %qD isn%'t suitable for data type",
                decl, decl);
       /* Now handle properly declared static register variables.  */
       else
@@ -3705,7 +3705,7 @@ initializer_constant_valid_p (tree value
       if (value
 	  && TREE_CODE (value) == FUNCTION_DECL
 	  && ((decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value))
-	      || DECL_NON_ADDR_CONST_P (value)))
+	      || DECL_DLLIMPORT_P (value)))
 	return NULL_TREE;
       return value;
 
/* Target support for C++ classes on Windows.
   Contributed by Danny Smith ([EMAIL PROTECTED])
   Copyright (C) 2005
   Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "output.h"
#include "tree.h"
#include "cp/cp-tree.h" /* this is why we're a separate module */
#include "flags.h"
#include "tm_p.h"
#include "toplev.h"
#include "hashtab.h"

bool
i386_pe_type_dllimport_p (tree decl)
{
   gcc_assert (TREE_CODE (decl) == VAR_DECL 
               || TREE_CODE (decl) == FUNCTION_DECL);

   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
     return false;

   /* We ignore the dllimport attribute for inline member functions.
      This differs from MSVC behavior which treats it like GNUC
      'extern inline' extension.  Also ignore for template
      instantiations with linkonce semantics and artificial methods.  */
    if (TREE_CODE (decl) ==  FUNCTION_DECL
        && (DECL_DECLARED_INLINE_P (decl)
	    || DECL_TEMPLATE_INSTANTIATION (decl)
	    || DECL_ARTIFICIAL (decl)))
      return false;

   /* Since we can't treat a pointer to a dllimport'd symbol as a
       constant address, we turn off the attribute on C++ virtual
       methods to allow creation of vtables using thunks.  */
    else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
	     && DECL_VIRTUAL_P (decl))
      {
	/* Even though we ignore the attribute from the start, warn if we later see
	   an out-of class definition, as we do for other member functions in
	   tree.c:merge_dllimport_decl_attributes.  If this is the key method, the
	   definition may affect the import-export status of vtables, depending
           on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c.   */
	if (DECL_INITIAL (decl))
	  {
	    warning ("%q+D redeclared without dllimport attribute: "
		    "previous dllimport ignored", decl);
#ifdef PE_DLL_DEBUG
	    if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl)))            
	      warning ("key method %q+D of dllimport'd class defined"
		       decl);
#endif
	  }
	return false;
      }

      /* Don't mark defined functions as dllimport.  This code will only be
         reached if we see a non-inline function defined out-of-class.  */
    else if (TREE_CODE (decl) ==  FUNCTION_DECL
	     && (DECL_INITIAL (decl)))
      return false;

    /*  Don't allow definitions of static data members in dllimport class,
        If vtable data is marked as DECL_EXTERNAL, import it; otherwise just
        ignore the class attribute.  */
    else if (TREE_CODE (decl) == VAR_DECL
	     && TREE_STATIC (decl) && TREE_PUBLIC (decl)
	     && !DECL_EXTERNAL (decl))
      {
	if (!DECL_VIRTUAL_P (decl))
	     error ("definition of static data member %q+D of "
		    "dllimport'd class", decl);
	return false;
      }

    return true;
}


bool
i386_pe_type_dllexport_p (tree decl)
{
   gcc_assert (TREE_CODE (decl) == VAR_DECL 
               || TREE_CODE (decl) == FUNCTION_DECL);
   /* Avoid exporting compiler-generated default dtors and copy ctors.
      The only artificial methods that need to be exported are virtual
      and non-virtual thunks.  */
   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
       && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
     return false;
   return true;
}

static inline void maybe_add_dllimport (tree decl) 
{
  if (i386_pe_type_dllimport_p (decl))
    DECL_DLLIMPORT_P (decl) = 1;   
}

void
i386_pe_adjust_class_at_definition (tree t)
{
  tree member;

  gcc_assert (CLASS_TYPE_P (t));

 /* We only look at dllimport.  The only thing that dllexport does is
    add stuff to a '.drectiv' section at end-of-file, so no need to do
    anything for dllexport'd classes until we generate RTL. */  
  if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE)
    return;

  /* We don't actually add the attribute to the decl, just set the flag
     that signals that the address of this symbol is not a compile-time
     constant.   Any subsequent out-of-class declaration of members wil
     cause the DECL_DLLIMPORT_P flag to be unset.
     (See  tree.c: merge_dllimport_decl_attributes).
     That is just right since out-of class declarations can only be a
     definition.  We recheck the class members  at RTL generation to
     emit warnings if this has happened.  Definition of static data member
     of dllimport'd class always causes an error (as per MS compiler).
     */

  /* Check static VAR_DECL's.  */
  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
    if (TREE_CODE (member) == VAR_DECL)     
      maybe_add_dllimport (member);
    
  /* Check FUNCTION_DECL's.  */
  for (member = TYPE_METHODS (t); member;  member = TREE_CHAIN (member))
    if (TREE_CODE (member) == FUNCTION_DECL)
      maybe_add_dllimport (member);
 
  /* Check vtables  */
  for (member = CLASSTYPE_VTABLES (t); member;  member = TREE_CHAIN (member))
    if (TREE_CODE (member) == VAR_DECL) 
      maybe_add_dllimport (member);

/* We leave typeinfo tables alone.  We can't mark TI objects as
     dllimport, since the address of a secondary VTT may be needed
     for static initialization of a primary VTT.  VTT's  of
     dllimport'd classes should always be link-once COMDAT.  */ 
}
/* Dummy subroutines for language-specific support on Windows.
   Contributed by Danny Smith ([EMAIL PROTECTED])
   Copyright (C) 2005
   Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "output.h"
#include "tree.h"
#include "flags.h"
#include "tm_p.h"
#include "toplev.h"
#include "hashtab.h"

bool
i386_pe_type_dllimport_p (tree decl ATTRIBUTE_UNUSED)
{
  return false;
}


bool
i386_pe_type_dllexport_p (tree decl ATTRIBUTE_UNUSED)
{
  return false;
}


void
i386_pe_adjust_class_at_definition (tree t ATTRIBUTE_UNUSED)
{ }
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to