Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / config / sh / symbian.c
blobcb04c8c8d769e3931037ee6264e00f758505edd5
1 /* Routines for GCC for a Symbian OS targeted SH backend.
2 Copyright (C) 2004 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 2, 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 COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "output.h"
29 #include "flags.h"
30 #include "tree.h"
31 #include "expr.h"
32 #include "tm_p.h"
33 #include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
34 #include "toplev.h"
36 /* Select the level of debugging information to display.
37 0 for no debugging.
38 1 for informative messages about decisions to add attributes
39 2 for verbose information about what is being done. */
40 #define SYMBIAN_DEBUG 0
41 //#define SYMBIAN_DEBUG 1
42 //#define SYMBIAN_DEBUG 2
44 /* A unique character to encode declspec encoded objects. */
45 #define SH_SYMBIAN_FLAG_CHAR "$"
47 /* Unique strings to prefix exported and imported objects. */
48 #define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
49 #define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
52 /* Return the type that we should use to determine if DECL is
53 imported or exported. */
55 static tree
56 sh_symbian_associated_type (tree decl)
58 tree t = NULL_TREE;
60 if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
61 /* Methods now inherit their dllimport/dllexport attributes correctly
62 so there is no need to check their class. In fact it is wrong to
63 check their class since a method can remain unexported from an
64 exported class. */
65 return t;
67 /* Otherwise we can just take the DECL_CONTEXT as normal. */
68 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
69 t = DECL_CONTEXT (decl);
71 return t;
74 /* Return nonzero if DECL is a dllexport'd object. */
76 bool
77 sh_symbian_dllexport_p (tree decl)
79 tree exp;
81 if ( TREE_CODE (decl) != VAR_DECL
82 && TREE_CODE (decl) != FUNCTION_DECL)
83 return false;
85 exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
87 /* Class members get the dllexport status of their class. */
88 if (exp == NULL)
90 tree class = sh_symbian_associated_type (decl);
92 if (class)
93 exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
95 #if SYMBIAN_DEBUG
96 if (exp)
98 print_node_brief (stderr, "dllexport:", decl, 0);
99 fprintf (stderr, "\n");
101 else
102 #if SYMBIAN_DEBUG < 2
103 if (TREE_CODE (decl) != FUNCTION_DECL)
104 #endif
106 print_node_brief (stderr, "no dllexport:", decl, 0);
107 fprintf (stderr, "\n");
109 #endif
110 return exp ? true : false;
113 /* Return nonzero if DECL is a dllimport'd object. */
115 static bool
116 sh_symbian_dllimport_p (tree decl)
118 tree imp;
120 if ( TREE_CODE (decl) != VAR_DECL
121 && TREE_CODE (decl) != FUNCTION_DECL)
122 return false;
124 imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
125 if (imp)
126 return true;
128 /* Class members get the dllimport status of their class. */
129 imp = sh_symbian_associated_type (decl);
130 if (! imp)
131 return false;
133 imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
134 if (!imp)
135 return false;
137 /* Don't mark defined functions as dllimport. If the definition itself
138 was marked with dllimport, then sh_symbian_handle_dll_attribute reports
139 an error. This handles the case when the definition overrides an
140 earlier declaration. */
141 if (TREE_CODE (decl) == FUNCTION_DECL
142 && DECL_INITIAL (decl)
143 && !DECL_INLINE (decl))
145 /* Don't warn about artificial methods. */
146 if (!DECL_ARTIFICIAL (decl))
147 warning ("%H function '%D' is defined after prior declaration as dllimport: attribute ignored",
148 & DECL_SOURCE_LOCATION (decl), 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 ("%Hinline function '%D' is declared as dllimport: attribute ignored.",
159 & DECL_SOURCE_LOCATION (decl), decl);
160 return false;
163 /* Don't allow definitions of static data members in dllimport
164 class. Just ignore the attribute for vtable data. */
165 else if (TREE_CODE (decl) == VAR_DECL
166 && TREE_STATIC (decl)
167 && TREE_PUBLIC (decl)
168 && !DECL_EXTERNAL (decl))
170 if (!DECL_VIRTUAL_P (decl))
171 error ("%Hdefinition of static data member '%D' of dllimport'd class.",
172 & DECL_SOURCE_LOCATION (decl), decl);
173 return false;
176 /* Since we can't treat a pointer to a dllimport'd symbol as a
177 constant address, we turn off the attribute on C++ virtual
178 methods to allow creation of vtables using thunks. Don't mark
179 artificial methods either (in sh_symbian_associated_type, only
180 COMDAT artificial method get import status from class context). */
181 else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
182 && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
183 return false;
185 return true;
188 /* Return nonzero if SYMBOL is marked as being dllexport'd. */
190 bool
191 sh_symbian_dllexport_name_p (const char *symbol)
193 return strncmp (DLL_EXPORT_PREFIX, symbol,
194 strlen (DLL_EXPORT_PREFIX)) == 0;
197 /* Return nonzero if SYMBOL is marked as being dllimport'd. */
200 bool
201 sh_symbian_dllimport_name_p (const char *symbol)
203 return strncmp (DLL_IMPORT_PREFIX, symbol,
204 strlen (DLL_IMPORT_PREFIX)) == 0;
207 /* Mark a DECL as being dllexport'd.
208 Note that we override the previous setting (e.g.: dllimport). */
210 static void
211 sh_symbian_mark_dllexport (tree decl)
213 const char *oldname;
214 char *newname;
215 rtx rtlname;
216 tree idp;
218 rtlname = XEXP (DECL_RTL (decl), 0);
220 if (GET_CODE (rtlname) == SYMBOL_REF)
221 oldname = XSTR (rtlname, 0);
222 else if (GET_CODE (rtlname) == MEM
223 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
224 oldname = XSTR (XEXP (rtlname, 0), 0);
225 else
226 abort ();
228 if (sh_symbian_dllimport_name_p (oldname))
230 /* Remove DLL_IMPORT_PREFIX.
231 Note - we do not issue a warning here. In Symbian's environment it
232 is legitimate for a prototype to be marked as dllimport and the
233 corresponding definition to be marked as dllexport. The prototypes
234 are in headers used everywhere and the definition is in a translation
235 unit which has included the header in order to ensure argument
236 correctness. */
237 oldname += strlen (DLL_IMPORT_PREFIX);
238 DECL_NON_ADDR_CONST_P (decl) = 0;
240 else if (sh_symbian_dllexport_name_p (oldname))
241 return; /* Already done. */
243 newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
244 sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
246 /* We pass newname through get_identifier to ensure it has a unique
247 address. RTL processing can sometimes peek inside the symbol ref
248 and compare the string's addresses to see if two symbols are
249 identical. */
250 idp = get_identifier (newname);
252 XEXP (DECL_RTL (decl), 0) =
253 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
256 /* Mark a DECL as being dllimport'd. */
258 static void
259 sh_symbian_mark_dllimport (tree decl)
261 const char *oldname;
262 char *newname;
263 tree idp;
264 rtx rtlname;
265 rtx newrtl;
267 rtlname = XEXP (DECL_RTL (decl), 0);
269 if (GET_CODE (rtlname) == SYMBOL_REF)
270 oldname = XSTR (rtlname, 0);
271 else if (GET_CODE (rtlname) == MEM
272 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
273 oldname = XSTR (XEXP (rtlname, 0), 0);
274 else
275 abort ();
277 if (sh_symbian_dllexport_name_p (oldname))
279 error ("%qs declared as both exported to and imported from a DLL",
280 IDENTIFIER_POINTER (DECL_NAME (decl)));
282 else if (sh_symbian_dllimport_name_p (oldname))
284 /* Already done, but do a sanity check to prevent assembler errors. */
285 if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
286 error ("%Hfailure in redeclaration of '%D': dllimport'd symbol lacks external linkage.",
287 &DECL_SOURCE_LOCATION (decl), decl);
289 else
291 newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
292 sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
294 /* We pass newname through get_identifier to ensure it has a unique
295 address. RTL processing can sometimes peek inside the symbol ref
296 and compare the string's addresses to see if two symbols are
297 identical. */
298 idp = get_identifier (newname);
299 newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
300 XEXP (DECL_RTL (decl), 0) = newrtl;
304 void
305 sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
307 default_encode_section_info (decl, rtl, first);
309 /* Mark the decl so we can tell from the rtl whether
310 the object is dllexport'd or dllimport'd. */
311 if (sh_symbian_dllexport_p (decl))
312 sh_symbian_mark_dllexport (decl);
313 else if (sh_symbian_dllimport_p (decl))
314 sh_symbian_mark_dllimport (decl);
315 /* It might be that DECL has already been marked as dllimport, but a
316 subsequent definition nullified that. The attribute is gone but
317 DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
318 that. Ditto for the DECL_NON_ADDR_CONST_P flag. */
319 else if ( (TREE_CODE (decl) == FUNCTION_DECL
320 || TREE_CODE (decl) == VAR_DECL)
321 && DECL_RTL (decl) != NULL_RTX
322 && GET_CODE (DECL_RTL (decl)) == MEM
323 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
324 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
325 && sh_symbian_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
327 const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
328 /* Remove DLL_IMPORT_PREFIX. */
329 tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
330 rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
332 warning ("%H%s '%D' %s after being referenced with dllimport linkage.",
333 & DECL_SOURCE_LOCATION (decl),
334 TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
335 decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
336 ? "defined locally" : "redeclared without dllimport attribute");
338 XEXP (DECL_RTL (decl), 0) = newrtl;
340 DECL_NON_ADDR_CONST_P (decl) = 0;
345 /* Return the length of a function name prefix
346 that starts with the character 'c'. */
348 static int
349 sh_symbian_get_strip_length (int c)
351 /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */
352 return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
355 /* Return a pointer to a function's name with any
356 and all prefix encodings stripped from it. */
358 const char *
359 sh_symbian_strip_name_encoding (const char *name)
361 int skip;
363 while ((skip = sh_symbian_get_strip_length (*name)))
364 name += skip;
366 return name;
369 /* Add the named attribute to the given node. Copes with both DECLs and
370 TYPEs. Will only add the attribute if it is not already present. */
372 static void
373 symbian_add_attribute (tree node, const char *attr_name)
375 tree attrs;
376 tree attr;
378 attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
380 if (lookup_attribute (attr_name, attrs) != NULL_TREE)
381 return;
383 attr = get_identifier (attr_name);
385 (DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node))
386 = tree_cons (attr, NULL_TREE, attrs);
388 #if SYMBIAN_DEBUG
389 fprintf (stderr, "propogate %s attribute", attr_name);
390 print_node_brief (stderr, " to", node, 0);
391 fprintf (stderr, "\n");
392 #endif
395 /* Handle a "dllimport" or "dllexport" attribute;
396 arguments as in struct attribute_spec.handler. */
398 tree
399 sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
400 int flags, bool *no_add_attrs)
402 tree thunk;
403 tree node = *pnode;
404 const char *attr = IDENTIFIER_POINTER (name);
406 /* These attributes may apply to structure and union types being
407 created, but otherwise should pass to the declaration involved. */
408 if (!DECL_P (node))
410 if (flags & ((int) ATTR_FLAG_DECL_NEXT
411 | (int) ATTR_FLAG_FUNCTION_NEXT
412 | (int) ATTR_FLAG_ARRAY_NEXT))
414 warning ("%qs attribute ignored", attr);
415 *no_add_attrs = true;
416 return tree_cons (name, args, NULL_TREE);
419 if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
421 warning ("%qs attribute ignored", attr);
422 *no_add_attrs = true;
425 return NULL_TREE;
428 /* Report error on dllimport ambiguities
429 seen now before they cause any damage. */
430 else if (is_attribute_p ("dllimport", name))
432 if (TREE_CODE (node) == VAR_DECL)
434 if (DECL_INITIAL (node))
436 error ("%Hvariable %qD definition is marked dllimport.",
437 & DECL_SOURCE_LOCATION (node), node);
438 *no_add_attrs = true;
441 /* `extern' needn't be specified with dllimport.
442 Specify `extern' now and hope for the best. Sigh. */
443 DECL_EXTERNAL (node) = 1;
444 /* Also, implicitly give dllimport'd variables declared within
445 a function global scope, unless declared static. */
446 if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
447 TREE_PUBLIC (node) = 1;
451 /* If the node is an overloaded constructor or destructor, then we must
452 make sure that the attribute is propagated along the overload chain,
453 as it is these overloaded functions which will be emitted, rather than
454 the user declared constructor itself. */
455 if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
456 && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
458 tree overload;
460 for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
462 tree node_args;
463 tree func_args;
464 tree function = OVL_CURRENT (overload);
466 if (! function
467 || ! DECL_P (function)
468 || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
469 || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function)))
470 continue;
472 /* The arguments must match as well. */
473 for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
474 node_args && func_args;
475 node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
476 if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
477 break;
479 if (node_args || func_args)
481 /* We can ignore an extraneous __in_chrg arguments in the node.
482 GCC generated destructors, for example, will have this. */
483 if ((node_args == NULL_TREE
484 || func_args != NULL_TREE)
485 && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
486 continue;
489 symbian_add_attribute (function, attr);
491 /* Propagate the attribute to any function thunks as well. */
492 for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
493 if (TREE_CODE (thunk) == FUNCTION_DECL)
494 symbian_add_attribute (thunk, attr);
498 if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
500 /* Propagate the attribute to any thunks of this function. */
501 for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
502 if (TREE_CODE (thunk) == FUNCTION_DECL)
503 symbian_add_attribute (thunk, attr);
506 /* Report error if symbol is not accessible at global scope. */
507 if (!TREE_PUBLIC (node)
508 && ( TREE_CODE (node) == VAR_DECL
509 || TREE_CODE (node) == FUNCTION_DECL))
511 error ("%Hexternal linkage required for symbol '%D' because of '%s' attribute.",
512 & DECL_SOURCE_LOCATION (node), node, IDENTIFIER_POINTER (name));
513 *no_add_attrs = true;
516 #if SYMBIAN_DEBUG
517 print_node_brief (stderr, "mark node", node, 0);
518 fprintf (stderr, " as %s\n", attr);
519 #endif
521 return NULL_TREE;
524 /* This code implements a specification for exporting the vtable and rtti of
525 classes that have members with the dllexport or dllexport attributes.
526 This specification is defined here:
528 http://www.armdevzone.com/EABI/exported_class.txt
530 Basically it says that a class's vtable and rtti should be exported if
531 the following rules apply:
533 - If it has any non-inline non-pure virtual functions,
534 at least one of these need to be declared dllimport
535 OR any of the constructors is declared dllimport.
539 - The class has an inline constructor/destructor and
540 a key-function (placement of vtable uniquely defined) that
541 is defined in this translation unit.
543 The specification also says that for classes which will have their
544 vtables and rtti exported that their base class(es) might also need a
545 similar exporting if:
547 - Every base class needs to have its vtable & rtti exported
548 as well, if the following the conditions hold true:
549 + The base class has a non-inline declared non-pure virtual function
550 + The base class is polymorphic (has or inherits any virtual functions)
551 or the base class has any virtual base classes. */
553 /* Decide if a base class of a class should
554 also have its vtable and rtti exported. */
556 static void
557 symbian_possibly_export_base_class (tree base_class)
559 tree methods;
560 int len;
562 if (! (TYPE_CONTAINS_VPTR_P (base_class)))
563 return;
565 methods = CLASSTYPE_METHOD_VEC (base_class);
566 len = methods ? TREE_VEC_LENGTH (methods) : 0;
568 for (;len --;)
570 tree member = TREE_VEC_ELT (methods, len);
572 if (! member)
573 continue;
575 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
577 if (TREE_CODE (member) != FUNCTION_DECL)
578 continue;
580 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
581 continue;
583 if (! DECL_VIRTUAL_P (member))
584 continue;
586 if (DECL_PURE_VIRTUAL_P (member))
587 continue;
589 if (DECL_INLINE (member))
590 continue;
592 break;
595 if (member)
596 break;
599 if (len < 0)
600 return;
602 /* FIXME: According to the spec this base class should be exported, but
603 a) how do we do this ? and
604 b) it does not appear to be necessary for compliance with the Symbian
605 OS which so far is the only consumer of this code. */
606 #if SYMBIAN_DEBUG
607 print_node_brief (stderr, "", base_class, 0);
608 fprintf (stderr, " EXPORTed [base class of exported class]\n");
609 #endif
612 /* Decide if a class needs its vtable and rtti exporting. */
614 static bool
615 symbian_export_vtable_and_rtti_p (tree ctype)
617 bool inline_ctor_dtor;
618 bool dllimport_ctor_dtor;
619 bool dllimport_member;
620 tree binfo, base_binfo;
621 tree methods;
622 tree key;
623 int i;
624 int len;
626 /* Make sure that we are examining a class... */
627 if (TREE_CODE (ctype) != RECORD_TYPE)
629 #if SYMBIAN_DEBUG
630 print_node_brief (stderr, "", ctype, 0);
631 fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
632 #endif
633 return false;
636 /* If the class does not have a key function it
637 does not need to have its vtable exported. */
638 if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
640 #if SYMBIAN_DEBUG
641 print_node_brief (stderr, "", ctype, 0);
642 fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
643 #endif
644 return false;
647 /* If the key fn has not been defined
648 then the class should not be exported. */
649 if (! TREE_ASM_WRITTEN (key))
651 #if SYMBIAN_DEBUG
652 print_node_brief (stderr, "", ctype, 0);
653 fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
654 #endif
655 return false;
658 /* Check the class's member functions. */
659 inline_ctor_dtor = false;
660 dllimport_ctor_dtor = false;
661 dllimport_member = false;
663 methods = CLASSTYPE_METHOD_VEC (ctype);
664 len = methods ? TREE_VEC_LENGTH (methods) : 0;
666 for (;len --;)
668 tree member = TREE_VEC_ELT (methods, len);
670 if (! member)
671 continue;
673 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
675 if (TREE_CODE (member) != FUNCTION_DECL)
676 continue;
678 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
680 if (DECL_INLINE (member)
681 /* Ignore C++ backend created inline ctors/dtors. */
682 && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
683 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
684 inline_ctor_dtor = true;
686 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
687 dllimport_ctor_dtor = true;
689 else
691 if (DECL_PURE_VIRTUAL_P (member))
692 continue;
694 if (! DECL_VIRTUAL_P (member))
695 continue;
697 if (DECL_INLINE (member))
698 continue;
700 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
701 dllimport_member = true;
706 if (! dllimport_member && ! dllimport_ctor_dtor)
708 #if SYMBIAN_DEBUG
709 print_node_brief (stderr, "", ctype, 0);
710 fprintf (stderr,
711 " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
712 #endif
713 return false;
716 if (! inline_ctor_dtor)
718 #if SYMBIAN_DEBUG
719 print_node_brief (stderr, "", ctype, 0);
720 fprintf (stderr,
721 " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
722 #endif
723 return false;
726 #if SYMBIAN_DEBUG
727 print_node_brief (stderr, "", ctype, 0);
728 fprintf (stderr, " DOES need to be EXPORTed\n");
729 #endif
731 /* Now we must check and possibly export the base classes. */
732 for (i = 0, binfo = TYPE_BINFO (ctype);
733 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
734 symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
736 return true;
739 /* Add the named attribute to a class and its vtable and rtti. */
741 static void
742 symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
744 symbian_add_attribute (ctype, attr_name);
746 /* If the vtable exists then they need annotating as well. */
747 if (CLASSTYPE_VTABLES (ctype))
748 /* XXX - Do we need to annotate any vtables other than the primary ? */
749 symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
751 /* If the rtti exists then it needs annotating as well. */
752 if (TYPE_MAIN_VARIANT (ctype)
753 && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
754 symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
755 attr_name);
758 /* Decide if a class needs to have an attribute because
759 one of its member functions has the attribute. */
761 static bool
762 symbian_class_needs_attribute_p (tree ctype, const char *attribute_name)
764 /* If the key function has the attribute then the class needs it too. */
765 if (TYPE_POLYMORPHIC_P (ctype)
766 && CLASSTYPE_KEY_METHOD (ctype)
767 && lookup_attribute (attribute_name,
768 DECL_ATTRIBUTES (CLASSTYPE_KEY_METHOD (ctype))))
769 return true;
771 /* Check the class's member functions. */
772 if (TREE_CODE (ctype) == RECORD_TYPE)
774 tree methods = CLASSTYPE_METHOD_VEC (ctype);
775 unsigned int len = methods ? TREE_VEC_LENGTH (methods) : 0;
777 for (;len --;)
779 tree member = TREE_VEC_ELT (methods, len);
781 if (! member)
782 continue;
784 for (member = OVL_CURRENT (member);
785 member;
786 member = OVL_NEXT (member))
788 if (TREE_CODE (member) != FUNCTION_DECL)
789 continue;
791 if (DECL_PURE_VIRTUAL_P (member))
792 continue;
794 if (! DECL_VIRTUAL_P (member))
795 continue;
797 if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
799 #if SYMBIAN_DEBUG
800 print_node_brief (stderr, "", ctype, 0);
801 fprintf (stderr, " inherits %s because", attribute_name);
802 print_node_brief (stderr, "", member, 0);
803 fprintf (stderr, " has it.\n");
804 #endif
805 return true;
811 #if SYMBIAN_DEBUG
812 print_node_brief (stderr, "", ctype, 0);
813 fprintf (stderr, " does not inherit %s\n", attribute_name);
814 #endif
815 return false;
819 symbian_import_export_class (tree ctype, int import_export)
821 const char *attr_name = NULL;
823 /* If we are exporting the class but it does not have the dllexport
824 attribute then we may need to add it. Similarly imported classes
825 may need the dllimport attribute. */
826 switch (import_export)
828 case 1: attr_name = "dllexport"; break;
829 case -1: attr_name = "dllimport"; break;
830 default: break;
833 if (attr_name
834 && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
836 if (symbian_class_needs_attribute_p (ctype, attr_name))
837 symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
839 /* Classes can be forced to export their
840 vtable and rtti under certain conditions. */
841 if (symbian_export_vtable_and_rtti_p (ctype))
843 symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
845 /* Make sure that the class and its vtable are exported. */
846 import_export = 1;
848 if (CLASSTYPE_VTABLES (ctype))
849 DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
851 /* Check to make sure that if the class has a key method that
852 it is now on the list of keyed classes. That way its vtable
853 will be emitted. */
854 if (CLASSTYPE_KEY_METHOD (ctype))
856 tree class;
858 for (class = keyed_classes; class; class = TREE_CHAIN (class))
859 if (class == ctype)
860 break;
862 if (class == NULL_TREE)
864 #if SYMBIAN_DEBUG
865 print_node_brief (stderr, "Add node", ctype, 0);
866 fprintf (stderr, " to the keyed classes list\n");
867 #endif
868 keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
872 /* Make sure that the typeinfo will be emitted as well. */
873 if (CLASS_TYPE_P (ctype))
874 TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
878 return import_export;
881 /* Dummy definition of this array for cc1 building purposes. */
882 tree cp_global_trees[CPTI_MAX] __attribute__((weak));
884 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
886 /* Dummy version of this G++ function for building cc1. */
887 void lang_check_failed (const char *, int, const char *) __attribute__((weak));
889 void
890 lang_check_failed (const char *file, int line, const char *function)
892 internal_error ("lang_* check: failed in %s, at %s:%d",
893 function, trim_filename (file), line);
895 #endif /* ENABLE_TREE_CHECKING */