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 21275, PR21597 cygwin/mingw32 bootstrap regressions on trunk


Hi, the attached patch fixes dllimport related bootstrap regressions
PR 21275 and PR 21597 on minw32 and cygwin.  It also fixes PR 19704
for C++ class members that get dllimport status from class type attribute.

The problem that this patch addresses is that currently the flag that
indicates a non-constant address for dllimports is not set until make_decl_rtl
calls i386_pe_encode_section_info. This is too late.

Setting non_addr_const_p flag earlier, when we first handle the
dllimport attribute, fixes most of the problems for C code, but still
fails to allow dllimport to be overriden by a later declaration sans
attribute or an earlier declaration with dllexport attribute. It also fails to
handle dllimport of C++ class members that acquire dllimport status via
a class type attribute rather than by a decl attribute.

This patch:

Renames the non_addr_const_p bitfield of the tree.h struct decl_with_vis
to dllimport_flag. This is not really necessary but historically this
bitfield has only been used for dllimport and renaming the field and
associated macro made it clearer to me what I was trying to do.

Sets the DECL_DLLIMPORT as early as possible: when we handle the
dllimport decl attribute or when we finish the definition of a C++ class
that has the dllimport type attribute. The latter is done via a new cxx
target hook targetm.cxx.check_class_attributes.

Unsets the DECL_DLLIMPORT attribute when merge_dllimport_decl_attributes
loses the attrubute.

Adds another target hook, valid_dllimport_attribute_p to allow targets
to add to the rules in tree.c:handle_dllimport_attribute.  In the case of
windows targets, this is needed to handle the -mnop-fun-dllimport compile
option.  

In varasm.c, uses the DECL_DLLIMPORT flag to test whether  ADDR_EXPR's
of both function and var decls are constant. I have removed
the test for DECL_NON_ADDR_CONST_P/DECL_DLLIMPORT in tree.c:staticp
(case VAR_DECL), since I have not been able to construct a testcase
where this is necessary.  Maybe I misunderstand what staticp means, but
dllimported vars do have static storage -- it's just that we don't know
their addresses until the library is loaded and the fixups to the import
address table are made.   If we do need to keep a test for
DECL_DLLIMPORT in staticp, then we also need to treat dllimports like
thread local variables in tree.c:recompute_tree_invarant_for_addr_expr. 

The definition of targetm.cxx.check_class_attributes for mingw and
cygwin requires access to cp/cp-tree.h definitions. So I have put it a
separate module as a cxx_target_obj. Having done this, putting the
other C++-specific code currently in winnt.c into the new module
simplified reading of the code and allowed improvement of the tests for
which members should be excluded (eg template instantiations) from
dllimport status.

Finally, setting the DECL_DLLIMPORT flag early allows it to be used in
ix86_function_ok_for_sibcall.

There are are still some warnings for dllimport/dllexport ambiguity that
were emitted in gcc3.4.x and earlier that are no longer emitted. The
warnings were significant in 3.x when the ambiguity was not detected
until late in the game amd we sometimes ended up with an unresolved
__imp__foo as well as a U _foo. Now some of these warning seem
overzealous, since the override semantics now just work as documented.
It seems that sh/symbian.c doesn't want them at all, so putting them
into merge_dllimport_decl_attributes may not be the right thing. 

I realize this patch is rather large, but it affects code used only when
TARGET_DLLIMPORT_DECL_ATTRIBUTES. I have an alternative patch in the
wings, if this one is too awkward for stage 3. 

I would also like to add testcases based on PR 21275, 21597, 19704 and
will include them in the next iteration of this patch. (I will also add
documentation to tm.texi for TARGET_VALID_DLLIMPORT_ATTRIBUTE_P. I just
noticed that I missed this.) 

Tested on i686-pc-mingw32,
../gcc/configure  --with-gcc --with-as=/mingw/mingw32/bin/as.exe
--with-ld=/mingw/mingw32/bin/ld.exe --with-nm=/mingw/mingw32/bin/nm.exe --host=mingw32
--build=mingw32 --target=mingw32  --prefix=/mingw --enable-threads --disable-nls
--enable-languages=c,c++,objc,ada,f95 --disable-win32-registry --disable-shared
--enable-sjlj-exceptions
with no new regressions.

