OSDN Git Service

Backported from mainline
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / winnt-cxx.c
1 /* Target support for C++ classes on Windows.
2    Contributed by Danny Smith (dannysmith@users.sourceforge.net)
3    Copyright (C) 2005, 2007, 2009, 2010  Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "cp/cp-tree.h" /* This is why we're a separate module.  */
27 #include "flags.h"
28 #include "tm_p.h"
29 #include "diagnostic-core.h"
30 #include "hashtab.h"
31
32 bool
33 i386_pe_type_dllimport_p (tree decl)
34 {
35   gcc_assert (TREE_CODE (decl) == VAR_DECL 
36               || TREE_CODE (decl) == FUNCTION_DECL);
37
38   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
39     return false;
40
41   /* We ignore the dllimport attribute for inline member functions.
42      This differs from MSVC behavior which treats it like GNUC
43      'extern inline' extension.  Also ignore for template
44      instantiations with linkonce semantics and artificial methods.  */
45   if (TREE_CODE (decl) ==  FUNCTION_DECL
46       && (DECL_DECLARED_INLINE_P (decl)
47           || DECL_TEMPLATE_INSTANTIATION (decl)
48           || DECL_ARTIFICIAL (decl)))
49     return false;
50   
51   /* Overrides of the class dllimport decls by out-of-class definitions are 
52      handled by tree.c:merge_dllimport_decl_attributes.   */
53   return true;
54 }
55
56 bool
57 i386_pe_type_dllexport_p (tree decl)
58 {
59   gcc_assert (TREE_CODE (decl) == VAR_DECL 
60               || TREE_CODE (decl) == FUNCTION_DECL);
61
62   /* Avoid exporting compiler-generated default dtors and copy ctors.
63      The only artificial methods that need to be exported are virtual
64      and non-virtual thunks.  */
65   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
66       && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
67     return false;
68   return true;
69 }
70
71 static inline void maybe_add_dllimport (tree decl) 
72 {
73   if (i386_pe_type_dllimport_p (decl))
74     DECL_DLLIMPORT_P (decl) = 1;
75 }
76
77 static inline void maybe_add_dllexport (tree decl) 
78 {
79   if (i386_pe_type_dllexport_p (decl))
80     {   
81       tree decl_attrs = DECL_ATTRIBUTES (decl);
82       if (lookup_attribute ("dllexport", decl_attrs) != NULL_TREE)
83         /* Already done.  */
84         return;
85       DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("dllexport"),
86                                           NULL_TREE, decl_attrs);
87     }
88 }
89
90 void
91 i386_pe_adjust_class_at_definition (tree t)
92 {
93   tree member;
94
95   gcc_assert (CLASS_TYPE_P (t));
96  
97  
98   if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (t)) != NULL_TREE)
99     {
100       tree tmv = TYPE_MAIN_VARIANT (t);
101
102       /* Make sure that we set dllexport attribute to typeinfo's
103          base declaration, as otherwise it would fail to be exported as
104          it isn't a class-member.  */
105       if (tmv != NULL_TREE
106           && CLASSTYPE_TYPEINFO_VAR (tmv) != NULL_TREE)
107         {
108           tree na, ti_decl = CLASSTYPE_TYPEINFO_VAR (tmv);
109           na = tree_cons (get_identifier ("dllexport"), NULL_TREE,
110                           NULL_TREE);
111           decl_attributes (&ti_decl, na, 0);
112         }
113
114       /* Check static VAR_DECL's.  */
115       for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
116         if (TREE_CODE (member) == VAR_DECL)     
117           maybe_add_dllexport (member);
118     
119       /* Check FUNCTION_DECL's.  */
120       for (member = TYPE_METHODS (t); member;  member = DECL_CHAIN (member))
121         if (TREE_CODE (member) == FUNCTION_DECL)
122           {
123             tree thunk;
124             maybe_add_dllexport (member);
125           
126             /* Also add the attribute to its thunks.  */
127             for (thunk = DECL_THUNKS (member); thunk;
128                  thunk = TREE_CHAIN (thunk))
129               maybe_add_dllexport (thunk);
130         }
131       /* Check vtables  */
132       for (member = CLASSTYPE_VTABLES (t); member;  member = DECL_CHAIN (member))
133         if (TREE_CODE (member) == VAR_DECL) 
134           maybe_add_dllexport (member);
135     }
136
137   else if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) != NULL_TREE)
138     {
139       /* We don't actually add the attribute to the decl, just set the flag
140          that signals that the address of this symbol is not a compile-time
141          constant.   Any subsequent out-of-class declaration of members wil
142          cause the DECL_DLLIMPORT_P flag to be unset.
143          (See  tree.c: merge_dllimport_decl_attributes).
144          That is just right since out-of class declarations can only be a
145          definition.   */
146
147       /* Check static VAR_DECL's.  */
148       for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
149         if (TREE_CODE (member) == VAR_DECL)     
150           maybe_add_dllimport (member);
151     
152       /* Check FUNCTION_DECL's.  */
153       for (member = TYPE_METHODS (t); member;  member = DECL_CHAIN (member))
154         if (TREE_CODE (member) == FUNCTION_DECL)
155           {
156             tree thunk;
157             maybe_add_dllimport (member);
158           
159             /* Also add the attribute to its thunks.  */
160             for (thunk = DECL_THUNKS (member); thunk;
161                  thunk = DECL_CHAIN (thunk))
162               maybe_add_dllimport (thunk);
163          }
164  
165       /* Check vtables  */
166       for (member = CLASSTYPE_VTABLES (t); member;  member = DECL_CHAIN (member))
167         if (TREE_CODE (member) == VAR_DECL) 
168           maybe_add_dllimport (member);
169
170       /* We leave typeinfo tables alone.  We can't mark TI objects as
171         dllimport, since the address of a secondary VTT may be needed
172         for static initialization of a primary VTT.  VTT's  of
173         dllimport'd classes should always be link-once COMDAT.  */ 
174     }
175 }