aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config.gcc7
-rw-r--r--gcc/config/sh/sh-protos.h14
-rw-r--r--gcc/config/sh/sh.c28
-rw-r--r--gcc/config/sh/symbian-post.h89
-rw-r--r--gcc/config/sh/symbian-pre.h48
-rw-r--r--gcc/config/sh/symbian.c906
-rw-r--r--gcc/config/sh/t-symbian35
-rw-r--r--gcc/doc/extend.texi60
8 files changed, 1164 insertions, 23 deletions
diff --git a/gcc/config.gcc b/gcc/config.gcc
index bc8fa23..26b4897 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1671,6 +1671,7 @@ s390x-ibm-tpf*)
tmake_file="t-slibgcc-elf-ver s390/t-crtstuff s390/t-tpf"
;;
sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
+sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
sh-*-linux* | sh[346lbe]*-*-linux* | \
sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
sh64-*-netbsd* | sh64l*-*-netbsd*)
@@ -1730,6 +1731,12 @@ sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
tm_file="${tm_file} sh/sh64.h"
extra_headers="shmedia.h ushmedia.h sshmedia.h"
;;
+ *-*-symbianelf*)
+ tmake_file="sh/t-symbian"
+ tm_file="sh/symbian-pre.h sh/little.h ${tm_file} sh/symbian-post.h"
+ extra_objs="symbian.o"
+ extra_parts="crt1.o crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o"
+ ;;
esac
# sed el/eb endian suffixes away to avoid confusion with sh[23]e
case `echo ${target} | sed 's/e[lb]-/-/'` in
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 05d694d..0d1733c 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -143,3 +143,17 @@ extern const char *sh_pch_valid_p (const void *data_p, size_t sz);
extern bool sh_promote_prototypes (tree);
#endif /* ! GCC_SH_PROTOS_H */
+
+#ifdef SYMBIAN
+extern bool sh_symbian_dllimport_name_p (const char *);
+extern const char * sh_symbian_strip_name_encoding (const char *);
+extern bool sh_symbian_dllexport_name_p (const char *);
+extern int symbian_import_export_class (tree, int);
+#ifdef TREE_CODE
+extern bool sh_symbian_dllexport_p (tree);
+extern tree sh_symbian_handle_dll_attribute (tree *, tree, tree, int, bool *);
+#ifdef RTX_CODE
+extern void sh_symbian_encode_section_info (tree, rtx, int);
+#endif
+#endif
+#endif /* SYMBIAN */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 11882dd..dc16c61 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -451,6 +451,17 @@ static tree sh_gimplify_va_arg_expr (tree, tree, tree *, tree *);
/* Return current register pressure for regmode. */
#define CURR_REGMODE_PRESSURE(MODE) curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
+#ifdef SYMBIAN
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO sh_symbian_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING sh_symbian_strip_name_encoding
+#undef TARGET_CXX_IMPORT_EXPORT_CLASS
+#define TARGET_CXX_IMPORT_EXPORT_CLASS symbian_import_export_class
+
+#endif /* SYMBIAN */
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Print the operand address in x to the stream. */
@@ -1431,6 +1442,12 @@ sh_file_start (void)
{
default_file_start ();
+#ifdef SYMBIAN
+ /* Declare the .directive section before it is used. */
+ fputs ("\t.section .directive, \"SM\", @progbits, 1\n", asm_out_file);
+ fputs ("\t.asciz \"#<SYMEDIT>#\\n\"\n", asm_out_file);
+#endif
+
if (TARGET_ELF)
/* We need to show the text section with the proper
attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
@@ -6950,6 +6967,17 @@ const struct attribute_spec sh_attribute_table[] =
{ "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
{ "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
{ "renesas", 0, 0, false, true, false, sh_handle_renesas_attribute },
+#ifdef SYMBIAN
+ /* Symbian support adds three new attributes:
+ dllexport - for exporting a function/variable that will live in a dll
+ dllimport - for importing a function/variable from a dll
+
+ Microsoft allows multiple declspecs in one __declspec, separating
+ them with spaces. We do NOT support this. Instead, use __declspec
+ multiple times. */
+ { "dllimport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute },
+ { "dllexport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute },
+#endif
{ NULL, 0, 0, false, false, false, NULL }
};
diff --git a/gcc/config/sh/symbian-post.h b/gcc/config/sh/symbian-post.h
new file mode 100644
index 0000000..b39262d
--- /dev/null
+++ b/gcc/config/sh/symbian-post.h
@@ -0,0 +1,89 @@
+/* Definitions for the Symbian OS running on an SH part.
+ This file is included after all the other target specific headers.
+
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by Red Hat.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION \
+ fputs (" (Renesas SH for Symbian OS)", stderr);
+
+#undef LINK_EMUL_PREFIX
+#define LINK_EMUL_PREFIX "shlsymbian"
+
+
+#define SYMBIAN_EXPORT_NAME(NAME,FILE,DECL) \
+ do \
+ { \
+ if ((DECL && sh_symbian_dllexport_p (DECL)) \
+ || sh_symbian_dllexport_name_p (NAME)) \
+ { \
+ fprintf ((FILE), "\t.pushsection .directive\n"); \
+ fprintf ((FILE), "\t.asciz \"EXPORT %s\\n\"\n", \
+ sh_symbian_strip_name_encoding (NAME)); \
+ fprintf ((FILE), "\t.popsection\n"); \
+ } \
+ } \
+ while (0)
+
+/* Output a function definition label. */
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
+ ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "function"); \
+ ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL ((FILE), (NAME)); \
+ } \
+ while (0)
+
+/* Output the label for an initialized variable. */
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ HOST_WIDE_INT size; \
+ \
+ SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
+ ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "object"); \
+ \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) \
+ && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE ((FILE), (NAME), size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL ((FILE), (NAME)); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE, NAME) \
+ do \
+ { \
+ asm_fprintf ((FILE), "%U%s", \
+ sh_symbian_strip_name_encoding (NAME)); \
+ } \
+ while (0)
diff --git a/gcc/config/sh/symbian-pre.h b/gcc/config/sh/symbian-pre.h
new file mode 100644
index 0000000..aa23535
--- /dev/null
+++ b/gcc/config/sh/symbian-pre.h
@@ -0,0 +1,48 @@
+/* Definitions for the Symbian OS running on an SH part.
+ This file is included before any other target specific headers.
+
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by Red Hat.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Enable Symbian specific code. */
+#define SYMBIAN 1
+
+/* Default to using the Renesas ABI. */
+#define TARGET_ABI_DEFAULT RENESAS_BIT
+
+/* Support the __declspec keyword by turning them into attributes.
+ We currently only support: naked, dllimport, and dllexport.
+ Note that the current way we do this may result in a collision with
+ predefined attributes later on. This can be solved by using one attribute,
+ say __declspec__, and passing args to it. The problem with that approach
+ is that args are not accumulated: each new appearance would clobber any
+ existing args. */
+#define SUBTARGET_CPP_SPEC "-D__declspec(x)=__attribute__((x))"
+
+/* Get tree.c to declare merge_dllimport_decl_attributes(). */
+#define TARGET_DLLIMPORT_DECL_ATTRIBUTES
+
+/* The Symbian OS currently does not support exception handling. */
+#define SUBTARGET_CC1PLUS_SPEC "-fno-exceptions"
+
+/* Create constructor/destructor sections without the writable flag.
+ Symbian puts them into the text segment and munges them later on. */
+#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"ax\",@progbits"
+#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"ax\",@progbits"
diff --git a/gcc/config/sh/symbian.c b/gcc/config/sh/symbian.c
new file mode 100644
index 0000000..33ab711
--- /dev/null
+++ b/gcc/config/sh/symbian.c
@@ -0,0 +1,906 @@
+/* Routines for GCC for a Symbian OS targeted SH backend.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by RedHat.
+ Most of this code is stolen from i386/winnt.c.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "output.h"
+#include "flags.h"
+#include "tree.h"
+#include "expr.h"
+#include "tm_p.h"
+#include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
+#include "toplev.h"
+
+/* Select the level of debugging information to display.
+ 0 for no debugging.
+ 1 for informative messages about decisions to add attributes
+ 2 for verbose information about what is being done. */
+#define SYMBIAN_DEBUG 0
+//#define SYMBIAN_DEBUG 1
+//#define SYMBIAN_DEBUG 2
+
+/* A unique character to encode declspec encoded objects. */
+#define SH_SYMBIAN_FLAG_CHAR "$"
+
+/* Unique strings to prefix exported and imported objects. */
+#define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
+#define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
+
+
+/* Return the type that we should use to determine if DECL is
+ imported or exported. */
+
+static tree
+sh_symbian_associated_type (tree decl)
+{
+ tree t = NULL_TREE;
+
+ if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
+ /* Methods now inherit their dllimport/dllexport attributes correctly
+ so there is no need to check their class. In fact it is wrong to
+ check their class since a method can remain unexported from an
+ exported class. */
+ return t;
+
+ /* Otherwise we can just take the DECL_CONTEXT as normal. */
+ if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+ t = DECL_CONTEXT (decl);
+
+ return t;
+}
+
+/* Return nonzero if DECL is a dllexport'd object. */
+
+bool
+sh_symbian_dllexport_p (tree decl)
+{
+ tree exp;
+
+ if ( TREE_CODE (decl) != VAR_DECL
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
+
+ exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
+
+ /* Class members get the dllexport status of their class. */
+ if (exp == NULL)
+ {
+ tree class = sh_symbian_associated_type (decl);
+
+ if (class)
+ exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
+ }
+#if SYMBIAN_DEBUG
+ if (exp)
+ {
+ print_node_brief (stderr, "dllexport:", decl, 0);
+ fprintf (stderr, "\n");
+ }
+ else
+#if SYMBIAN_DEBUG < 2
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+#endif
+ {
+ print_node_brief (stderr, "no dllexport:", decl, 0);
+ fprintf (stderr, "\n");
+ }
+#endif
+ return exp ? true : false;
+}
+
+/* Return nonzero if DECL is a dllimport'd object. */
+
+static bool
+sh_symbian_dllimport_p (tree decl)
+{
+ tree imp;
+
+ if ( TREE_CODE (decl) != VAR_DECL
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
+
+ imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
+ if (imp)
+ return true;
+
+ /* Class members get the dllimport status of their class. */
+ imp = sh_symbian_associated_type (decl);
+ if (! imp)
+ return false;
+
+ imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
+ if (!imp)
+ return false;
+
+ /* Don't mark defined functions as dllimport. If the definition itself
+ was marked with dllimport, then sh_symbian_handle_dll_attribute reports
+ an error. This handles the case when the definition overrides an
+ earlier declaration. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INITIAL (decl)
+ && !DECL_INLINE (decl))
+ {
+ /* Don't warn about artificial methods. */
+ if (!DECL_ARTIFICIAL (decl))
+ warning ("%H function '%D' is defined after prior declaration as dllimport: attribute ignored",
+ & DECL_SOURCE_LOCATION (decl), decl);
+ return false;
+ }
+
+ /* We ignore the dllimport attribute for inline member functions.
+ This differs from MSVC behavior which treats it like GNUC
+ 'extern inline' extension. */
+ else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
+ {
+ if (extra_warnings)
+ warning ("%Hinline function '%D' is declared as dllimport: attribute ignored.",
+ & DECL_SOURCE_LOCATION (decl), decl);
+ return false;
+ }
+
+ /* Don't allow definitions of static data members in dllimport
+ class. Just ignore the attribute for vtable data. */
+ else if (TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl)
+ && TREE_PUBLIC (decl)
+ && !DECL_EXTERNAL (decl))
+ {
+ if (!DECL_VIRTUAL_P (decl))
+ error ("%Hdefinition of static data member '%D' of dllimport'd class.",
+ & DECL_SOURCE_LOCATION (decl), decl);
+ return false;
+ }
+
+ /* Since we can't treat a pointer to a dllimport'd symbol as a
+ constant address, we turn off the attribute on C++ virtual
+ methods to allow creation of vtables using thunks. Don't mark
+ artificial methods either (in sh_symbian_associated_type, only
+ COMDAT artificial method get import status from class context). */
+ else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
+ && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
+ return false;
+
+ return true;
+}
+
+/* Return nonzero if SYMBOL is marked as being dllexport'd. */
+
+bool
+sh_symbian_dllexport_name_p (const char *symbol)
+{
+ return strncmp (DLL_EXPORT_PREFIX, symbol,
+ strlen (DLL_EXPORT_PREFIX)) == 0;
+}
+
+/* Return nonzero if SYMBOL is marked as being dllimport'd. */
+
+
+bool
+sh_symbian_dllimport_name_p (const char *symbol)
+{
+ return strncmp (DLL_IMPORT_PREFIX, symbol,
+ strlen (DLL_IMPORT_PREFIX)) == 0;
+}
+
+/* Mark a DECL as being dllexport'd.
+ Note that we override the previous setting (eg: dllimport). */
+
+static void
+sh_symbian_mark_dllexport (tree decl)
+{
+ const char *oldname;
+ char *newname;
+ rtx rtlname;
+ tree idp;
+
+ rtlname = XEXP (DECL_RTL (decl), 0);
+
+ if (GET_CODE (rtlname) == SYMBOL_REF)
+ oldname = XSTR (rtlname, 0);
+ else if (GET_CODE (rtlname) == MEM
+ && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
+ oldname = XSTR (XEXP (rtlname, 0), 0);
+ else
+ abort ();
+
+ if (sh_symbian_dllimport_name_p (oldname))
+ {
+ /* Remove DLL_IMPORT_PREFIX.
+ Note - we do not issue a warning here. In Symbian's environment it
+ is legitimate for a prototype to be marked as dllimport and the
+ corresponding defintion to be marked as dllexport. The prototypes
+ are in headers used everywhere and the defintion is in a translation
+ unit which has included the header in order to ensure argument
+ correctness. */
+ oldname += strlen (DLL_IMPORT_PREFIX);
+ DECL_NON_ADDR_CONST_P (decl) = 0;
+ }
+ else if (sh_symbian_dllexport_name_p (oldname))
+ return; /* Already done. */
+
+ newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
+ sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
+
+ /* We pass newname through get_identifier to ensure it has a unique
+ address. RTL processing can sometimes peek inside the symbol ref
+ and compare the string's addresses to see if two symbols are
+ identical. */
+ idp = get_identifier (newname);
+
+ XEXP (DECL_RTL (decl), 0) =
+ gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
+}
+
+/* Mark a DECL as being dllimport'd. */
+
+static void
+sh_symbian_mark_dllimport (tree decl)
+{
+ const char *oldname;
+ char *newname;
+ tree idp;
+ rtx rtlname;
+ rtx newrtl;
+
+ rtlname = XEXP (DECL_RTL (decl), 0);
+
+ if (GET_CODE (rtlname) == SYMBOL_REF)
+ oldname = XSTR (rtlname, 0);
+ else if (GET_CODE (rtlname) == MEM
+ && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
+ oldname = XSTR (XEXP (rtlname, 0), 0);
+ else
+ abort ();
+
+ if (sh_symbian_dllexport_name_p (oldname))
+ {
+ error ("`%s' declared as both exported to and imported from a DLL",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ }
+ else if (sh_symbian_dllimport_name_p (oldname))
+ {
+ /* Already done, but do a sanity check to prevent assembler errors. */
+ if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
+ error ("%Hfailure in redeclaration of '%D': dllimport'd symbol lacks external linkage.",
+ &DECL_SOURCE_LOCATION (decl), decl);
+ }
+ else
+ {
+ newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
+ sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
+
+ /* We pass newname through get_identifier to ensure it has a unique
+ address. RTL processing can sometimes peek inside the symbol ref
+ and compare the string's addresses to see if two symbols are
+ identical. */
+ idp = get_identifier (newname);
+ newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
+ XEXP (DECL_RTL (decl), 0) = newrtl;
+ }
+}
+
+void
+sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
+{
+ default_encode_section_info (decl, rtl, first);
+
+ /* Mark the decl so we can tell from the rtl whether
+ the object is dllexport'd or dllimport'd. */
+ if (sh_symbian_dllexport_p (decl))
+ sh_symbian_mark_dllexport (decl);
+ else if (sh_symbian_dllimport_p (decl))
+ sh_symbian_mark_dllimport (decl);
+ /* It might be that DECL has already been marked as dllimport, but a
+ subsequent definition nullified that. The attribute is gone but
+ DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
+ that. Ditto for the DECL_NON_ADDR_CONST_P flag. */
+ else if ( (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && DECL_RTL (decl) != NULL_RTX
+ && GET_CODE (DECL_RTL (decl)) == MEM
+ && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
+ && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
+ && sh_symbian_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
+ {
+ const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
+ /* Remove DLL_IMPORT_PREFIX. */
+ tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
+ rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
+
+ warning ("%H%s '%D' %s after being referenced with dllimport linkage.",
+ & DECL_SOURCE_LOCATION (decl),
+ TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
+ decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
+ ? "defined locally" : "redeclared without dllimport attribute");
+
+ XEXP (DECL_RTL (decl), 0) = newrtl;
+
+ DECL_NON_ADDR_CONST_P (decl) = 0;
+ }
+}
+
+
+/* Return the length of a function name prefix
+ that starts with the character 'c'. */
+
+static int
+sh_symbian_get_strip_length (int c)
+{
+ /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */
+ return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
+}
+
+/* Return a pointer to a function's name with any
+ and all prefix encodings stripped from it. */
+
+const char *
+sh_symbian_strip_name_encoding (const char *name)
+{
+ int skip;
+
+ while ((skip = sh_symbian_get_strip_length (*name)))
+ name += skip;
+
+ return name;
+}
+
+/* Add the named attribute to the given node. Copes with both DECLs and
+ TYPEs. Will only add the attribute if it is not already present. */
+
+static void
+symbian_add_attribute (tree node, const char *attr_name)
+{
+ tree attrs;
+ tree attr;
+
+ attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
+
+ if (lookup_attribute (attr_name, attrs) != NULL_TREE)
+ return;
+
+ attr = get_identifier (attr_name);
+
+ (DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node))
+ = tree_cons (attr, NULL_TREE, attrs);
+
+#if SYMBIAN_DEBUG
+ fprintf (stderr, "propogate %s attribute", attr_name);
+ print_node_brief (stderr, " to", node, 0);
+ fprintf (stderr, "\n");
+#endif
+}
+
+/* Handle a "dllimport" or "dllexport" attribute;
+ arguments as in struct attribute_spec.handler. */
+
+tree
+sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ tree thunk;
+ tree node = *pnode;
+ const char *attr = IDENTIFIER_POINTER (name);
+
+ /* These attributes may apply to structure and union types being
+ created, but otherwise should pass to the declaration involved. */
+ if (!DECL_P (node))
+ {
+ if (flags & ((int) ATTR_FLAG_DECL_NEXT
+ | (int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_ARRAY_NEXT))
+ {
+ warning ("`%s' attribute ignored", attr);
+ *no_add_attrs = true;
+ return tree_cons (name, args, NULL_TREE);
+ }
+
+ if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
+ {
+ warning ("`%s' attribute ignored", attr);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Report error on dllimport ambiguities
+ seen now before they cause any damage. */
+ else if (is_attribute_p ("dllimport", name))
+ {
+ if (TREE_CODE (node) == VAR_DECL)
+ {
+ if (DECL_INITIAL (node))
+ {
+ error ("%Hvariable `%D' definition is marked dllimport.",
+ & DECL_SOURCE_LOCATION (node), node);
+ *no_add_attrs = true;
+ }
+
+ /* `extern' needn't be specified with dllimport.
+ Specify `extern' now and hope for the best. Sigh. */
+ DECL_EXTERNAL (node) = 1;
+ /* Also, implicitly give dllimport'd variables declared within
+ a function global scope, unless declared static. */
+ if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
+ TREE_PUBLIC (node) = 1;
+ }
+ }
+
+ /* If the node is an overloaded constructor or desctructor, then we must
+ make sure that the attribute is propogated along the overload chain,
+ as it is these overloaded functions which will be emitted, rather than
+ the user declared constructor itself. */
+ if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
+ && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
+ {
+ tree overload;
+
+ for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
+ {
+ tree node_args;
+ tree func_args;
+ tree function = OVL_CURRENT (overload);
+
+ if (! function
+ || ! DECL_P (function)
+ || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
+ || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function)))
+ continue;
+
+ /* The arguments must match as well. */
+ for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
+ node_args && func_args;
+ node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
+ if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
+ break;
+
+ if (node_args || func_args)
+ {
+ /* We can ignore an extraneous __in_chrg arguments in the node.
+ GCC generated destructors, for example, will have this. */
+ if ((node_args == NULL_TREE
+ || func_args != NULL_TREE)
+ && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
+ continue;
+ }
+
+ symbian_add_attribute (function, attr);
+
+ /* Propogate the attribute to any function thunks as well. */
+ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+ if (TREE_CODE (thunk) == FUNCTION_DECL)
+ symbian_add_attribute (thunk, attr);
+ }
+ }
+
+ if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
+ {
+ /* Propogate the attribute to any thunks of this function. */
+ for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
+ if (TREE_CODE (thunk) == FUNCTION_DECL)
+ symbian_add_attribute (thunk, attr);
+ }
+
+ /* Report error if symbol is not accessible at global scope. */
+ if (!TREE_PUBLIC (node)
+ && ( TREE_CODE (node) == VAR_DECL
+ || TREE_CODE (node) == FUNCTION_DECL))
+ {
+ error ("%Hexternal linkage required for symbol '%D' because of '%s' attribute.",
+ & DECL_SOURCE_LOCATION (node), node, IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "mark node", node, 0);
+ fprintf (stderr, " as %s\n", attr);
+#endif
+
+ return NULL_TREE;
+}
+
+/* This code implements a specification for exporting the vtable and rtti of
+ classes that have members with the dllexport or dllexport attributes.
+ This specification is defined here:
+
+ http://www.armdevzone.com/EABI/exported_class.txt
+
+ Basically it says that a class's vtable and rtti should be exported if
+ the following rules apply:
+
+ - If it has any non-inline non-pure virtual functions,
+ at least one of these need to be declared dllimport
+ OR any of the constructors is declared dllimport.
+
+ AND
+
+ - The class has an inline constructor/destructor and
+ a key-function (placement of vtable uniquely defined) that
+ is defined in this translation unit.
+
+ The specification also says that for classes which will have their
+ vtables and rtti exported that their base class(es) might also need a
+ similar exporting if:
+
+ - Every base class needs to have its vtable & rtti exported
+ as well, if the following the conditions hold true:
+ + The base class has a non-inline declared non-pure virtual function
+ + The base class is polymorphic (has or inherits any virtual functions)
+ or the base class has any virtual base classes. */
+
+/* Decide if a base class of a class should
+ also have its vtable and rtti exported. */
+
+static void
+symbian_possibly_export_base_class (tree base_class)
+{
+ tree methods;
+ int len;
+
+ if (! (TYPE_POLYMORPHIC_P (base_class)
+ || TYPE_USES_VIRTUAL_BASECLASSES (base_class)))
+ return;
+
+ methods = CLASSTYPE_METHOD_VEC (base_class);
+ len = methods ? TREE_VEC_LENGTH (methods) : 0;
+
+ for (;len --;)
+ {
+ tree member = TREE_VEC_ELT (methods, len);
+
+ if (! member)
+ continue;
+
+ for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
+ {
+ if (TREE_CODE (member) != FUNCTION_DECL)
+ continue;
+
+ if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
+ continue;
+
+ if (! DECL_VIRTUAL_P (member))
+ continue;
+
+ if (DECL_PURE_VIRTUAL_P (member))
+ continue;
+
+ if (DECL_INLINE (member))
+ continue;
+
+ break;
+ }
+
+ if (member)
+ break;
+ }
+
+ if (len < 0)
+ return;
+
+ /* FIXME: According to the spec this base class should be exported, but
+ a) how do we do this ? and
+ b) it does not appear to be necessary for compliance with the Symbian
+ OS which so far is the only consumer of this code. */
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", base_class, 0);
+ fprintf (stderr, " EXPORTed [base class of exported class]\n");
+#endif
+}
+
+/* Decide if a class needs its vtable and rtti exporting. */
+
+static bool
+symbian_export_vtable_and_rtti_p (tree ctype)
+{
+ bool inline_ctor_dtor;
+ bool dllimport_ctor_dtor;
+ bool dllimport_member;
+ tree binfos;
+ tree methods;
+ tree key;
+ int len;
+
+ /* Make sure that we are examining a class... */
+ if (TREE_CODE (ctype) != RECORD_TYPE)
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
+#endif
+ return false;
+ }
+
+ /* If the class does not have a key function it
+ does not need to have its vtable exported. */
+ if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
+#endif
+ return false;
+ }
+
+ /* If the key fn has not been defined
+ then the class should not be exported. */
+ if (! TREE_ASM_WRITTEN (key))
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
+#endif
+ return false;
+ }
+
+ /* Check the class's member functions. */
+ inline_ctor_dtor = false;
+ dllimport_ctor_dtor = false;
+ dllimport_member = false;
+
+ methods = CLASSTYPE_METHOD_VEC (ctype);
+ len = methods ? TREE_VEC_LENGTH (methods) : 0;
+
+ for (;len --;)
+ {
+ tree member = TREE_VEC_ELT (methods, len);
+
+ if (! member)
+ continue;
+
+ for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
+ {
+ if (TREE_CODE (member) != FUNCTION_DECL)
+ continue;
+
+ if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
+ {
+ if (DECL_INLINE (member)
+ /* Ignore C++ backend created inline ctors/dtors. */
+ && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
+ || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
+ inline_ctor_dtor = true;
+
+ if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
+ dllimport_ctor_dtor = true;
+ }
+ else
+ {
+ if (DECL_PURE_VIRTUAL_P (member))
+ continue;
+
+ if (! DECL_VIRTUAL_P (member))
+ continue;
+
+ if (DECL_INLINE (member))
+ continue;
+
+ if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
+ dllimport_member = true;
+ }
+ }
+ }
+
+ if (! dllimport_member && ! dllimport_ctor_dtor)
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr,
+ " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
+#endif
+ return false;
+ }
+
+ if (! inline_ctor_dtor)
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr,
+ " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
+#endif
+ return false;
+ }
+
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr, " DOES need to be EXPORTed\n");
+#endif
+
+ /* Now we must check and possibly export the base classes. */
+ binfos = BINFO_BASE_BINFOS (TYPE_BINFO (ctype));
+ len = BINFO_N_BASE_BINFOS (TYPE_BINFO (ctype));
+
+ for (; len --;)
+ {
+ tree base_binfo;
+ tree basetype;
+
+ /* Figure out which base we're looking at. */
+ base_binfo = TREE_VEC_ELT (binfos, len);
+ basetype = TREE_TYPE (base_binfo);
+
+ symbian_possibly_export_base_class (basetype);
+ }
+
+ return true;
+}
+
+/* Add the named attribute to a class and its vtable and rtti. */
+
+static void
+symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
+{
+ symbian_add_attribute (ctype, attr_name);
+
+ /* If the vtable exists then they need annotating as well. */
+ if (CLASSTYPE_VTABLES (ctype))
+ /* XXX - Do we need to annotate any vtables other than the primary ? */
+ symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
+
+ /* If the rtti exists then it needs annotating as well. */
+ if (TYPE_MAIN_VARIANT (ctype)
+ && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
+ symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
+ attr_name);
+}
+
+/* Decide if a class needs to have an attribute because
+ one of its member functions has the attribute. */
+
+static bool
+symbian_class_needs_attribute_p (tree ctype, const char *attribute_name)
+{
+ /* If the key function has the attribute then the class needs it too. */
+ if (TYPE_POLYMORPHIC_P (ctype)
+ && CLASSTYPE_KEY_METHOD (ctype)
+ && lookup_attribute (attribute_name,
+ DECL_ATTRIBUTES (CLASSTYPE_KEY_METHOD (ctype))))
+ return true;
+
+ /* Check the class's member functions. */
+ if (TREE_CODE (ctype) == RECORD_TYPE)
+ {
+ tree methods = CLASSTYPE_METHOD_VEC (ctype);
+ unsigned int len = methods ? TREE_VEC_LENGTH (methods) : 0;
+
+ for (;len --;)
+ {
+ tree member = TREE_VEC_ELT (methods, len);
+
+ if (! member)
+ continue;
+
+ for (member = OVL_CURRENT (member);
+ member;
+ member = OVL_NEXT (member))
+ {
+ if (TREE_CODE (member) != FUNCTION_DECL)
+ continue;
+
+ if (DECL_PURE_VIRTUAL_P (member))
+ continue;
+
+ if (! DECL_VIRTUAL_P (member))
+ continue;
+
+ if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr, " inherits %s because", attribute_name);
+ print_node_brief (stderr, "", member, 0);
+ fprintf (stderr, " has it.\n");
+#endif
+ return true;
+ }
+ }
+ }
+ }
+
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "", ctype, 0);
+ fprintf (stderr, " does not inherit %s\n", attribute_name);
+#endif
+ return false;
+}
+
+int
+symbian_import_export_class (tree ctype, int import_export)
+{
+ const char *attr_name = NULL;
+
+ /* If we are exporting the class but it does not have the dllexport
+ attribute then we may need to add it. Similarly imported classes
+ may need the dllimport attribute. */
+ switch (import_export)
+ {
+ case 1: attr_name = "dllexport"; break;
+ case -1: attr_name = "dllimport"; break;
+ default: break;
+ }
+
+ if (attr_name
+ && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
+ {
+ if (symbian_class_needs_attribute_p (ctype, attr_name))
+ symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
+
+ /* Classes can be forced to export their
+ vtable and rtti under certain conditions. */
+ if (symbian_export_vtable_and_rtti_p (ctype))
+ {
+ symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
+
+ /* Make sure that the class and its vtable are exported. */
+ import_export = 1;
+
+ if (CLASSTYPE_VTABLES (ctype))
+ DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
+
+ /* Check to make sure that if the class has a key method that
+ it is now on the list of keyed classes. That way its vtable
+ will be emitted. */
+ if (CLASSTYPE_KEY_METHOD (ctype))
+ {
+ tree class;
+
+ for (class = keyed_classes; class; class = TREE_CHAIN (class))
+ if (class == ctype)
+ break;
+
+ if (class == NULL_TREE)
+ {
+#if SYMBIAN_DEBUG
+ print_node_brief (stderr, "Add node", ctype, 0);
+ fprintf (stderr, " to the keyed classes list\n");
+#endif
+ keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
+ }
+ }
+
+ /* Make sure that the typeinfo will be emitted as well. */
+ if (CLASS_TYPE_P (ctype))
+ TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
+ }
+ }
+
+ return import_export;
+}
+
+/* Dummy defintion of this array for cc1 building purposes. */
+tree cp_global_trees[CPTI_MAX] __attribute__((weak));
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Dummy version of this G++ function for building cc1. */
+void lang_check_failed (const char *, int, const char *) __attribute__((weak));
+
+void
+lang_check_failed (const char *file, int line, const char *function)
+{
+ internal_error ("lang_* check: failed in %s, at %s:%d",
+ function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
diff --git a/gcc/config/sh/t-symbian b/gcc/config/sh/t-symbian
new file mode 100644
index 0000000..494029f
--- /dev/null
+++ b/gcc/config/sh/t-symbian
@@ -0,0 +1,35 @@
+LIB1ASMSRC = sh/lib1funcs.asm
+LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
+ _movstr_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
+ $(LIB1ASMFUNCS_CACHE)
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
+$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
+$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
+
+$(out_object_file): gt-sh.h
+gt-sh.h : s-gtype ; @true
+
+symbian.o: $(srcdir)/config/sh/symbian.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/symbian.c
+
+
+# Local Variables:
+# mode: Makefile
+# End:
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 4f9b9d9..1df0221 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2009,10 +2009,11 @@ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
@item dllexport
@cindex @code{__declspec(dllexport)}
-On Microsoft Windows targets the @code{dllexport} attribute causes the
-compiler to provide a global pointer to a pointer in a dll, so that it
-can be referenced with the @code{dllimport} attribute. The pointer name
-is formed by combining @code{_imp__} and the function or variable name.
+On Microsoft Windows targets and Symbian targets the @code{dllexport}
+attribute causes the compiler to provide a global pointer to a pointer
+in a dll, so that it can be referenced with the @code{dllimport}
+attribute. The pointer name is formed by combining @code{_imp__} and
+the function or variable name.
Currently, the @code{dllexport}attribute is ignored for inlined
functions, but export can be forced by using the
@@ -2024,21 +2025,24 @@ member functions and static data members as exports. Static consts
initialized in-class are not marked unless they are also defined
out-of-class.
-On cygwin, mingw and arm-pe targets, @code{__declspec(dllexport)} is
-recognized as a synonym for @code{__attribute__ ((dllexport))} for
-compatibility with other Microsoft Windows compilers.
+On cygwin, mingw, arm-pe and sh-symbianelf targets,
+@code{__declspec(dllexport)} is recognized as a synonym for
+@code{__attribute__ ((dllexport))} for compatibility with other
+Microsoft Windows and Symbian compilers.
-Alternative methods for including the symbol in the dll's export table
-are to use a .def file with an @code{EXPORTS} section or, with GNU ld,
-using the @option{--export-all} linker flag.
+For Microsoft Windows targets there are alternative methods for
+including the symbol in the dll's export table such as using a
+@file{.def} file with an @code{EXPORTS} section or, with GNU ld, using
+the @option{--export-all} linker flag.
@item dllimport
@cindex @code{__declspec(dllimport)}
-On Microsoft Windows targets, the @code{dllimport} attribute causes the
-compiler to reference a function or variable via a global pointer to a
-pointer that is set up by the Microsoft Windows dll library. The pointer
-name is formed by combining @code{_imp__} and the function or variable
-name. The attribute implies @code{extern} storage.
+On Microsoft Windows and Symbian targets, the @code{dllimport}
+attribute causes the compiler to reference a function or variable via
+a global pointer to a pointer that is set up by the Microsoft Windows
+dll library. The pointer name is formed by combining @code{_imp__} and
+the function or variable name. The attribute implies @code{extern}
+storage.
Currently, the attribute is ignored for inlined functions. If the
attribute is applied to a symbol @emph{definition}, an error is reported.
@@ -2052,15 +2056,25 @@ member functions and static data members as imports. However, the
attribute is ignored for virtual methods to allow creation of vtables
using thunks.
-On cygwin, mingw and arm-pe targets, @code{__declspec(dllimport)} is
-recognized as a synonym for @code{__attribute__ ((dllimport))} for
-compatibility with other Microsoft Windows compilers.
+For Symbian targets the @code{dllimport} attribute also has another
+affect - it can cause the vtable and run-time type information for a
+class to be exported. This happens when the class has a dllimport'ed
+constructor or a non-inline, non-pure virtual function and, for either
+of those two conditions, the class also has a inline constructor or
+destructor and has a key function that is defined in the current
+translation unit.
-The use of the @code{dllimport} attribute on functions is not necessary,
-but provides a small performance benefit by eliminating a thunk in the
-dll. The use of the @code{dllimport} attribute on imported variables was
-required on older versions of GNU ld, but can now be avoided by passing
-the @option{--enable-auto-import} switch to ld. As with functions, using
+On cygwin, mingw, arm-pe sh-symbianelf targets,
+@code{__declspec(dllimport)} is recognized as a synonym for
+@code{__attribute__ ((dllimport))} for compatibility with other
+Microsoft Windows and Symbian compilers.
+
+For Microsoft Windows based targets the use of the @code{dllimport}
+attribute on functions is not necessary, but provides a small
+performance benefit by eliminating a thunk in the dll. The use of the
+@code{dllimport} attribute on imported variables was required on older
+versions of GNU ld, but can now be avoided by passing the
+@option{--enable-auto-import} switch to ld. As with functions, using
the attribute for a variable eliminates a thunk in the dll.
One drawback to using this attribute is that a pointer to a function or