Merge from mainline (160224:163495).
[official-gcc/graphite-test-results.git] / gcc / config / sh / symbian-cxx.c
blob5f1ef93ca6e6605dc3b10f2fd4d35c6160374c13
1 /* Routines for C++ support for GCC for a Symbian OS targeted SH backend.
2 Copyright (C) 2004, 2005, 2007, 2009 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 "diagnostic-core.h"
34 #include "toplev.h"
35 #include "sh-symbian.h"
38 /* Return the type that we should use to determine if DECL is
39 imported or exported. */
41 tree
42 sh_symbian_associated_type (tree decl)
44 tree t = NULL_TREE;
46 if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
47 /* Methods now inherit their dllimport/dllexport attributes correctly
48 so there is no need to check their class. In fact it is wrong to
49 check their class since a method can remain unexported from an
50 exported class. */
51 return t;
53 /* Otherwise we can just take the DECL_CONTEXT as normal. */
54 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
55 t = DECL_CONTEXT (decl);
57 return t;
61 /* Return nonzero if DECL is a dllimport'd object. */
63 bool
64 sh_symbian_is_dllimported (tree decl)
66 tree imp;
68 if ( TREE_CODE (decl) != VAR_DECL
69 && TREE_CODE (decl) != FUNCTION_DECL)
70 return false;
72 imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
73 if (imp)
74 return true;
76 /* Class members get the dllimport status of their class. */
77 imp = sh_symbian_associated_type (decl);
78 if (! imp)
79 return false;
81 imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
82 if (!imp)
83 return false;
85 /* Don't mark defined functions as dllimport. If the definition itself
86 was marked with dllimport, then sh_symbian_handle_dll_attribute reports
87 an error. This handles the case when the definition overrides an
88 earlier declaration. */
89 if (TREE_CODE (decl) == FUNCTION_DECL
90 && DECL_INITIAL (decl)
91 && ! DECL_DECLARED_INLINE_P (decl))
93 /* Don't warn about artificial methods. */
94 if (!DECL_ARTIFICIAL (decl))
95 warning (OPT_Wattributes, "function %q+D is defined after prior "
96 "declaration as dllimport: attribute ignored",
97 decl);
98 return false;
101 /* We ignore the dllimport attribute for inline member functions.
102 This differs from MSVC behavior which treats it like GNUC
103 'extern inline' extension. */
104 else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
106 if (extra_warnings)
107 warning (OPT_Wattributes, "inline function %q+D is declared as "
108 "dllimport: attribute ignored",
109 decl);
110 return false;
113 /* Don't allow definitions of static data members in dllimport
114 class. Just ignore the attribute for vtable data. */
115 else if (TREE_CODE (decl) == VAR_DECL
116 && TREE_STATIC (decl)
117 && TREE_PUBLIC (decl)
118 && !DECL_EXTERNAL (decl))
120 if (!DECL_VIRTUAL_P (decl))
121 error ("definition of static data member %q+D of dllimport'd class",
122 decl);
123 return false;
126 /* Since we can't treat a pointer to a dllimport'd symbol as a
127 constant address, we turn off the attribute on C++ virtual
128 methods to allow creation of vtables using thunks. Don't mark
129 artificial methods either (in sh_symbian_associated_type, only
130 COMDAT artificial method get import status from class context). */
131 else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
132 && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
133 return false;
135 return true;
139 /* This code implements a specification for exporting the vtable and rtti of
140 classes that have members with the dllexport or dllexport attributes.
141 This specification is defined here:
143 http://www.armdevzone.com/EABI/exported_class.txt
145 Basically it says that a class's vtable and rtti should be exported if
146 the following rules apply:
148 - If it has any non-inline non-pure virtual functions,
149 at least one of these need to be declared dllimport
150 OR any of the constructors is declared dllimport.
154 - The class has an inline constructor/destructor and
155 a key-function (placement of vtable uniquely defined) that
156 is defined in this translation unit.
158 The specification also says that for classes which will have their
159 vtables and rtti exported that their base class(es) might also need a
160 similar exporting if:
162 - Every base class needs to have its vtable & rtti exported
163 as well, if the following the conditions hold true:
164 + The base class has a non-inline declared non-pure virtual function
165 + The base class is polymorphic (has or inherits any virtual functions)
166 or the base class has any virtual base classes. */
168 /* Decide if a base class of a class should
169 also have its vtable and rtti exported. */
171 static void
172 sh_symbian_possibly_export_base_class (tree base_class)
174 VEC(tree,gc) *method_vec;
175 int len;
177 if (! (TYPE_CONTAINS_VPTR_P (base_class)))
178 return;
180 method_vec = CLASSTYPE_METHOD_VEC (base_class);
181 len = method_vec ? VEC_length (tree, method_vec) : 0;
183 for (;len --;)
185 tree member = VEC_index (tree, method_vec, len);
187 if (! member)
188 continue;
190 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
192 if (TREE_CODE (member) != FUNCTION_DECL)
193 continue;
195 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
196 continue;
198 if (! DECL_VIRTUAL_P (member))
199 continue;
201 if (DECL_PURE_VIRTUAL_P (member))
202 continue;
204 if (DECL_DECLARED_INLINE_P (member))
205 continue;
207 break;
210 if (member)
211 break;
214 if (len < 0)
215 return;
217 /* FIXME: According to the spec this base class should be exported, but
218 a) how do we do this ? and
219 b) it does not appear to be necessary for compliance with the Symbian
220 OS which so far is the only consumer of this code. */
221 #if SYMBIAN_DEBUG
222 print_node_brief (stderr, "", base_class, 0);
223 fprintf (stderr, " EXPORTed [base class of exported class]\n");
224 #endif
227 /* Add the named attribute to the given node. Copes with both DECLs and
228 TYPEs. Will only add the attribute if it is not already present. */
230 static void
231 sh_symbian_add_attribute (tree node, const char *attr_name)
233 tree attrs;
234 tree attr;
236 attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
238 if (lookup_attribute (attr_name, attrs) != NULL_TREE)
239 return;
241 attr = get_identifier (attr_name);
243 if (DECL_P (node))
244 DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
245 else
246 TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
248 #if SYMBIAN_DEBUG
249 fprintf (stderr, "propagate %s attribute", attr_name);
250 print_node_brief (stderr, " to", node, 0);
251 fprintf (stderr, "\n");
252 #endif
255 /* Add the named attribute to a class and its vtable and rtti. */
257 static void
258 sh_symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
260 sh_symbian_add_attribute (ctype, attr_name);
262 /* If the vtable exists then they need annotating as well. */
263 if (CLASSTYPE_VTABLES (ctype))
264 /* XXX - Do we need to annotate any vtables other than the primary ? */
265 sh_symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
267 /* If the rtti exists then it needs annotating as well. */
268 if (TYPE_MAIN_VARIANT (ctype)
269 && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
270 sh_symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
271 attr_name);
274 /* Decide if a class needs to have an attribute because
275 one of its member functions has the attribute. */
277 static bool
278 sh_symbian_class_needs_attribute (tree ctype, const char *attribute_name)
280 VEC(tree,gc) *method_vec;
282 method_vec = CLASSTYPE_METHOD_VEC (ctype);
284 /* If the key function has the attribute then the class needs it too. */
285 if (TYPE_POLYMORPHIC_P (ctype)
286 && method_vec
287 && tree_contains_struct [TREE_CODE (ctype), TS_DECL_COMMON] == 1
288 && lookup_attribute (attribute_name,
289 DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
290 return true;
292 /* Check the class's member functions. */
293 if (TREE_CODE (ctype) == RECORD_TYPE)
295 unsigned int len;
297 len = method_vec ? VEC_length (tree, method_vec) : 0;
299 for (;len --;)
301 tree member = VEC_index (tree, method_vec, len);
303 if (! member)
304 continue;
306 for (member = OVL_CURRENT (member);
307 member;
308 member = OVL_NEXT (member))
310 if (TREE_CODE (member) != FUNCTION_DECL)
311 continue;
313 if (DECL_PURE_VIRTUAL_P (member))
314 continue;
316 if (! DECL_VIRTUAL_P (member))
317 continue;
319 if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
321 #if SYMBIAN_DEBUG
322 print_node_brief (stderr, "", ctype, 0);
323 fprintf (stderr, " inherits %s because", attribute_name);
324 print_node_brief (stderr, "", member, 0);
325 fprintf (stderr, " has it.\n");
326 #endif
327 return true;
333 #if SYMBIAN_DEBUG
334 print_node_brief (stderr, "", ctype, 0);
335 fprintf (stderr, " does not inherit %s\n", attribute_name);
336 #endif
337 return false;
340 /* Decide if a class needs its vtable and rtti exporting. */
342 static bool
343 symbian_export_vtable_and_rtti_p (tree ctype)
345 bool inline_ctor_dtor;
346 bool dllimport_ctor_dtor;
347 bool dllimport_member;
348 tree binfo, base_binfo;
349 VEC(tree,gc) *method_vec;
350 tree key;
351 int i;
352 int len;
354 /* Make sure that we are examining a class... */
355 if (TREE_CODE (ctype) != RECORD_TYPE)
357 #if SYMBIAN_DEBUG
358 print_node_brief (stderr, "", ctype, 0);
359 fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
360 #endif
361 return false;
364 /* If the class does not have a key function it
365 does not need to have its vtable exported. */
366 if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
368 #if SYMBIAN_DEBUG
369 print_node_brief (stderr, "", ctype, 0);
370 fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
371 #endif
372 return false;
375 /* If the key fn has not been defined
376 then the class should not be exported. */
377 if (! TREE_ASM_WRITTEN (key))
379 #if SYMBIAN_DEBUG
380 print_node_brief (stderr, "", ctype, 0);
381 fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
382 #endif
383 return false;
386 /* Check the class's member functions. */
387 inline_ctor_dtor = false;
388 dllimport_ctor_dtor = false;
389 dllimport_member = false;
391 method_vec = CLASSTYPE_METHOD_VEC (ctype);
392 len = method_vec ? VEC_length (tree, method_vec) : 0;
394 for (;len --;)
396 tree member = VEC_index (tree, method_vec, len);
398 if (! member)
399 continue;
401 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
403 if (TREE_CODE (member) != FUNCTION_DECL)
404 continue;
406 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
408 if (DECL_DECLARED_INLINE_P (member)
409 /* Ignore C++ backend created inline ctors/dtors. */
410 && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
411 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
412 inline_ctor_dtor = true;
414 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
415 dllimport_ctor_dtor = true;
417 else
419 if (DECL_PURE_VIRTUAL_P (member))
420 continue;
422 if (! DECL_VIRTUAL_P (member))
423 continue;
425 if (DECL_DECLARED_INLINE_P (member))
426 continue;
428 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
429 dllimport_member = true;
434 if (! dllimport_member && ! dllimport_ctor_dtor)
436 #if SYMBIAN_DEBUG
437 print_node_brief (stderr, "", ctype, 0);
438 fprintf (stderr,
439 " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
440 #endif
441 return false;
444 if (! inline_ctor_dtor)
446 #if SYMBIAN_DEBUG
447 print_node_brief (stderr, "", ctype, 0);
448 fprintf (stderr,
449 " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
450 #endif
451 return false;
454 #if SYMBIAN_DEBUG
455 print_node_brief (stderr, "", ctype, 0);
456 fprintf (stderr, " DOES need to be EXPORTed\n");
457 #endif
459 /* Now we must check and possibly export the base classes. */
460 for (i = 0, binfo = TYPE_BINFO (ctype);
461 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
462 sh_symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
464 return true;
467 /* Possibly override the decision to export class TYPE. Upon entry
468 IMPORT_EXPORT will contain 1 if the class is going to be exported,
469 -1 if it is going to be imported and 0 otherwise. This function
470 should return the modified value and perform any other actions
471 necessary to support the backend's targeted operating system. */
474 sh_symbian_import_export_class (tree ctype, int import_export)
476 const char *attr_name = NULL;
478 /* If we are exporting the class but it does not have the dllexport
479 attribute then we may need to add it. Similarly imported classes
480 may need the dllimport attribute. */
481 switch (import_export)
483 case 1: attr_name = "dllexport"; break;
484 case -1: attr_name = "dllimport"; break;
485 default: break;
488 if (attr_name
489 && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
491 if (sh_symbian_class_needs_attribute (ctype, attr_name))
492 sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
494 /* Classes can be forced to export their
495 vtable and rtti under certain conditions. */
496 if (symbian_export_vtable_and_rtti_p (ctype))
498 sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
500 /* Make sure that the class and its vtable are exported. */
501 import_export = 1;
503 if (CLASSTYPE_VTABLES (ctype))
504 DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
506 /* Check to make sure that if the class has a key method that
507 it is now on the list of keyed classes. That way its vtable
508 will be emitted. */
509 if (CLASSTYPE_KEY_METHOD (ctype))
511 tree class;
513 for (class = keyed_classes; class; class = TREE_CHAIN (class))
514 if (class == ctype)
515 break;
517 if (class == NULL_TREE)
519 #if SYMBIAN_DEBUG
520 print_node_brief (stderr, "Add node", ctype, 0);
521 fprintf (stderr, " to the keyed classes list\n");
522 #endif
523 keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
527 /* Make sure that the typeinfo will be emitted as well. */
528 if (CLASS_TYPE_P (ctype))
529 TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
533 return import_export;
536 /* Handle a "dllimport" or "dllexport" attribute;
537 arguments as in struct attribute_spec.handler. */
539 tree
540 sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
541 int flags, bool *no_add_attrs)
543 tree thunk;
544 tree node = *pnode;
545 const char *attr = IDENTIFIER_POINTER (name);
547 /* These attributes may apply to structure and union types being
548 created, but otherwise should pass to the declaration involved. */
549 if (!DECL_P (node))
551 if (flags & ((int) ATTR_FLAG_DECL_NEXT
552 | (int) ATTR_FLAG_FUNCTION_NEXT
553 | (int) ATTR_FLAG_ARRAY_NEXT))
555 warning (OPT_Wattributes, "%qs attribute ignored", attr);
556 *no_add_attrs = true;
557 return tree_cons (name, args, NULL_TREE);
560 if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
562 warning (OPT_Wattributes, "%qs attribute ignored", attr);
563 *no_add_attrs = true;
566 return NULL_TREE;
569 /* Report error on dllimport ambiguities
570 seen now before they cause any damage. */
571 else if (is_attribute_p ("dllimport", name))
573 if (TREE_CODE (node) == VAR_DECL)
575 if (DECL_INITIAL (node))
577 error ("variable %q+D definition is marked dllimport",
578 node);
579 *no_add_attrs = true;
582 /* `extern' needn't be specified with dllimport.
583 Specify `extern' now and hope for the best. Sigh. */
584 DECL_EXTERNAL (node) = 1;
585 /* Also, implicitly give dllimport'd variables declared within
586 a function global scope, unless declared static. */
587 if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
588 TREE_PUBLIC (node) = 1;
592 /* If the node is an overloaded constructor or destructor, then we must
593 make sure that the attribute is propagated along the overload chain,
594 as it is these overloaded functions which will be emitted, rather than
595 the user declared constructor itself. */
596 if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
597 && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
599 tree overload;
601 for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
603 tree node_args;
604 tree func_args;
605 tree function = OVL_CURRENT (overload);
607 if (! function
608 || ! DECL_P (function)
609 || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
610 || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function)))
611 continue;
613 /* The arguments must match as well. */
614 for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
615 node_args && func_args;
616 node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
617 if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
618 break;
620 if (node_args || func_args)
622 /* We can ignore an extraneous __in_chrg arguments in the node.
623 GCC generated destructors, for example, will have this. */
624 if ((node_args == NULL_TREE
625 || func_args != NULL_TREE)
626 && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
627 continue;
630 sh_symbian_add_attribute (function, attr);
632 /* Propagate the attribute to any function thunks as well. */
633 for (thunk = DECL_THUNKS (function); thunk; thunk = DECL_CHAIN (thunk))
634 if (TREE_CODE (thunk) == FUNCTION_DECL)
635 sh_symbian_add_attribute (thunk, attr);
639 if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
641 /* Propagate the attribute to any thunks of this function. */
642 for (thunk = DECL_THUNKS (node); thunk; thunk = DECL_CHAIN (thunk))
643 if (TREE_CODE (thunk) == FUNCTION_DECL)
644 sh_symbian_add_attribute (thunk, attr);
647 /* Report error if symbol is not accessible at global scope. */
648 if (!TREE_PUBLIC (node)
649 && ( TREE_CODE (node) == VAR_DECL
650 || TREE_CODE (node) == FUNCTION_DECL))
652 error ("external linkage required for symbol %q+D because of %qE attribute",
653 node, name);
654 *no_add_attrs = true;
657 #if SYMBIAN_DEBUG
658 print_node_brief (stderr, "mark node", node, 0);
659 fprintf (stderr, " as %s\n", attr);
660 #endif
662 return NULL_TREE;