The bootstrap requires that the recent TARGET_ENCODE_SECTION_INFO
changes for i386 either be reverted or modified by the patch at:
http://gcc.gnu.org/ml/gcc-patches/2005-08/msg00009.html
  

ChangeLog

	PR middle-end/21275, middle-end/21597
	* target.h (struct gcc_target): Add valid_dllimport_attribute_p
	target hook.
	(struct cxx): Add check_class_attributes target hook.
	* target-def.h: (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): New define,
	defaulting to hook_bool_tree_true. Add to TARGET_INITIALIZER
	(TARGET_CXX_CHECK_CLASS_ATTRIBUTES): New define, defaulting to 
	hook_void_tree. Add to TARGET_CXX.
	* tree.h (struct decl_with_vis): Rename non_addr_const_p field to
	dllimport_flag.
	(DECL_NON_ADDR_CONSTANT_P): Replace with DECL_DLLIMPORT macro.
	* tree.c (merge_dllimport_decl_attributes): Check and update
	DECL_DLLIMPORT. Check for dllexport override.  Tweak lookup of 
	dllimport atribute.
	(handle_dll_attribute): Check targetm.valid_dllimport_attribute_p
	for target specific rules.  Don't add dllimport attribute if
	DECL_DECLARED_ONLINE_P.  Set DECL_DLLIMPORT when adding dllimport
	attribute. 
	(staticp): Don't check DECL_NON_ADDR_CONSTANT_P in VAR_DECL case.
	* varasm.c (initializer_constant_valid_p): Check DECL_DLLIMPORT
	of both variable and function decls in FDESC,  ADDR_EXPR cases. 
	* config.gcc (i[34567]86-*-cygwin*): Add winnt-cxx.o to 
	'cxx_target_objs', winnt-stubs,o to 'extra_objs'.
	(i[34567]86-*-mingw32*): Likewise.

	* doc/tm.texi (TARGET_CXX_CHECK_CLASS_ATTRIBUTES): Document.
			
	* config/i386/winnt.c (i386_pe_dllimport_p): Factor out C++ specific code.
	Change return value to bool. 
	(i386_pe_dllimport_p): Likewise.
	(associated_type): Simplify and make language-independent
	(i386_pe_encode_section_info): Replace override of ambiguous dllimport symbol
	refs with a gcc_assert.
	(i386_pe_valid_dllimport_attribute_p): Define.
	* config/i386/winnt-cxx.c: New file. Define i386_pe_class dllimport_p,
	i386_pe_class_dllexport_p, i386_pe_check_class_attributes.
	* config/i386/winnt-stubs.c: New file. Define stub versions of lang-specific
	functions.
	config/i386/i386-protos.h: Declare winnt-[cxx|stubs].c functions
	i386_pe_class dllimport_p, i386_pe_class_dllexport_p, 
	i386_pe_check_class_attributes.
	(i386_pe_valid_dllimport_attribute_p): Declare. 
	* config/i386/cygming.h (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Define.
	(TARGET_CXX_CHECK_CLASS_ATTRIBUTES) Define.
	* config/i386/t-cygming: Add rules for winnt-cxx.o, winnt-stubs.o.

	PR target/19704
	config/i386/i386.c (ix86_function_ok_for_sibcall): Replace test for
	dllimport attribute with test of DECL_DLLIMPORT flag.	


cp/ChangeLog 

	PR middle-end/21275, middle-end/21597
	class.c (finish_struct_1): Call targetm.cxx.check_class_attributes.



Index: config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.559
diff -c -3 -p -r1.559 config.gcc
*** config.gcc	26 Jul 2005 21:22:44 -0000	1.559
--- config.gcc	2 Aug 2005 04:58:28 -0000
*************** i[34567]86-*-pe | i[34567]86-*-cygwin*)
*** 1179,1187 ****
  	tmake_file="i386/t-cygwin i386/t-cygming"
  	target_gtfiles="\$(srcdir)/config/i386/winnt.c"
  	extra_options="${extra_options} i386/cygming.opt"
! 	extra_objs=winnt.o
  	c_target_objs=cygwin2.o
! 	cxx_target_objs=cygwin2.o
  	extra_gcc_objs=cygwin1.o
  	if test x$enable_threads = xyes; then
  		thread_file='posix'
