1/* Routines for GCC for a Symbian OS targeted SH backend. 2 Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3 Contributed by RedHat. 4 Most of this code is stolen from i386/winnt.c. 5 6 This file is part of GCC. 7 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. 12 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. 17 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, 51 Franklin Street, Fifth Floor, 21 Boston, MA 02110-1301, USA. */ 22 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" 35 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 */ 43 44/* A unique character to encode declspec encoded objects. */ 45#define SH_SYMBIAN_FLAG_CHAR "$" 46 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." 50 51 52/* Return the type that we should use to determine if DECL is 53 imported or exported. */ 54 55static tree 56sh_symbian_associated_type (tree decl) 57{ 58 tree t = NULL_TREE; 59 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; 66 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); 70 71 return t; 72} 73 74/* Return nonzero if DECL is a dllexport'd object. */ 75 76bool 77sh_symbian_dllexport_p (tree decl) 78{ 79 tree exp; 80 81 if ( TREE_CODE (decl) != VAR_DECL 82 && TREE_CODE (decl) != FUNCTION_DECL) 83 return false; 84 85 exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); 86 87 /* Class members get the dllexport status of their class. */ 88 if (exp == NULL) 89 { 90 tree class = sh_symbian_associated_type (decl); 91 92 if (class) 93 exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class)); 94 } 95#if SYMBIAN_DEBUG 96 if (exp) 97 { 98 print_node_brief (stderr, "dllexport:", decl, 0); 99 fprintf (stderr, "\n"); 100 } 101 else 102#if SYMBIAN_DEBUG < 2 103 if (TREE_CODE (decl) != FUNCTION_DECL) 104#endif 105 { 106 print_node_brief (stderr, "no dllexport:", decl, 0); 107 fprintf (stderr, "\n"); 108 } 109#endif 110 return exp ? true : false; 111} 112 113/* Return nonzero if DECL is a dllimport'd object. */ 114 115static bool 116sh_symbian_dllimport_p (tree decl) 117{ 118 tree imp; 119 120 if ( TREE_CODE (decl) != VAR_DECL 121 && TREE_CODE (decl) != FUNCTION_DECL) 122 return false; 123 124 imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); 125 if (imp) 126 return true; 127 128 /* Class members get the dllimport status of their class. */ 129 imp = sh_symbian_associated_type (decl); 130 if (! imp) 131 return false; 132 133 imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp)); 134 if (!imp) 135 return false; 136 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)) 144 { 145 /* Don't warn about artificial methods. */ 146 if (!DECL_ARTIFICIAL (decl)) 147 warning (OPT_Wattributes, "function %q+D is defined after prior " 148 "declaration as dllimport: attribute ignored", 149 decl); 150 return false; 151 } 152 153 /* We ignore the dllimport attribute for inline member functions. 154 This differs from MSVC behavior which treats it like GNUC 155 'extern inline' extension. */ 156 else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) 157 { 158 if (extra_warnings) 159 warning (OPT_Wattributes, "inline function %q+D is declared as " 160 "dllimport: attribute ignored", 161 decl); 162 return false; 163 } 164 165 /* Don't allow definitions of static data members in dllimport 166 class. Just ignore the attribute for vtable data. */ 167 else if (TREE_CODE (decl) == VAR_DECL 168 && TREE_STATIC (decl) 169 && TREE_PUBLIC (decl) 170 && !DECL_EXTERNAL (decl)) 171 { 172 if (!DECL_VIRTUAL_P (decl)) 173 error ("definition of static data member %q+D of dllimport'd class", 174 decl); 175 return false; 176 } 177 178 /* Since we can't treat a pointer to a dllimport'd symbol as a 179 constant address, we turn off the attribute on C++ virtual 180 methods to allow creation of vtables using thunks. Don't mark 181 artificial methods either (in sh_symbian_associated_type, only 182 COMDAT artificial method get import status from class context). */ 183 else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE 184 && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl))) 185 return false; 186 187 return true; 188} 189 190/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 191 192bool 193sh_symbian_dllexport_name_p (const char *symbol) 194{ 195 return strncmp (DLL_EXPORT_PREFIX, symbol, 196 strlen (DLL_EXPORT_PREFIX)) == 0; 197} 198 199/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 200 201 202bool 203sh_symbian_dllimport_name_p (const char *symbol) 204{ 205 return strncmp (DLL_IMPORT_PREFIX, symbol, 206 strlen (DLL_IMPORT_PREFIX)) == 0; 207} 208 209/* Mark a DECL as being dllexport'd. 210 Note that we override the previous setting (e.g.: dllimport). */ 211 212static void 213sh_symbian_mark_dllexport (tree decl) 214{ 215 const char *oldname; 216 char *newname; 217 rtx rtlname; 218 tree idp; 219 220 rtlname = XEXP (DECL_RTL (decl), 0); 221 if (GET_CODE (rtlname) == MEM) 222 rtlname = XEXP (rtlname, 0); 223 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 224 oldname = XSTR (rtlname, 0); 225 226 if (sh_symbian_dllimport_name_p (oldname)) 227 { 228 /* Remove DLL_IMPORT_PREFIX. 229 Note - we do not issue a warning here. In Symbian's environment it 230 is legitimate for a prototype to be marked as dllimport and the 231 corresponding definition to be marked as dllexport. The prototypes 232 are in headers used everywhere and the definition is in a translation 233 unit which has included the header in order to ensure argument 234 correctness. */ 235 oldname += strlen (DLL_IMPORT_PREFIX); 236 DECL_DLLIMPORT_P (decl) = 0; 237 } 238 else if (sh_symbian_dllexport_name_p (oldname)) 239 return; /* Already done. */ 240 241 newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1); 242 sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname); 243 244 /* We pass newname through get_identifier to ensure it has a unique 245 address. RTL processing can sometimes peek inside the symbol ref 246 and compare the string's addresses to see if two symbols are 247 identical. */ 248 idp = get_identifier (newname); 249 250 XEXP (DECL_RTL (decl), 0) = 251 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 252} 253 254/* Mark a DECL as being dllimport'd. */ 255 256static void 257sh_symbian_mark_dllimport (tree decl) 258{ 259 const char *oldname; 260 char *newname; 261 tree idp; 262 rtx rtlname; 263 rtx newrtl; 264 265 rtlname = XEXP (DECL_RTL (decl), 0); 266 if (GET_CODE (rtlname) == MEM) 267 rtlname = XEXP (rtlname, 0); 268 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 269 oldname = XSTR (rtlname, 0); 270 271 if (sh_symbian_dllexport_name_p (oldname)) 272 { 273 error ("%qs declared as both exported to and imported from a DLL", 274 IDENTIFIER_POINTER (DECL_NAME (decl))); 275 } 276 else if (sh_symbian_dllimport_name_p (oldname)) 277 { 278 /* Already done, but do a sanity check to prevent assembler errors. */ 279 if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) 280 error ("failure in redeclaration of %q+D: dllimport'd symbol lacks external linkage", 281 decl); 282 } 283 else 284 { 285 newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); 286 sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); 287 288 /* We pass newname through get_identifier to ensure it has a unique 289 address. RTL processing can sometimes peek inside the symbol ref 290 and compare the string's addresses to see if two symbols are 291 identical. */ 292 idp = get_identifier (newname); 293 newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 294 XEXP (DECL_RTL (decl), 0) = newrtl; 295 } 296} 297 298void 299sh_symbian_encode_section_info (tree decl, rtx rtl, int first) 300{ 301 default_encode_section_info (decl, rtl, first); 302 303 /* Mark the decl so we can tell from the rtl whether 304 the object is dllexport'd or dllimport'd. */ 305 if (sh_symbian_dllexport_p (decl)) 306 sh_symbian_mark_dllexport (decl); 307 else if (sh_symbian_dllimport_p (decl)) 308 sh_symbian_mark_dllimport (decl); 309 /* It might be that DECL has already been marked as dllimport, but a 310 subsequent definition nullified that. The attribute is gone but 311 DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove 312 that. Ditto for the DECL_DLLIMPORT_P flag. */ 313 else if ( (TREE_CODE (decl) == FUNCTION_DECL 314 || TREE_CODE (decl) == VAR_DECL) 315 && DECL_RTL (decl) != NULL_RTX 316 && GET_CODE (DECL_RTL (decl)) == MEM 317 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM 318 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF 319 && sh_symbian_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) 320 { 321 const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); 322 /* Remove DLL_IMPORT_PREFIX. */ 323 tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX)); 324 rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 325 326 warning (0, "%s %q+D %s after being referenced with dllimport linkage", 327 TREE_CODE (decl) == VAR_DECL ? "variable" : "function", 328 decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl)) 329 ? "defined locally" : "redeclared without dllimport attribute"); 330 331 XEXP (DECL_RTL (decl), 0) = newrtl; 332 333 DECL_DLLIMPORT_P (decl) = 0; 334 } 335} 336 337 338/* Return the length of a function name prefix 339 that starts with the character 'c'. */ 340 341static int 342sh_symbian_get_strip_length (int c) 343{ 344 /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */ 345 return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0; 346} 347 348/* Return a pointer to a function's name with any 349 and all prefix encodings stripped from it. */ 350 351const char * 352sh_symbian_strip_name_encoding (const char *name) 353{ 354 int skip; 355 356 while ((skip = sh_symbian_get_strip_length (*name))) 357 name += skip; 358 359 return name; 360} 361 362/* Add the named attribute to the given node. Copes with both DECLs and 363 TYPEs. Will only add the attribute if it is not already present. */ 364 365static void 366symbian_add_attribute (tree node, const char *attr_name) 367{ 368 tree attrs; 369 tree attr; 370 371 attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node); 372 373 if (lookup_attribute (attr_name, attrs) != NULL_TREE) 374 return; 375 376 attr = get_identifier (attr_name); 377 378 if (DECL_P (node)) 379 DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs); 380 else 381 TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs); 382 383#if SYMBIAN_DEBUG 384 fprintf (stderr, "propogate %s attribute", attr_name); 385 print_node_brief (stderr, " to", node, 0); 386 fprintf (stderr, "\n"); 387#endif 388} 389 390/* Handle a "dllimport" or "dllexport" attribute; 391 arguments as in struct attribute_spec.handler. */ 392 393tree 394sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args, 395 int flags, bool *no_add_attrs) 396{ 397 tree thunk; 398 tree node = *pnode; 399 const char *attr = IDENTIFIER_POINTER (name); 400 401 /* These attributes may apply to structure and union types being 402 created, but otherwise should pass to the declaration involved. */ 403 if (!DECL_P (node)) 404 { 405 if (flags & ((int) ATTR_FLAG_DECL_NEXT 406 | (int) ATTR_FLAG_FUNCTION_NEXT 407 | (int) ATTR_FLAG_ARRAY_NEXT)) 408 { 409 warning (OPT_Wattributes, "%qs attribute ignored", attr); 410 *no_add_attrs = true; 411 return tree_cons (name, args, NULL_TREE); 412 } 413 414 if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) 415 { 416 warning (OPT_Wattributes, "%qs attribute ignored", attr); 417 *no_add_attrs = true; 418 } 419 420 return NULL_TREE; 421 } 422 423 /* Report error on dllimport ambiguities 424 seen now before they cause any damage. */ 425 else if (is_attribute_p ("dllimport", name)) 426 { 427 if (TREE_CODE (node) == VAR_DECL) 428 { 429 if (DECL_INITIAL (node)) 430 { 431 error ("variable %q+D definition is marked dllimport", 432 node); 433 *no_add_attrs = true; 434 } 435 436 /* `extern' needn't be specified with dllimport. 437 Specify `extern' now and hope for the best. Sigh. */ 438 DECL_EXTERNAL (node) = 1; 439 /* Also, implicitly give dllimport'd variables declared within 440 a function global scope, unless declared static. */ 441 if (current_function_decl != NULL_TREE && ! TREE_STATIC (node)) 442 TREE_PUBLIC (node) = 1; 443 } 444 } 445 446 /* If the node is an overloaded constructor or destructor, then we must 447 make sure that the attribute is propagated along the overload chain, 448 as it is these overloaded functions which will be emitted, rather than 449 the user declared constructor itself. */ 450 if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE 451 && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node))) 452 { 453 tree overload; 454 455 for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload)) 456 { 457 tree node_args; 458 tree func_args; 459 tree function = OVL_CURRENT (overload); 460 461 if (! function 462 || ! DECL_P (function) 463 || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function)) 464 || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function))) 465 continue; 466 467 /* The arguments must match as well. */ 468 for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function); 469 node_args && func_args; 470 node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args)) 471 if (TREE_TYPE (node_args) != TREE_TYPE (func_args)) 472 break; 473 474 if (node_args || func_args) 475 { 476 /* We can ignore an extraneous __in_chrg arguments in the node. 477 GCC generated destructors, for example, will have this. */ 478 if ((node_args == NULL_TREE 479 || func_args != NULL_TREE) 480 && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0) 481 continue; 482 } 483 484 symbian_add_attribute (function, attr); 485 486 /* Propagate the attribute to any function thunks as well. */ 487 for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk)) 488 if (TREE_CODE (thunk) == FUNCTION_DECL) 489 symbian_add_attribute (thunk, attr); 490 } 491 } 492 493 if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node)) 494 { 495 /* Propagate the attribute to any thunks of this function. */ 496 for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk)) 497 if (TREE_CODE (thunk) == FUNCTION_DECL) 498 symbian_add_attribute (thunk, attr); 499 } 500 501 /* Report error if symbol is not accessible at global scope. */ 502 if (!TREE_PUBLIC (node) 503 && ( TREE_CODE (node) == VAR_DECL 504 || TREE_CODE (node) == FUNCTION_DECL)) 505 { 506 error ("external linkage required for symbol %q+D because of %qs attribute", 507 node, IDENTIFIER_POINTER (name)); 508 *no_add_attrs = true; 509 } 510 511#if SYMBIAN_DEBUG 512 print_node_brief (stderr, "mark node", node, 0); 513 fprintf (stderr, " as %s\n", attr); 514#endif 515 516 return NULL_TREE; 517} 518 519/* This code implements a specification for exporting the vtable and rtti of 520 classes that have members with the dllexport or dllexport attributes. 521 This specification is defined here: 522 523 http://www.armdevzone.com/EABI/exported_class.txt 524 525 Basically it says that a class's vtable and rtti should be exported if 526 the following rules apply: 527 528 - If it has any non-inline non-pure virtual functions, 529 at least one of these need to be declared dllimport 530 OR any of the constructors is declared dllimport. 531 532 AND 533 534 - The class has an inline constructor/destructor and 535 a key-function (placement of vtable uniquely defined) that 536 is defined in this translation unit. 537 538 The specification also says that for classes which will have their 539 vtables and rtti exported that their base class(es) might also need a 540 similar exporting if: 541 542 - Every base class needs to have its vtable & rtti exported 543 as well, if the following the conditions hold true: 544 + The base class has a non-inline declared non-pure virtual function 545 + The base class is polymorphic (has or inherits any virtual functions) 546 or the base class has any virtual base classes. */ 547 548/* Decide if a base class of a class should 549 also have its vtable and rtti exported. */ 550 551static void 552symbian_possibly_export_base_class (tree base_class) 553{ 554 VEC(tree,gc) *method_vec; 555 int len; 556 557 if (! (TYPE_CONTAINS_VPTR_P (base_class))) 558 return; 559 560 method_vec = CLASSTYPE_METHOD_VEC (base_class); 561 len = method_vec ? VEC_length (tree, method_vec) : 0; 562 563 for (;len --;) 564 { 565 tree member = VEC_index (tree, method_vec, len); 566 567 if (! member) 568 continue; 569 570 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member)) 571 { 572 if (TREE_CODE (member) != FUNCTION_DECL) 573 continue; 574 575 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member)) 576 continue; 577 578 if (! DECL_VIRTUAL_P (member)) 579 continue; 580 581 if (DECL_PURE_VIRTUAL_P (member)) 582 continue; 583 584 if (DECL_INLINE (member)) 585 continue; 586 587 break; 588 } 589 590 if (member) 591 break; 592 } 593 594 if (len < 0) 595 return; 596 597 /* FIXME: According to the spec this base class should be exported, but 598 a) how do we do this ? and 599 b) it does not appear to be necessary for compliance with the Symbian 600 OS which so far is the only consumer of this code. */ 601#if SYMBIAN_DEBUG 602 print_node_brief (stderr, "", base_class, 0); 603 fprintf (stderr, " EXPORTed [base class of exported class]\n"); 604#endif 605} 606 607/* Decide if a class needs its vtable and rtti exporting. */ 608 609static bool 610symbian_export_vtable_and_rtti_p (tree ctype) 611{ 612 bool inline_ctor_dtor; 613 bool dllimport_ctor_dtor; 614 bool dllimport_member; 615 tree binfo, base_binfo; 616 VEC(tree,gc) *method_vec; 617 tree key; 618 int i; 619 int len; 620 621 /* Make sure that we are examining a class... */ 622 if (TREE_CODE (ctype) != RECORD_TYPE) 623 { 624#if SYMBIAN_DEBUG 625 print_node_brief (stderr, "", ctype, 0); 626 fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n"); 627#endif 628 return false; 629 } 630 631 /* If the class does not have a key function it 632 does not need to have its vtable exported. */ 633 if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE) 634 { 635#if SYMBIAN_DEBUG 636 print_node_brief (stderr, "", ctype, 0); 637 fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n"); 638#endif 639 return false; 640 } 641 642 /* If the key fn has not been defined 643 then the class should not be exported. */ 644 if (! TREE_ASM_WRITTEN (key)) 645 { 646#if SYMBIAN_DEBUG 647 print_node_brief (stderr, "", ctype, 0); 648 fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n"); 649#endif 650 return false; 651 } 652 653 /* Check the class's member functions. */ 654 inline_ctor_dtor = false; 655 dllimport_ctor_dtor = false; 656 dllimport_member = false; 657 658 method_vec = CLASSTYPE_METHOD_VEC (ctype); 659 len = method_vec ? VEC_length (tree, method_vec) : 0; 660 661 for (;len --;) 662 { 663 tree member = VEC_index (tree, method_vec, len); 664 665 if (! member) 666 continue; 667 668 for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member)) 669 { 670 if (TREE_CODE (member) != FUNCTION_DECL) 671 continue; 672 673 if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member)) 674 { 675 if (DECL_INLINE (member) 676 /* Ignore C++ backend created inline ctors/dtors. */ 677 && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member) 678 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member))) 679 inline_ctor_dtor = true; 680 681 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member))) 682 dllimport_ctor_dtor = true; 683 } 684 else 685 { 686 if (DECL_PURE_VIRTUAL_P (member)) 687 continue; 688 689 if (! DECL_VIRTUAL_P (member)) 690 continue; 691 692 if (DECL_INLINE (member)) 693 continue; 694 695 if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member))) 696 dllimport_member = true; 697 } 698 } 699 } 700 701 if (! dllimport_member && ! dllimport_ctor_dtor) 702 { 703#if SYMBIAN_DEBUG 704 print_node_brief (stderr, "", ctype, 0); 705 fprintf (stderr, 706 " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n"); 707#endif 708 return false; 709 } 710 711 if (! inline_ctor_dtor) 712 { 713#if SYMBIAN_DEBUG 714 print_node_brief (stderr, "", ctype, 0); 715 fprintf (stderr, 716 " does NOT need to be EXPORTed [no inline ctor/dtor]\n"); 717#endif 718 return false; 719 } 720 721#if SYMBIAN_DEBUG 722 print_node_brief (stderr, "", ctype, 0); 723 fprintf (stderr, " DOES need to be EXPORTed\n"); 724#endif 725 726 /* Now we must check and possibly export the base classes. */ 727 for (i = 0, binfo = TYPE_BINFO (ctype); 728 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 729 symbian_possibly_export_base_class (BINFO_TYPE (base_binfo)); 730 731 return true; 732} 733 734/* Add the named attribute to a class and its vtable and rtti. */ 735 736static void 737symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name) 738{ 739 symbian_add_attribute (ctype, attr_name); 740 741 /* If the vtable exists then they need annotating as well. */ 742 if (CLASSTYPE_VTABLES (ctype)) 743 /* XXX - Do we need to annotate any vtables other than the primary ? */ 744 symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name); 745 746 /* If the rtti exists then it needs annotating as well. */ 747 if (TYPE_MAIN_VARIANT (ctype) 748 && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype))) 749 symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)), 750 attr_name); 751} 752 753/* Decide if a class needs to have an attribute because 754 one of its member functions has the attribute. */ 755 756static bool 757symbian_class_needs_attribute_p (tree ctype, const char *attribute_name) 758{ 759 VEC(tree,gc) *method_vec; 760 761 method_vec = CLASSTYPE_METHOD_VEC (ctype); 762 763 /* If the key function has the attribute then the class needs it too. */ 764 if (TYPE_POLYMORPHIC_P (ctype) 765 && method_vec 766 && lookup_attribute (attribute_name, 767 DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0)))) 768 return true; 769 770 /* Check the class's member functions. */ 771 if (TREE_CODE (ctype) == RECORD_TYPE) 772 { 773 unsigned int len; 774 775 len = method_vec ? VEC_length (tree, method_vec) : 0; 776 777 for (;len --;) 778 { 779 tree member = VEC_index (tree, method_vec, len); 780 781 if (! member) 782 continue; 783 784 for (member = OVL_CURRENT (member); 785 member; 786 member = OVL_NEXT (member)) 787 { 788 if (TREE_CODE (member) != FUNCTION_DECL) 789 continue; 790 791 if (DECL_PURE_VIRTUAL_P (member)) 792 continue; 793 794 if (! DECL_VIRTUAL_P (member)) 795 continue; 796 797 if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member))) 798 { 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; 806 } 807 } 808 } 809 } 810 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; 816} 817 818int 819symbian_import_export_class (tree ctype, int import_export) 820{ 821 const char *attr_name = NULL; 822 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) 827 { 828 case 1: attr_name = "dllexport"; break; 829 case -1: attr_name = "dllimport"; break; 830 default: break; 831 } 832 833 if (attr_name 834 && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype))) 835 { 836 if (symbian_class_needs_attribute_p (ctype, attr_name)) 837 symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name); 838 839 /* Classes can be forced to export their 840 vtable and rtti under certain conditions. */ 841 if (symbian_export_vtable_and_rtti_p (ctype)) 842 { 843 symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport"); 844 845 /* Make sure that the class and its vtable are exported. */ 846 import_export = 1; 847 848 if (CLASSTYPE_VTABLES (ctype)) 849 DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1; 850 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)) 855 { 856 tree class; 857 858 for (class = keyed_classes; class; class = TREE_CHAIN (class)) 859 if (class == ctype) 860 break; 861 862 if (class == NULL_TREE) 863 { 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); 869 } 870 } 871 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; 875 } 876 } 877 878 return import_export; 879} 880 881/* Dummy definition of this array for cc1 building purposes. */ 882tree cp_global_trees[CPTI_MAX] __attribute__((weak)); 883 884#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) 885 886/* Dummy version of this G++ function for building cc1. */ 887void lang_check_failed (const char *, int, const char *) __attribute__((weak)); 888 889void 890lang_check_failed (const char *file, int line, const char *function) 891{ 892 internal_error ("lang_* check: failed in %s, at %s:%d", 893 function, trim_filename (file), line); 894} 895#endif /* ENABLE_TREE_CHECKING */ 896