Merged with mainline at revision 128810.
[official-gcc.git] / gcc / config / sh / symbian.c
blobabe685b57669cf6366b7110bfc1ffb063e4a6be2
1 /* Routines for GCC for a Symbian OS targeted SH backend.
2 Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
3 Contributed by RedHat.
4 Most of this code is stolen from i386/winnt.c.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 3, or (at your
11 option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "output.h"
28 #include "flags.h"
29 #include "tree.h"
30 #include "expr.h"
31 #include "tm_p.h"
32 #include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
33 #include "toplev.h"
35 /* Select the level of debugging information to display.
36 0 for no debugging.
37 1 for informative messages about decisions to add attributes
38 2 for verbose information about what is being done. */
39 #define SYMBIAN_DEBUG 0
40 /* #define SYMBIAN_DEBUG 1 */
41 /* #define SYMBIAN_DEBUG 2 */
43 /* A unique character to encode declspec encoded objects. */
44 #define SH_SYMBIAN_FLAG_CHAR "$"
46 /* Unique strings to prefix exported and imported objects. */
47 #define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
48 #define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
51 /* Return the type that we should use to determine if DECL is
52 imported or exported. */
54 static tree
55 sh_symbian_associated_type (tree decl)
57 tree t = NULL_TREE;
59 if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
60 /* Methods now inherit their dllimport/dllexport attributes correctly
61 so there is no need to check their class. In fact it is wrong to
62 check their class since a method can remain unexported from an
63 exported class. */
64 return t;
66 /* Otherwise we can just take the DECL_CONTEXT as normal. */
67 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
68 t = DECL_CONTEXT (decl);
70 return t;
73 /* Return nonzero if DECL is a dllexport'd object. */
75 bool
76 sh_symbian_dllexport_p (tree decl)
78 tree exp;
80 if ( TREE_CODE (decl) != VAR_DECL
81 && TREE_CODE (decl) != FUNCTION_DECL)
82 return false;
84 exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
86 /* Class members get the dllexport status of their class. */
87 if (exp == NULL)
89 tree class = sh_symbian_associated_type (decl);
91 if (class)
92 exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
94 #if SYMBIAN_DEBUG
95 if (exp)
97 print_node_brief (stderr, "dllexport:", decl, 0);
98 fprintf (stderr, "\n");
100 else
101 #if SYMBIAN_DEBUG < 2
102 if (TREE_CODE (decl) != FUNCTION_DECL)
103 #endif
105 print_node_brief (stderr, "no dllexport:", decl, 0);
106 fprintf (stderr, "\n");
108 #endif
109 return exp ? true : false;
112 /* Return nonzero if DECL is a dllimport'd object. */
114 static bool
115 sh_symbian_dllimport_p (tree decl)
117 tree imp;
119 if ( TREE_CODE (decl) != VAR_DECL
120 && TREE_CODE (decl) != FUNCTION_DECL)
121 return false;
123 imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
124 if (imp)
125 return true;
127 /* Class members get the dllimport status of their class. */
128 imp = sh_symbian_associated_type (decl);
129 if (! imp)
130 return false;
132 imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
133 if (!imp)
134 return false;
136 /* Don't mark defined functions as dllimport. If the definition itself
137 was marked with dllimport, then sh_symbian_handle_dll_attribute reports
138 an error. This handles the case when the definition overrides an
139 earlier declaration. */
140 if (TREE_CODE (decl) == FUNCTION_DECL
141 && DECL_INITIAL (decl)
142 && !DECL_INLINE (decl))
144 /* Don't warn about artificial methods. */
145 if (!DECL_ARTIFICIAL (decl))
146 warning (OPT_Wattributes, "function %q+D is defined after prior "
147 "declaration as dllimport: attribute ignored",
148 decl);
149 return false;
152 /* We ignore the dllimport attribute for inline member functions.
153 This differs from MSVC behavior which treats it like GNUC
154 'extern inline' extension. */
155 else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
157 if (extra_warnings)
158 warning (OPT_Wattributes, "inline function %q+D is declared as "
159 "dllimport: attribute ignored",
160 decl);
161 return false;
164 /* Don't allow definitions of static data members in dllimport
165 class. Just ignore the attribute for vtable data. */
166 else if (TREE_CODE (decl) == VAR_DECL
167 && TREE_STATIC (decl)
168 && TREE_PUBLIC (decl)
169 && !DECL_EXTERNAL (decl))
171 if (!DECL_VIRTUAL_P (decl))
172 error ("definition of static data member %q+D of dllimport'd class",
173 decl);
174 return false;
177 /* Since we can't treat a pointer to a dllimport'd symbol as a
178 constant address, we turn off the attribute on C++ virtual
179 methods to allow creation of vtables using thunks. Don't mark
180 artificial methods either (in sh_symbian_associated_type, only
181 COMDAT artificial method get import status from class context). */
182 else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
183 && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
184 return false;
186 return true;
189 /* Return nonzero if SYMBOL is marked as being dllexport'd. */
191 bool
192 sh_symbian_dllexport_name_p (const char *symbol)
194 return strncmp (DLL_EXPORT_PREFIX, symbol,
195 strlen (DLL_EXPORT_PREFIX)) == 0;
198 /* Return nonzero if SYMBOL is marked as being dllimport'd. */
201 bool
202 sh_symbian_dllimport_name_p (const char *symbol)
204 return strncmp (DLL_IMPORT_PREFIX, symbol,
205 strlen (DLL_IMPORT_PREFIX)) == 0;
208 /* Mark a DECL as being dllexport'd.
209 Note that we override the previous setting (e.g.: dllimport). */
211 static void
212 sh_symbian_mark_dllexport (tree decl)
214 const char *oldname;
215 char *newname;
216 rtx rtlname;
217 tree idp;
219 rtlname = XEXP (DECL_RTL (decl), 0);
220 if (GET_CODE (rtlname) == MEM)
221 rtlname = XEXP (rtlname, 0);
222 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
223 oldname = XSTR (rtlname, 0);
225 if (sh_symbian_dllimport_name_p (oldname))
227 /* Remove DLL_IMPORT_PREFIX.
228 Note - we do not issue a warning here. In Symbian's environment it
229 is legitimate for a prototype to be marked as dllimport and the
230 corresponding definition to be marked as dllexport. The prototypes
231 are in headers used everywhere and the definition is in a translation
232 unit which has included the header in order to ensure argument
233 correctness. */
234 oldname += strlen (DLL_IMPORT_PREFIX);
235 DECL_DLLIMPORT_P (decl) = 0;
237 else if (sh_symbian_dllexport_name_p (oldname))
238 return; /* Already done. */
240 newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
241 sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
243 /* We pass newname through get_identifier to ensure it has a unique
244 address. RTL processing can sometimes peek inside the symbol ref
245 and compare the string's addresses to see if two symbols are
246 identical. */
247 idp = get_identifier (newname);
249 XEXP (DECL_RTL (decl), 0) =
250 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
253 /* Mark a DECL as being dllimport'd. */
255 static void
256 sh_symbian_mark_dllimport (tree decl)
258 const char *oldname;
259 char *newname;
260 tree idp;
261 rtx rtlname;
262 rtx newrtl;
264 rtlname = XEXP (DECL_RTL (decl), 0);
265 if (GET_CODE (rtlname) == MEM)
266 rtlname = XEXP (rtlname, 0);
267 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
268 oldname = XSTR (rtlname, 0);
270 if (sh_symbian_dllexport_name_p (oldname))
272 error ("%qs declared as both exported to and imported from a DLL",
273 IDENTIFIER_POINTER (DECL_NAME (decl)));
275 else if (sh_symbian_dllimport_name_p (oldname))
277 /* Already done, but do a sanity check to prevent assembler errors. */
278 if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
279 error ("failure in redeclaration of %q+D: dllimport'd symbol lacks external linkage",
280 decl);
282 else
284 newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
285 sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
287 /* We pass newname through get_identifier to ensure it has a unique
288 address. RTL processing can sometimes peek inside the symbol ref
289 and compare the string's addresses to see if two symbols are
290 identical. */
291 idp = get_identifier (newname);
292 newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
293 XEXP (DECL_RTL (decl), 0) = newrtl;
297 void
298 sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
300 default_encode_section_info (decl, rtl, first);
302 /* Mark the decl so we can tell from the rtl whether
303 the object is dllexport'd or dllimport'd. */
304 if (sh_symbian_dllexport_p (decl))
305 sh_symbian_mark_dllexport (decl);
306 else if (sh_symbian_dllimport_p (decl))
307 sh_symbian_mark_dllimport (decl);
308 /* It might be that DECL has already been marked as dllimport, but a
309 subsequent definition nullified that. The attribute is gone but
310 DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
311 that. Ditto for the DECL_DLLIMPORT_P flag. */
312 else if ( (TREE_CODE (decl) == FUNCTION_DECL
313 || TREE_CODE (decl) == VAR_DECL)
314 && DECL_RTL (decl) != NULL_RTX
315 && GET_CODE (DECL_RTL (decl)) == MEM
316 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
317 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
318 && sh_symbian_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
320 const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
321 /* Remove DLL_IMPORT_PREFIX. */
322 tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
323 rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
325 warning (0, "%s %q+D %s after being referenced with dllimport linkage",
326 TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
327 decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
328 ? "defined locally" : "redeclared without dllimport attribute");
330 XEXP (DECL_RTL (decl), 0) = newrtl;
332 DECL_DLLIMPORT_P (decl) = 0;
337 /* Return the length of a function name prefix
338 that starts with the character 'c'. */
340 static int
341 sh_symbian_get_strip_length (int c)
343 /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */
344 return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
347 /* Return a pointer to a function's name with any
348 and all prefix encodings stripped from it. */
350 const char *
351 sh_symbian_strip_name_encoding (const char *name)
353 int skip;
355 while ((skip = sh_symbian_get_strip_length (*name)))
356 name += skip;
358 return name;
361 /* Add the named attribute to the given node. Copes with both DECLs and
362 TYPEs. Will only add the attribute if it is not already present. */
364 static void
365 symbian_add_attribute (tree node, const char *attr_name)
367 tree attrs;
368 tree attr;
370 attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
372 if (lookup_attribute (attr_name, attrs) != NULL_TREE)
373 return;
375 attr = get_identifier (attr_name);
377 if (DECL_P (node))
378 DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
379 else
380 TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
382 #if SYMBIAN_DEBUG
383 fprintf (stderr, "propagate %s attribute", attr_name);
384 print_node_brief (stderr, " to", node, 0);
385 fprintf (stderr, "\n");
386 #endif
389 /* Handle a "dllimport" or "dllexport" attribute;
390 arguments as in struct attribute_spec.handler. */
392 tree
393 sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
394 int flags, bool *no_add_attrs)
396 tree thunk;
397 tree node = *pnode;
398 const char *attr = IDENTIFIER_POINTER (name);
400 /* These attributes may apply to structure and union types being
401 created, but otherwise should pass to the declaration involved. */
402 if (!DECL_P (node))
404 if (flags & ((int) ATTR_FLAG_DECL_NEXT
405 | (int) ATTR_FLAG_FUNCTION_NEXT
406 | (int) ATTR_FLAG_ARRAY_NEXT))
408 warning (OPT_Wattributes, "%qs attribute ignored", attr);
409 *no_add_attrs = true;
410 return tree_cons (name, args, NULL_TREE);
413 if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
415 warning (OPT_Wattributes, "%qs attribute ignored", attr);
416 *no_add_attrs = true;
419 return NULL_TREE;
422 /* Report error on dllimport ambiguities
423 seen now before they cause any damage. */
424 else if (is_attribute_p ("dllimport", name))
426 if (TREE_CODE (node) == VAR_DECL)
428 if (DECL_INITIAL (node))
430 error ("variable %q+D definition is marked dllimport",
431 node);
432 *no_add_attrs = true;
435 /* `extern' needn't be specified with dllimport.
436 Specify `extern' now and hope for the best. Sigh. */
437 DECL_EXTERNAL (node) = 1;
438 /* Also, implicitly give dllimport'd variables declared within
439 a function global scope, unless declared static. */
440 if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
441 TREE_PUBLIC (node) = 1;
445 /* If the node is an overloaded constructor or destructor, then we must
446 make sure that the attribute is propagated along the overload chain,
447 as it is these overloaded functions which will be emitted, rather than
448 the user declared constructor itself. */
449 if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
450 && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
452 tree overload;
454 for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
456 tree node_args;
457 tree func_args;
458 tree function = OVL_CURRENT (overload);
460 if (! function
461 || ! DECL_P (function)
462 || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
463 || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function)))
464 continue;
466 /* The arguments must match as well. */
467 for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
468 node_args && func_args;
469 node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
470 if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
471 break;
473 if (node_args || func_args)
475 /* We can ignore an extraneous __in_chrg arguments in the node.
476 GCC generated destructors, for example, will have this. */
477 if ((node_args == NULL_TREE
478 || func_args != NULL_TREE)
479 && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
480 continue;
483 symbian_add_attribute (function, attr);
485 /* Propagate the attribute to any function thunks as well. */
486 for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
487 if (TREE_CODE (thunk) == FUNCTION_DECL)
488 symbian_add_attribute (thunk, attr);
492 if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
494 /* Propagate the attribute to any thunks of this function. */
495 for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
496 if (TREE_CODE (thunk) == FUNCTION_DECL)
497 symbian_add_attribute (thunk, attr);
500 /* Report error if symbol is not accessible at global scope. */
501 if (!TREE_PUBLIC (node)
502 && ( TREE_CODE (node) == VAR_DECL
503 || TREE_CODE (node) == FUNCTION_DECL))
505 error ("external linkage required for symbol %q+D because of %qs attribute",
506 node, IDENTIFIER_POINTER (name));
507 *no_add_attrs = true;
510 #if SYMBIAN_DEBUG
511 print_node_brief (stderr, "mark node", node, 0);
512 fprintf (stderr, " as %s\n", attr);
513 #endif
515 return NULL_TREE;
518 /* This code implements a specification for exporting the vtable and rtti of
519 classes that have members with the dllexport or dllexport attributes.
520 This specification is defined here:
522 http://www.armdevzone.com/EABI/exported_class.txt
524 Basically it says that a class's vtable and rtti should be exported if
525 the following rules apply:
527 - If it has any non-inline non-pure virtual functions,
528 at least one of these need to be declared dllimport
529 OR any of the constructors is declared dllimport.
533 - The class has an inline constructor/destructor and
534 a key-function (placement of vtable uniquely defined) that
535 is defined in this translation unit.
537 The specification also says that for classes which will have their
538 vtables and rtti exported that their base class(es) might also need a
539 similar exporting if:
541 - Every base class needs to have its vtable & rtti exported
542 as well, if the following the conditions hold true:
543 + The base class has a non-inline declared non-pure virtual function
544 + The base class is polymorphic (has or inherits any virtual functions)
545 or the base class has any virtual base classes. */
547 /* Decide if a base class of a class should
548 also have its vtable and rtti exported. */
550 static void
551 symbian_possibly_export_base_class (tree base_class)
553 VEC(tree,gc) *method_vec;
554 int len;
556 if (! (TYPE_CONTAINS_VPTR_P (base_class)))
557 return;
559 method_vec = CLASSTYPE_METHOD_VEC (base_class);
560 len = method_vec ? VEC_length (tree, method_vec) : 0;
562 for (;len --;)
564 tree member = VEC_index (tree, method_vec, len);
566 if (! member)
567 continue;
569 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
571 if (TREE_CODE (member) != FUNCTION_DECL)
572 continue;
574 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
575 continue;
577 if (! DECL_VIRTUAL_P (member))
578 continue;
580 if (DECL_PURE_VIRTUAL_P (member))
581 continue;
583 if (DECL_INLINE (member))
584 continue;
586 break;
589 if (member)
590 break;
593 if (len < 0)
594 return;
596 /* FIXME: According to the spec this base class should be exported, but
597 a) how do we do this ? and
598 b) it does not appear to be necessary for compliance with the Symbian
599 OS which so far is the only consumer of this code. */
600 #if SYMBIAN_DEBUG
601 print_node_brief (stderr, "", base_class, 0);
602 fprintf (stderr, " EXPORTed [base class of exported class]\n");
603 #endif
606 /* Decide if a class needs its vtable and rtti exporting. */
608 static bool
609 symbian_export_vtable_and_rtti_p (tree ctype)
611 bool inline_ctor_dtor;
612 bool dllimport_ctor_dtor;
613 bool dllimport_member;
614 tree binfo, base_binfo;
615 VEC(tree,gc) *method_vec;
616 tree key;
617 int i;
618 int len;
620 /* Make sure that we are examining a class... */
621 if (TREE_CODE (ctype) != RECORD_TYPE)
623 #if SYMBIAN_DEBUG
624 print_node_brief (stderr, "", ctype, 0);
625 fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
626 #endif
627 return false;
630 /* If the class does not have a key function it
631 does not need to have its vtable exported. */
632 if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
634 #if SYMBIAN_DEBUG
635 print_node_brief (stderr, "", ctype, 0);
636 fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
637 #endif
638 return false;
641 /* If the key fn has not been defined
642 then the class should not be exported. */
643 if (! TREE_ASM_WRITTEN (key))
645 #if SYMBIAN_DEBUG
646 print_node_brief (stderr, "", ctype, 0);
647 fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
648 #endif
649 return false;
652 /* Check the class's member functions. */
653 inline_ctor_dtor = false;
654 dllimport_ctor_dtor = false;
655 dllimport_member = false;
657 method_vec = CLASSTYPE_METHOD_VEC (ctype);
658 len = method_vec ? VEC_length (tree, method_vec) : 0;
660 for (;len --;)
662 tree member = VEC_index (tree, method_vec, len);
664 if (! member)
665 continue;
667 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
669 if (TREE_CODE (member) != FUNCTION_DECL)
670 continue;
672 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
674 if (DECL_INLINE (member)
675 /* Ignore C++ backend created inline ctors/dtors. */
676 && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
677 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
678 inline_ctor_dtor = true;
680 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
681 dllimport_ctor_dtor = true;
683 else
685 if (DECL_PURE_VIRTUAL_P (member))
686 continue;
688 if (! DECL_VIRTUAL_P (member))
689 continue;
691 if (DECL_INLINE (member))
692 continue;
694 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
695 dllimport_member = true;
700 if (! dllimport_member && ! dllimport_ctor_dtor)
702 #if SYMBIAN_DEBUG
703 print_node_brief (stderr, "", ctype, 0);
704 fprintf (stderr,
705 " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
706 #endif
707 return false;
710 if (! inline_ctor_dtor)
712 #if SYMBIAN_DEBUG
713 print_node_brief (stderr, "", ctype, 0);
714 fprintf (stderr,
715 " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
716 #endif
717 return false;
720 #if SYMBIAN_DEBUG
721 print_node_brief (stderr, "", ctype, 0);
722 fprintf (stderr, " DOES need to be EXPORTed\n");
723 #endif
725 /* Now we must check and possibly export the base classes. */
726 for (i = 0, binfo = TYPE_BINFO (ctype);
727 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
728 symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
730 return true;
733 /* Add the named attribute to a class and its vtable and rtti. */
735 static void
736 symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
738 symbian_add_attribute (ctype, attr_name);
740 /* If the vtable exists then they need annotating as well. */
741 if (CLASSTYPE_VTABLES (ctype))
742 /* XXX - Do we need to annotate any vtables other than the primary ? */
743 symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
745 /* If the rtti exists then it needs annotating as well. */
746 if (TYPE_MAIN_VARIANT (ctype)
747 && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
748 symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
749 attr_name);
752 /* Decide if a class needs to have an attribute because
753 one of its member functions has the attribute. */
755 static bool
756 symbian_class_needs_attribute_p (tree ctype, const char *attribute_name)
758 VEC(tree,gc) *method_vec;
760 method_vec = CLASSTYPE_METHOD_VEC (ctype);
762 /* If the key function has the attribute then the class needs it too. */
763 if (TYPE_POLYMORPHIC_P (ctype)
764 && method_vec
765 && lookup_attribute (attribute_name,
766 DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
767 return true;
769 /* Check the class's member functions. */
770 if (TREE_CODE (ctype) == RECORD_TYPE)
772 unsigned int len;
774 len = method_vec ? VEC_length (tree, method_vec) : 0;
776 for (;len --;)
778 tree member = VEC_index (tree, method_vec, len);
780 if (! member)
781 continue;
783 for (member = OVL_CURRENT (member);
784 member;
785 member = OVL_NEXT (member))
787 if (TREE_CODE (member) != FUNCTION_DECL)
788 continue;
790 if (DECL_PURE_VIRTUAL_P (member))
791 continue;
793 if (! DECL_VIRTUAL_P (member))
794 continue;
796 if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
798 #if SYMBIAN_DEBUG
799 print_node_brief (stderr, "", ctype, 0);
800 fprintf (stderr, " inherits %s because", attribute_name);
801 print_node_brief (stderr, "", member, 0);
802 fprintf (stderr, " has it.\n");
803 #endif
804 return true;
810 #if SYMBIAN_DEBUG
811 print_node_brief (stderr, "", ctype, 0);
812 fprintf (stderr, " does not inherit %s\n", attribute_name);
813 #endif
814 return false;
818 symbian_import_export_class (tree ctype, int import_export)
820 const char *attr_name = NULL;
822 /* If we are exporting the class but it does not have the dllexport
823 attribute then we may need to add it. Similarly imported classes
824 may need the dllimport attribute. */
825 switch (import_export)
827 case 1: attr_name = "dllexport"; break;
828 case -1: attr_name = "dllimport"; break;
829 default: break;
832 if (attr_name
833 && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
835 if (symbian_class_needs_attribute_p (ctype, attr_name))
836 symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
838 /* Classes can be forced to export their
839 vtable and rtti under certain conditions. */
840 if (symbian_export_vtable_and_rtti_p (ctype))
842 symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
844 /* Make sure that the class and its vtable are exported. */
845 import_export = 1;
847 if (CLASSTYPE_VTABLES (ctype))
848 DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
850 /* Check to make sure that if the class has a key method that
851 it is now on the list of keyed classes. That way its vtable
852 will be emitted. */
853 if (CLASSTYPE_KEY_METHOD (ctype))
855 tree class;
857 for (class = keyed_classes; class; class = TREE_CHAIN (class))
858 if (class == ctype)
859 break;
861 if (class == NULL_TREE)
863 #if SYMBIAN_DEBUG
864 print_node_brief (stderr, "Add node", ctype, 0);
865 fprintf (stderr, " to the keyed classes list\n");
866 #endif
867 keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
871 /* Make sure that the typeinfo will be emitted as well. */
872 if (CLASS_TYPE_P (ctype))
873 TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
877 return import_export;
880 /* Dummy definition of this array for cc1 building purposes. */
881 tree cp_global_trees[CPTI_MAX] __attribute__((weak));
883 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
885 /* Dummy version of this G++ function for building cc1. */
886 void lang_check_failed (const char *, int, const char *) __attribute__((weak));
888 void
889 lang_check_failed (const char *file, int line, const char *function)
891 internal_error ("lang_* check: failed in %s, at %s:%d",
892 function, trim_filename (file), line);
894 #endif /* ENABLE_TREE_CHECKING */