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.
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/>. */
24 #include "coretypes.h"
32 #include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
33 #include "diagnostic-core.h"
35 #include "sh-symbian.h"
38 /* Return the type that we should use to determine if DECL is
39 imported or exported. */
42 sh_symbian_associated_type (tree decl
)
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
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
);
61 /* Return nonzero if DECL is a dllimport'd object. */
64 sh_symbian_is_dllimported (tree decl
)
68 if ( TREE_CODE (decl
) != VAR_DECL
69 && TREE_CODE (decl
) != FUNCTION_DECL
)
72 imp
= lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl
));
76 /* Class members get the dllimport status of their class. */
77 imp
= sh_symbian_associated_type (decl
);
81 imp
= lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp
));
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",
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
))
107 warning (OPT_Wattributes
, "inline function %q+D is declared as "
108 "dllimport: attribute ignored",
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",
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
)))
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. */
172 sh_symbian_possibly_export_base_class (tree base_class
)
174 VEC(tree
,gc
) *method_vec
;
177 if (! (TYPE_CONTAINS_VPTR_P (base_class
)))
180 method_vec
= CLASSTYPE_METHOD_VEC (base_class
);
181 len
= method_vec
? VEC_length (tree
, method_vec
) : 0;
185 tree member
= VEC_index (tree
, method_vec
, len
);
190 for (member
= OVL_CURRENT (member
); member
; member
= OVL_NEXT (member
))
192 if (TREE_CODE (member
) != FUNCTION_DECL
)
195 if (DECL_CONSTRUCTOR_P (member
) || DECL_DESTRUCTOR_P (member
))
198 if (! DECL_VIRTUAL_P (member
))
201 if (DECL_PURE_VIRTUAL_P (member
))
204 if (DECL_DECLARED_INLINE_P (member
))
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. */
222 print_node_brief (stderr
, "", base_class
, 0);
223 fprintf (stderr
, " EXPORTed [base class of exported class]\n");
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. */
231 sh_symbian_add_attribute (tree node
, const char *attr_name
)
236 attrs
= DECL_P (node
) ? DECL_ATTRIBUTES (node
) : TYPE_ATTRIBUTES (node
);
238 if (lookup_attribute (attr_name
, attrs
) != NULL_TREE
)
241 attr
= get_identifier (attr_name
);
244 DECL_ATTRIBUTES (node
) = tree_cons (attr
, NULL_TREE
, attrs
);
246 TYPE_ATTRIBUTES (node
) = tree_cons (attr
, NULL_TREE
, attrs
);
249 fprintf (stderr
, "propagate %s attribute", attr_name
);
250 print_node_brief (stderr
, " to", node
, 0);
251 fprintf (stderr
, "\n");
255 /* Add the named attribute to a class and its vtable and rtti. */
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
)),
274 /* Decide if a class needs to have an attribute because
275 one of its member functions has the attribute. */
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
)
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))))
292 /* Check the class's member functions. */
293 if (TREE_CODE (ctype
) == RECORD_TYPE
)
297 len
= method_vec
? VEC_length (tree
, method_vec
) : 0;
301 tree member
= VEC_index (tree
, method_vec
, len
);
306 for (member
= OVL_CURRENT (member
);
308 member
= OVL_NEXT (member
))
310 if (TREE_CODE (member
) != FUNCTION_DECL
)
313 if (DECL_PURE_VIRTUAL_P (member
))
316 if (! DECL_VIRTUAL_P (member
))
319 if (lookup_attribute (attribute_name
, DECL_ATTRIBUTES (member
)))
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");
334 print_node_brief (stderr
, "", ctype
, 0);
335 fprintf (stderr
, " does not inherit %s\n", attribute_name
);
340 /* Decide if a class needs its vtable and rtti exporting. */
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
;
354 /* Make sure that we are examining a class... */
355 if (TREE_CODE (ctype
) != RECORD_TYPE
)
358 print_node_brief (stderr
, "", ctype
, 0);
359 fprintf (stderr
, " does NOT need to be EXPORTed [not a class]\n");
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
)
369 print_node_brief (stderr
, "", ctype
, 0);
370 fprintf (stderr
, " does NOT need to be EXPORTed [no key function]\n");
375 /* If the key fn has not been defined
376 then the class should not be exported. */
377 if (! TREE_ASM_WRITTEN (key
))
380 print_node_brief (stderr
, "", ctype
, 0);
381 fprintf (stderr
, " does NOT need to be EXPORTed [key function not defined]\n");
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;
396 tree member
= VEC_index (tree
, method_vec
, len
);
401 for (member
= OVL_CURRENT (member
); member
; member
= OVL_NEXT (member
))
403 if (TREE_CODE (member
) != FUNCTION_DECL
)
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;
419 if (DECL_PURE_VIRTUAL_P (member
))
422 if (! DECL_VIRTUAL_P (member
))
425 if (DECL_DECLARED_INLINE_P (member
))
428 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member
)))
429 dllimport_member
= true;
434 if (! dllimport_member
&& ! dllimport_ctor_dtor
)
437 print_node_brief (stderr
, "", ctype
, 0);
439 " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
444 if (! inline_ctor_dtor
)
447 print_node_brief (stderr
, "", ctype
, 0);
449 " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
455 print_node_brief (stderr
, "", ctype
, 0);
456 fprintf (stderr
, " DOES need to be EXPORTed\n");
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
));
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;
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. */
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
509 if (CLASSTYPE_KEY_METHOD (ctype
))
513 for (class = keyed_classes
; class; class = TREE_CHAIN (class))
517 if (class == NULL_TREE
)
520 print_node_brief (stderr
, "Add node", ctype
, 0);
521 fprintf (stderr
, " to the keyed classes list\n");
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. */
540 sh_symbian_handle_dll_attribute (tree
*pnode
, tree name
, tree args
,
541 int flags
, bool *no_add_attrs
)
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. */
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;
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",
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
)))
601 for (overload
= OVL_CHAIN (node
); overload
; overload
= OVL_CHAIN (overload
))
605 tree function
= OVL_CURRENT (overload
);
608 || ! DECL_P (function
)
609 || (DECL_CONSTRUCTOR_P (node
) && ! DECL_CONSTRUCTOR_P (function
))
610 || (DECL_DESTRUCTOR_P (node
) && ! DECL_DESTRUCTOR_P (function
)))
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
))
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)
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",
654 *no_add_attrs
= true;
658 print_node_brief (stderr
, "mark node", node
, 0);
659 fprintf (stderr
, " as %s\n", attr
);