--- 1179,1187 ----
  	tmake_file="i386/t-cygwin i386/t-cygming"
  	target_gtfiles="\$(srcdir)/config/i386/winnt.c"
  	extra_options="${extra_options} i386/cygming.opt"
! 	extra_objs="winnt.o winnt-stubs.o"
  	c_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'
*************** i[34567]86-*-mingw32*)
*** 1193,1199 ****
  	tmake_file="i386/t-cygming i386/t-mingw32"
  	target_gtfiles="\$(srcdir)/config/i386/winnt.c"
  	extra_options="${extra_options} i386/cygming.opt"
! 	extra_objs=winnt.o
  	case ${enable_threads} in
  	  "" | yes | win32) thread_file='win32' ;;
  	esac
--- 1193,1200 ----
  	tmake_file="i386/t-cygming i386/t-mingw32"
  	target_gtfiles="\$(srcdir)/config/i386/winnt.c"
  	extra_options="${extra_options} i386/cygming.opt"
! 	extra_objs="winnt.o winnt-stubs.o"
! 	cxx_target_objs=winnt-cxx.o
  	case ${enable_threads} in
  	  "" | yes | win32) thread_file='win32' ;;
  	esac
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.498
diff -c -3 -p -r1.498 tree.c
*** tree.c	28 Jul 2005 16:30:00 -0000	1.498
--- tree.c	2 Aug 2005 04:58:44 -0000
*************** staticp (tree arg)
*** 1786,1792 ****
      case VAR_DECL:
        return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
  	      && ! DECL_THREAD_LOCAL_P (arg)
- 	      && ! DECL_NON_ADDR_CONST_P (arg)
  	      ? arg : NULL);
  
      case CONST_DECL:
--- 1786,1791 ----
*************** tree
*** 3451,3482 ****
  merge_dllimport_decl_attributes (tree old, tree new)
  {
    tree a;
!   int delete_dllimport_p;
! 
!   old = DECL_ATTRIBUTES (old);
!   new = DECL_ATTRIBUTES (new);
  
    /* 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;
!   else
!     delete_dllimport_p = 0;
  
!   a = merge_attributes (old, new);
  
!   if (delete_dllimport_p)
      {
        tree prev, t;
  
        /* 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
--- 3450,3486 ----
  merge_dllimport_decl_attributes (tree old, tree new)
  {
    tree a;
!   int delete_dllimport_p = 0;
  
    /* 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.  We also remove a `new' dllimport if the old list
!      contains dllexport:  dllexport always overrides dllimport, regardless
!      of the order of declaration.  */
! 
!   if ((DECL_DLLIMPORT (old) && !DECL_DLLIMPORT (new))
!       || (lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))
! 	    != NULL_TREE))
!      delete_dllimport_p = 1;
  
!   a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new));
  
!   if (delete_dllimport_p) 
      {
        tree prev, t;
+       const size_t attr_len = strlen ("dllimport");
  
+       DECL_DLLIMPORT (old) =  DECL_DLLIMPORT (new) = 0;
+      
        /* Scan the list for dllimport and delete it.  */
        for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
  	{
! 	  if (is_attribute_with_length_p ("dllimport", attr_len,
! 					  TREE_PURPOSE (t)))
  	    {
+ 	      /* FIXME, should we warn about inconsistency in
+ 		 dll linkage here, or just silently override?  */	
  	      if (prev == NULL_TREE)
  		a = TREE_CHAIN (a);
  	      else
*************** merge_dllimport_decl_attributes (tree ol
*** 3485,3491 ****
  	    }
  	}
      }
- 
    return a;
  }
  
--- 3489,3494 ----
*************** handle_dll_attribute (tree * pnode, tree
*** 3522,3533 ****
       any damage.  */
    if (is_attribute_p ("dllimport", name))
      {
        /* 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 ("function %q+D definition is marked dllimport", node);
  	  *no_add_attrs = true;
--- 3525,3544 ----
       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 (OPT_Wattributes, "inline function %q+D 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. */
!       else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
  	{
  	  error ("function %q+D definition is marked dllimport", node);
  	  *no_add_attrs = true;
*************** handle_dll_attribute (tree * pnode, tree
*** 3550,3555 ****
--- 3561,3569 ----
  	  if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
  	    TREE_PUBLIC (node) = 1;
  	}
+ 
+       if (*no_add_attrs == false)
+         DECL_DLLIMPORT (node) = 1;
      }
  
    /*  Report error if symbol is not accessible at global scope.  */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.750
diff -c -3 -p -r1.750 tree.h
*** tree.h	26 Jul 2005 02:56:44 -0000	1.750
--- tree.h	2 Aug 2005 04:58:56 -0000
*************** struct tree_parm_decl GTY(())
*** 2421,2430 ****
  #define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
    DECL_WITH_VIS_CHECK (DECL)->decl_with_vis.gimple_formal_temp
  
! /* Used to indicate that the pointer to this DECL cannot be treated as
!    an address constant.  */
! #define DECL_NON_ADDR_CONST_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.non_addr_const_p)
! 
  
  /* Used in a DECL to indicate that, even if it TREE_PUBLIC, it need
     not be put out unless it is needed in this translation unit.
--- 2421,2428 ----
  #define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
    DECL_WITH_VIS_CHECK (DECL)->decl_with_vis.gimple_formal_temp
  
! /* Used to indicate that the DECL is a dllimport.  */
! #define DECL_DLLIMPORT(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
  
  /* Used in a DECL to indicate that, even if it TREE_PUBLIC, it need
     not be put out unless it is needed in this translation unit.
*************** struct tree_decl_with_vis GTY(())
*** 2500,2506 ****
   unsigned common_flag:1; 
   unsigned in_text_section : 1;
   unsigned gimple_formal_temp : 1;
!  unsigned non_addr_const_p : 1; 
   /* Used by C++.  Might become a generic decl flag.  */
   unsigned shadowed_for_var_p : 1;
   
--- 2498,2504 ----
   unsigned common_flag:1; 
   unsigned in_text_section : 1;
   unsigned gimple_formal_temp : 1;
!  unsigned dllimport_flag : 1; 
   /* Used by C++.  Might become a generic decl flag.  */
   unsigned shadowed_for_var_p : 1;
   
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.524
diff -c -3 -p -r1.524 varasm.c
*** varasm.c	31 Jul 2005 09:12:25 -0000	1.524
--- varasm.c	2 Aug 2005 04:59:10 -0000
*************** initializer_constant_valid_p (tree value
*** 3635,3642 ****
        /* Taking the address of a nested function involves a trampoline.  */
        if (value
  	  && TREE_CODE (value) == FUNCTION_DECL
! 	  && ((decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value))
! 	      || DECL_NON_ADDR_CONST_P (value)))
  	return NULL_TREE;
        return value;
  
--- 3635,3645 ----
        /* Taking the address of a nested function involves a trampoline.  */
        if (value
  	  && TREE_CODE (value) == FUNCTION_DECL
! 	  && decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value))
! 	return NULL_TREE;
!       if (value
! 	  && VAR_OR_FUNCTION_DECL_P (value)
! 	  && DECL_DLLIMPORT (value))
  	return NULL_TREE;
        return value;
  
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.144
diff -c -3 -p -r1.144 target.h
*** target.h	14 Jul 2005 07:39:55 -0000	1.144
--- target.h	2 Aug 2005 04:59:12 -0000
*************** struct gcc_target
*** 550,555 ****
--- 550,557 ----
    /* Returns NULL if target supports the insn within a doloop block,
       otherwise it returns an error message.  */
    const char * (*invalid_within_doloop) (rtx);
+ 
+   bool (* valid_dllimport_attribute_p) (tree);
      
    /* Functions relating to calls - argument passing, returns, etc.  */
    struct calls {
*************** struct gcc_target
*** 660,665 ****
--- 662,670 ----
      /* Returns true if __aeabi_atexit should be used to register static
         destructors.  */
      bool (*use_aeabi_atexit) (void);
+     /* Use this hook If the target needs check type attributes of a class
+        and apply to member decls.  */  
+     void (*check_class_attributes) (tree);
    } cxx;
  
    /* True if unwinding tables should be generated by default.  */
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.132
diff -c -3 -p -r1.132 target-def.h
*** target-def.h	14 Jul 2005 07:39:54 -0000	1.132
--- target-def.h	2 Aug 2005 04:59:14 -0000
*************** Foundation, 51 Franklin Street, Fifth Fl
*** 145,150 ****
--- 145,154 ----
  #define TARGET_INVALID_WITHIN_DOLOOP default_invalid_within_doloop
  #endif
  
+ #ifndef TARGET_VALID_DLLIMPORT_ATTRIBUTE_P
+ #define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P hook_bool_tree_true
+ #endif
+ 
  #ifndef TARGET_HAVE_TLS
  #define TARGET_HAVE_TLS false
  #endif
*************** Foundation, 51 Franklin Street, Fifth Fl
*** 514,519 ****
--- 518,527 ----
  #define TARGET_CXX_USE_AEABI_ATEXIT hook_bool_void_false
  #endif
  
+ #ifndef TARGET_CXX_CHECK_CLASS_ATTRIBUTES
+ #define TARGET_CXX_CHECK_CLASS_ATTRIBUTES hook_void_tree
+ #endif
+ 
  #define TARGET_CXX				\
    {						\
      TARGET_CXX_GUARD_TYPE,			\
*************** Foundation, 51 Franklin Street, Fifth Fl
*** 526,531 ****
--- 534,540 ----
      TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY,	\
      TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT,        \
      TARGET_CXX_USE_AEABI_ATEXIT,		\
+     TARGET_CXX_CHECK_CLASS_ATTRIBUTES		\
    }
  
  /* The whole shebang.  */
*************** Foundation, 51 Franklin Street, Fifth Fl
*** 591,596 ****
--- 600,606 ----
    TARGET_STACK_PROTECT_GUARD,			\
    TARGET_STACK_PROTECT_FAIL,			\
    TARGET_INVALID_WITHIN_DOLOOP,			\
+   TARGET_VALID_DLLIMPORT_ATTRIBUTE_P,		\
    TARGET_CALLS,					\
    TARGET_INVALID_CONVERSION,			\
    TARGET_INVALID_UNARY_OP,			\
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.443
diff -c -3 -p -r1.443 tm.texi
*** doc/tm.texi	21 Jul 2005 00:55:20 -0000	1.443
--- doc/tm.texi	2 Aug 2005 04:59:52 -0000
*************** should be used to register static destru
*** 8660,8665 ****
--- 8660,8670 ----
  is in effect.  The default is to return false to use @code{__cxa_atexit}.
  @end deftypefn
  
+ @deftypefn {Target Hook} bool TARGET_CXX_CHECK_CLASS_ATTRIBUTES (tree @var{type})
+ Define this hook if the attributes of class @var{type} need to be checked
+ and possibly propagated to class members when the class is defined.
+ @end deftypefn
+ 
  @node Misc
  @section Miscellaneous Parameters
  @cindex parameters, miscellaneous
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.146
diff -c -3 -p -r1.146 i386-protos.h
*** config/i386/i386-protos.h	31 Jul 2005 09:12:28 -0000	1.146
--- config/i386/i386-protos.h	2 Aug 2005 04:59:52 -0000
*************** extern void i386_pe_encode_section_info 
*** 244,249 ****
--- 244,256 ----
  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 bool i386_pe_valid_dllimport_attribute_p (tree);
+ 
+ /* In winnt-cxx.c and winnt-stubs.c  */
+ extern void i386_pe_check_class_attributes (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];
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.846
diff -c -3 -p -r1.846 i386.c
*** config/i386/i386.c	31 Jul 2005 09:12:28 -0000	1.846
--- config/i386/i386.c	2 Aug 2005 05:00:31 -0000
*************** ix86_function_ok_for_sibcall (tree decl,
*** 1951,1957 ****
  
  #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
    /* Dllimport'd functions are also called indirectly.  */
!   if (decl && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
        && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
      return false;
  #endif
--- 1955,1961 ----
  
  #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
    /* Dllimport'd functions are also called indirectly.  */
!   if (decl && DECL_DLLIMPORT (decl)
        && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
      return false;
  #endif
Index: config/i386/winnt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/winnt.c,v
retrieving revision 1.84
diff -c -3 -p -r1.84 winnt.c
*** config/i386/winnt.c	2 Jul 2005 10:55:26 -0000	1.84
--- config/i386/winnt.c	2 Aug 2005 05:00:33 -0000
*************** Software Foundation, 51 Franklin Street,
*** 46,55 ****
     multiple times.
  */
  
- static tree associated_type (tree);
  static tree gen_stdcall_or_fastcall_suffix (tree, bool);
! static int i386_pe_dllexport_p (tree);
! static int i386_pe_dllimport_p (tree);
  static void i386_pe_mark_dllexport (tree);
  static void i386_pe_mark_dllimport (tree);
  
--- 46,54 ----
     multiple times.
  */
  
  static tree gen_stdcall_or_fastcall_suffix (tree, bool);
! static bool i386_pe_dllexport_p (tree);
! static bool i386_pe_dllimport_p (tree);
  static void i386_pe_mark_dllexport (tree);
  static void i386_pe_mark_dllimport (tree);
  
*************** ix86_handle_selectany_attribute (tree *n
*** 115,245 ****
  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.  */
  
! static 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)
!     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;
!     }
  
!   return 0;
! }
  
! /* Return nonzero if DECL is a dllimport'd object.  */
  
! static 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 (0, "function %q+D is defined after prior declaration "
! 		     "as dllimport: attribute ignored", 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 (0, "inline function %q+D is declared as dllimport: "
! 		     "attribute ignored", 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 ("definition of static data member %q+D of "
! 		   "dllimport'd class", 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;
!     }
! 
!   return 0;
  }
  
  /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
--- 114,177 ----
  static tree
  associated_type (tree decl)
  {
!   return  (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
!             ?  DECL_CONTEXT (decl) : NULL_TREE;
  }
  
  
! /* Return true if DECL is a dllexport'd object.  */
! 
! static bool
  i386_pe_dllexport_p (tree decl)
  {
    if (TREE_CODE (decl) != VAR_DECL
!        && TREE_CODE (decl) != FUNCTION_DECL)
!     return false;
  
!   if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
!     return true;
  
!   /* 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 false;
! }
  
! static bool
  i386_pe_dllimport_p (tree decl)
  {
    if (TREE_CODE (decl) != VAR_DECL
!        && TREE_CODE (decl) != FUNCTION_DECL)
!     return false;
  
!   /* Lookup the attribute rather than rely on the DECL_DLLIMPORT flag.
!      We may need to override an earlier decision so that merge
!      attributes can reset the flag.  */
!   if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
!     return true;
! 
!   /* The DECL_DLLIMPORT flag was set for decls in the class definition
!      by  targetm.cxx_propagate_class_attributes.  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 false;
! }
! 
! /* Handle the -mnop-fun-dllimport target switch.  */
! bool
! i386_pe_valid_dllimport_attribute_p (tree decl)
! {
!    if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
!      return false;
!    return true;
  }
  
  /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
*************** i386_pe_mark_dllexport (tree decl)
*** 283,289 ****
  	       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  */
--- 215,220 ----
*************** i386_pe_mark_dllimport (tree decl)
*** 328,334 ****
      {
        /* Already done, but do a sanity check to prevent assembler
  	 errors.  */
!       gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl));
      }
  
    newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
--- 259,267 ----
      {
        /* Already done, but do a sanity check to prevent assembler
  	 errors.  */
!       gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
! 		  && DECL_DLLIMPORT (decl));
!       return;
      }
  
    newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
*************** i386_pe_mark_dllimport (tree decl)
*** 345,352 ****
    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;
  }
  
  /* Return string which is the former assembler name modified with a
--- 278,284 ----
    newrtl = gen_rtx_MEM (Pmode,symref);
    XEXP (DECL_RTL (decl), 0) = newrtl;
  
!   DECL_DLLIMPORT (decl) = 1;
  }
  
  /* Return string which is the former assembler name modified with a
*************** i386_pe_encode_section_info (tree decl, 
*** 431,449 ****
      }
  
    /* 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.  */
  
    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
--- 363,389 ----
      }
  
    /* Mark the decl so we can tell from the rtl whether the object is
!      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.  Assert that
!      tree.c: merge_dllimport_decl_attributes is doing its job.  */
! #if 1
!   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))));
+ #else
+   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
*************** i386_pe_encode_section_info (tree decl, 
*** 457,475 ****
        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 (0, "%q+D defined locally after being "
  		 "referenced with dllimport linkage", decl);
        else
  	warning (OPT_Wattributes, "%q+D redeclared without dllimport "
  		 "attribute after being referenced with dllimport linkage",
  		 decl);
!     }
  }
  
  /* Strip only the leading encoding, leaving the stdcall suffix and fastcall
--- 397,417 ----
        rtx symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
        SYMBOL_REF_DECL (symref) = decl;
        XEXP (DECL_RTL (decl), 0) = symref;
!       DECL_DLLIMPORT (decl) = 0;
  
        /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
  	 We leave these alone for now.  */
  
        if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
! 	warning (OPT_Wattributes, "%q+D defined locally after being "
  		 "referenced with dllimport linkage", decl);
        else
  	warning (OPT_Wattributes, "%q+D redeclared without dllimport "
  		 "attribute after being referenced with dllimport linkage",
  		 decl);
! 
!   }
! #endif
  }
  
  /* Strip only the leading encoding, leaving the stdcall suffix and fastcall
Index: config/i386/cygming.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/cygming.h,v
retrieving revision 1.31
diff -c -3 -p -r1.31 cygming.h
*** config/i386/cygming.h	25 Jun 2005 01:21:07 -0000	1.31
--- config/i386/cygming.h	2 Aug 2005 05:00:34 -0000
*************** extern int i386_pe_dllimport_name_p (con
*** 407,412 ****
--- 410,418 ----
  #undef NO_PROFILE_COUNTERS
  #define NO_PROFILE_COUNTERS 1
  
+ #define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P i386_pe_valid_dllimport_attribute_p
+ #define TARGET_CXX_CHECK_CLASS_ATTRIBUTES i386_pe_check_class_attributes
+ 
  #undef TREE
  
  #ifndef BUFSIZ
Index: config/i386/t-cygming
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/t-cygming,v
retrieving revision 1.3
diff -c -3 -p -r1.3 t-cygming
*** config/i386/t-cygming	23 Sep 2003 18:55:59 -0000	1.3
--- config/i386/t-cygming	2 Aug 2005 05:00:34 -0000
*************** winnt.o: $(srcdir)/config/i386/winnt.c $
*** 16,19 ****
--- 16,32 ----
  	$(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
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.729
diff -c -3 -p -r1.729 class.c
*** cp/class.c	21 Jul 2005 19:43:47 -0000	1.729
--- cp/class.c	2 Aug 2005 05:00:54 -0000
*************** finish_struct_1 (tree t)
*** 5023,5028 ****
--- 5023,5030 ----
  
    complete_vars (t);
  
+   targetm.cxx.check_class_attributes (t);
+ 
    if (warn_overloaded_virtual)
      warn_hidden (t);
  
*** /dev/null	Tue Aug  2 17:01:17 2005
--- config/i386/winnt-stubs.c	Mon Aug  1 10:28:50 2005
***************
*** 0 ****
--- 1,53 ----
+ /* Dummy subroutines for language-specific support on Windows.
+    Contributed by Danny Smith (dannysmith@users.sourceforge.net)
+    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_check_class_attributes (tree t ATTRIBUTE_UNUSED)
+ { }
*** /dev/null	Tue Aug  2 17:01:17 2005
--- config/i386/winnt-cxx.c	Tue Aug  2 14:16:29 2005
***************
*** 0 ****
--- 1,167 ----
+ /* Target support for C++ classes on Windows.
+    Contributed by Danny Smith (dannysmith@users.sourceforge.net)
+    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)))
+       {
+ 	if (extra_warnings && DECL_DECLARED_INLINE_P (decl)
+ 	    /* Only warn at definition?  */
+ 	    && !current_class_type)
+ 	  warning (OPT_Wattributes, "inline function %q+D implicitly "
+ 		  "declared as dllimport: attribute ignored", decl); 
+ 	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)))
+       {
+ 	/* Avoid multiple warnings on clones.  */
+ 	if (!DECL_CLONED_FUNCTION_P (decl)
+ 	    || DECL_NAME (decl) == complete_ctor_identifier
+ 	    || DECL_NAME (decl) == complete_dtor_identifier)
+ 	  warning (OPT_Wattributes, "non-inline function %q+D is defined after prior declaration "
+ 		     "as dllimport: attribute ignored", decl);
+ 
+          /* FIXME: Should we emit a special warning if we are defining
+             the key method of a dllimport'd polymorphic class?  */
+ 
+ 	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;
+       }
+ 
+     /* 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))
+       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 (decl) = 1;   
+ }
+ 
+ void
+ i386_pe_check_class_attributes (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 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))
+     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.  */
+ }

Send instant messages to your online friends http://au.messenger.yahoo.com 


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