aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2009-09-30 07:27:28 +0000
committerNick Clifton <nickc@gcc.gnu.org>2009-09-30 07:27:28 +0000
commit3c8348d376afad91fb9f89f14960af14e8cd5e77 (patch)
treea07773b7f99167050e2f054029c205c70e6e0dec /gcc
parent08a4a761ebe388e1b231eabd6f8e7e155d10b222 (diff)
downloadgcc-3c8348d376afad91fb9f89f14960af14e8cd5e77.zip
gcc-3c8348d376afad91fb9f89f14960af14e8cd5e77.tar.gz
gcc-3c8348d376afad91fb9f89f14960af14e8cd5e77.tar.bz2
config.gcc (sh-symbianelf): Replace definition of extra_objs with separate definitions of c_target_objs and...
* config.gcc (sh-symbianelf): Replace definition of extra_objs with separate definitions of c_target_objs and cxx_target_objs. * config/sh/t-sh: Add rules to build symbian-cxx.o, symbian-c.o and symbian-base.o. * config/sh/sh.c (TARGET_CXX_INPUT_EXPORT_CLASS): Use sh_symbian_import_export_class. * config/sh/sh-protos.h: Fix names of exported symbian functions. * config/sh/symbian.c: Delete, moving code into... * config/sh/symbian-base.c: ... here * config/sh/symbian-c.c: ... and here * config/sh/symbian-cxx.c: ... and here. From-SVN: r152323
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config.gcc3
-rw-r--r--gcc/config/sh/sh-protos.h8
-rw-r--r--gcc/config/sh/sh-symbian.h42
-rw-r--r--gcc/config/sh/sh.c2
-rw-r--r--gcc/config/sh/symbian-base.c244
-rw-r--r--gcc/config/sh/symbian-c.c181
-rw-r--r--gcc/config/sh/symbian-cxx.c (renamed from gcc/config/sh/symbian.c)744
-rw-r--r--gcc/config/sh/symbian-post.h4
-rw-r--r--gcc/config/sh/t-symbian22
10 files changed, 768 insertions, 496 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a14b81c..0c6ebdc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2009-09-30 Nick Clifton <nickc@redhat.com>
+
+ * config.gcc (sh-symbianelf): Replace definition of extra_objs
+ with separate definitions of c_target_objs and cxx_target_objs.
+ * config/sh/t-sh: Add rules to build symbian-cxx.o, symbian-c.o
+ and symbian-base.o.
+ * config/sh/sh.c (TARGET_CXX_INPUT_EXPORT_CLASS): Use
+ sh_symbian_import_export_class.
+ * config/sh/sh-protos.h: Fix names of exported symbian functions.
+ * config/sh/symbian.c: Delete, moving code into...
+ * config/sh/symbian-base.c: ... here
+ * config/sh/symbian-c.c: ... and here
+ * config/sh/symbian-cxx.c: ... and here.
+
2009-09-30 Uros Bizjak <ubizjak@gmail.com>
PR target/22093
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 6351aa5..1b0194b 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2184,7 +2184,8 @@ sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
*-*-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"
+ c_target_objs="symbian-base.o symbian-c.o"
+ cxx_target_objs="symbian-base.o symbian-cxx.o"
extra_parts="crt1.o crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o"
;;
*-*-elf*)
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index f61c5d5..8157221 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -183,15 +183,15 @@ extern bool sh_hard_regno_mode_ok (unsigned int, enum machine_mode);
#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);
+extern bool sh_symbian_is_dllexported_name (const char *);
#ifdef TREE_CODE
-extern bool sh_symbian_dllexport_p (tree);
+extern bool sh_symbian_is_dllexported (tree);
+extern int sh_symbian_import_export_class (tree, int);
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-symbian.h b/gcc/config/sh/sh-symbian.h
new file mode 100644
index 0000000..2e37d2b
--- /dev/null
+++ b/gcc/config/sh/sh-symbian.h
@@ -0,0 +1,42 @@
+/* header file for GCC for a Symbian OS targeted SH backend.
+ Copyright (C) 2004, 2005, 2007, 2009 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 3, 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 COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* 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."
+
+/* 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 */
+
+/* Functions exported from symbian-base.c. */
+extern tree sh_symbian_associated_type (tree);
+
+/* Functions exported from symbian-[c|c++].c. */
+extern bool sh_symbian_is_dllimported (tree);
+
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index df03c14..679cf11 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -503,7 +503,7 @@ static const struct attribute_spec sh_attribute_table[] =
#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
+#define TARGET_CXX_IMPORT_EXPORT_CLASS sh_symbian_import_export_class
#endif /* SYMBIAN */
diff --git a/gcc/config/sh/symbian-base.c b/gcc/config/sh/symbian-base.c
new file mode 100644
index 0000000..624c6fc
--- /dev/null
+++ b/gcc/config/sh/symbian-base.c
@@ -0,0 +1,244 @@
+/* Routines for GCC for a Symbian OS targeted SH backend, shared by
+ both the C and C++ compilers.
+ Copyright (C) 2004, 2005, 2007, 2009 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 3, 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 COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#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 "toplev.h"
+#include "sh-symbian.h"
+
+/* Return nonzero if SYMBOL is marked as being dllexport'd. */
+
+bool
+sh_symbian_is_dllexported_name (const char *symbol)
+{
+ return strncmp (DLL_EXPORT_PREFIX, symbol,
+ strlen (DLL_EXPORT_PREFIX)) == 0;
+}
+
+/* Return nonzero if SYMBOL is marked as being dllimport'd. */
+
+static bool
+sh_symbian_is_dllimported_name (const char *symbol)
+{
+ return strncmp (DLL_IMPORT_PREFIX, symbol,
+ strlen (DLL_IMPORT_PREFIX)) == 0;
+}
+
+/* Return nonzero if DECL is a dllexport'd object. */
+
+bool
+sh_symbian_is_dllexported (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;
+}
+
+/* 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 (MEM_P (rtlname))
+ rtlname = XEXP (rtlname, 0);
+ gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+ oldname = XSTR (rtlname, 0);
+
+ if (sh_symbian_is_dllexported_name (oldname))
+ {
+ error ("%qE declared as both exported to and imported from a DLL",
+ DECL_NAME (decl));
+ }
+ else if (sh_symbian_is_dllimported_name (oldname))
+ {
+ /* Already done, but do a sanity check to prevent assembler errors. */
+ if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
+ error ("failure in redeclaration of %q+D: dllimport'd symbol lacks external linkage",
+ decl);
+ }
+ else
+ {
+ newname = (char *) 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;
+ }
+}
+
+/* Mark a DECL as being dllexport'd.
+ Note that we override the previous setting (e.g.: 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 (MEM_P (rtlname))
+ rtlname = XEXP (rtlname, 0);
+ gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+ oldname = XSTR (rtlname, 0);
+
+ if (sh_symbian_is_dllimported_name (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 definition to be marked as dllexport. The prototypes
+ are in headers used everywhere and the definition is in a translation
+ unit which has included the header in order to ensure argument
+ correctness. */
+ oldname += strlen (DLL_IMPORT_PREFIX);
+ DECL_DLLIMPORT_P (decl) = 0;
+ }
+ else if (sh_symbian_is_dllexported_name (oldname))
+ return; /* Already done. */
+
+ newname = (char *) 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));
+}
+
+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_is_dllexported (decl))
+ sh_symbian_mark_dllexport (decl);
+ else if (sh_symbian_is_dllimported (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_DLLIMPORT_P flag. */
+ else if ( (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && DECL_RTL (decl) != NULL_RTX
+ && MEM_P (DECL_RTL (decl))
+ && MEM_P (XEXP (DECL_RTL (decl), 0))
+ && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
+ && sh_symbian_is_dllimported_name (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 (0, "%s %q+D %s after being referenced with dllimport linkage",
+ 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_DLLIMPORT_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;
+}
+
diff --git a/gcc/config/sh/symbian-c.c b/gcc/config/sh/symbian-c.c
new file mode 100644
index 0000000..4fda0ae
--- /dev/null
+++ b/gcc/config/sh/symbian-c.c
@@ -0,0 +1,181 @@
+/* Routines for C compiler part of GCC for a Symbian OS targeted SH backend.
+ Copyright (C) 2004, 2005, 2007, 2009 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 3, 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 COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#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 "toplev.h"
+#include "sh-symbian.h"
+
+
+/* Return the type that we should use to determine if DECL is
+ imported or exported. */
+
+tree
+sh_symbian_associated_type (tree decl)
+{
+ tree t = NULL_TREE;
+
+ /* 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 dllimport'd object. */
+
+bool
+sh_symbian_is_dllimported (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_DECLARED_INLINE_P (decl))
+ {
+ warning (OPT_Wattributes, "function %q+D is defined after prior "
+ "declaration as dllimport: attribute ignored",
+ 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))
+ {
+ error ("definition of static data member %q+D of dllimport'd class",
+ decl);
+ return false;
+ }
+
+ return true;
+}
+
+/* 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 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 (OPT_Wattributes, "%qs 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 (OPT_Wattributes, "%qs 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 ("variable %q+D definition is marked dllimport",
+ 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;
+ }
+ }
+
+ /* 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 ("external linkage required for symbol %q+D because of %qE attribute",
+ node, 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;
+}
+
+int
+sh_symbian_import_export_class (tree ctype ATTRIBUTE_UNUSED, int import_export)
+{
+ return import_export;
+}
diff --git a/gcc/config/sh/symbian.c b/gcc/config/sh/symbian-cxx.c
index b4dbc3f..0a45765 100644
--- a/gcc/config/sh/symbian.c
+++ b/gcc/config/sh/symbian-cxx.c
@@ -1,4 +1,4 @@
-/* Routines for GCC for a Symbian OS targeted SH backend.
+/* Routines for C++ support for GCC for a Symbian OS targeted SH backend.
Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
Contributed by RedHat.
Most of this code is stolen from i386/winnt.c.
@@ -31,27 +31,13 @@
#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."
+#include "sh-symbian.h"
/* Return the type that we should use to determine if DECL is
imported or exported. */
-static tree
+tree
sh_symbian_associated_type (tree decl)
{
tree t = NULL_TREE;
@@ -70,49 +56,11 @@ sh_symbian_associated_type (tree 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)
+bool
+sh_symbian_is_dllimported (tree decl)
{
tree imp;
@@ -186,335 +134,7 @@ sh_symbian_dllimport_p (tree decl)
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 (e.g.: 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 (MEM_P (rtlname))
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- 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 definition to be marked as dllexport. The prototypes
- are in headers used everywhere and the definition is in a translation
- unit which has included the header in order to ensure argument
- correctness. */
- oldname += strlen (DLL_IMPORT_PREFIX);
- DECL_DLLIMPORT_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 (MEM_P (rtlname))
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- if (sh_symbian_dllexport_name_p (oldname))
- {
- error ("%qE declared as both exported to and imported from a DLL",
- 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 ("failure in redeclaration of %q+D: dllimport'd symbol lacks external linkage",
- 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_DLLIMPORT_P flag. */
- else if ( (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && DECL_RTL (decl) != NULL_RTX
- && MEM_P (DECL_RTL (decl))
- && MEM_P (XEXP (DECL_RTL (decl), 0))
- && 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 (0, "%s %q+D %s after being referenced with dllimport linkage",
- 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_DLLIMPORT_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);
-
- if (DECL_P (node))
- DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
- else
- TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
-
-#if SYMBIAN_DEBUG
- fprintf (stderr, "propagate %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 (OPT_Wattributes, "%qs 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 (OPT_Wattributes, "%qs 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 ("variable %q+D definition is marked dllimport",
- 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 destructor, then we must
- make sure that the attribute is propagated 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);
-
- /* Propagate 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))
- {
- /* Propagate 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 ("external linkage required for symbol %q+D because of %qE attribute",
- node, 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:
@@ -543,12 +163,12 @@ sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
+ 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)
+sh_symbian_possibly_export_base_class (tree base_class)
{
VEC(tree,gc) *method_vec;
int len;
@@ -603,6 +223,119 @@ symbian_possibly_export_base_class (tree base_class)
#endif
}
+/* 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
+sh_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);
+
+ if (DECL_P (node))
+ DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
+ else
+ TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
+
+#if SYMBIAN_DEBUG
+ fprintf (stderr, "propagate %s attribute", attr_name);
+ print_node_brief (stderr, " to", node, 0);
+ fprintf (stderr, "\n");
+#endif
+}
+
+/* Add the named attribute to a class and its vtable and rtti. */
+
+static void
+sh_symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
+{
+ sh_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 ? */
+ sh_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)))
+ sh_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
+sh_symbian_class_needs_attribute (tree ctype, const char *attribute_name)
+{
+ VEC(tree,gc) *method_vec;
+
+ method_vec = CLASSTYPE_METHOD_VEC (ctype);
+
+ /* If the key function has the attribute then the class needs it too. */
+ if (TYPE_POLYMORPHIC_P (ctype)
+ && method_vec
+ && tree_contains_struct [TREE_CODE (ctype), TS_DECL_COMMON] == 1
+ && lookup_attribute (attribute_name,
+ DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
+ return true;
+
+ /* Check the class's member functions. */
+ if (TREE_CODE (ctype) == RECORD_TYPE)
+ {
+ unsigned int len;
+
+ len = method_vec ? VEC_length (tree, method_vec) : 0;
+
+ for (;len --;)
+ {
+ tree member = VEC_index (tree, method_vec, 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;
+}
+
/* Decide if a class needs its vtable and rtti exporting. */
static bool
@@ -725,97 +458,19 @@ symbian_export_vtable_and_rtti_p (tree ctype)
/* Now we must check and possibly export the base classes. */
for (i = 0, binfo = TYPE_BINFO (ctype);
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
+ sh_symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
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)
-{
- VEC(tree,gc) *method_vec;
-
- method_vec = CLASSTYPE_METHOD_VEC (ctype);
-
- /* If the key function has the attribute then the class needs it too. */
- if (TYPE_POLYMORPHIC_P (ctype)
- && method_vec
- && lookup_attribute (attribute_name,
- DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
- return true;
-
- /* Check the class's member functions. */
- if (TREE_CODE (ctype) == RECORD_TYPE)
- {
- unsigned int len;
-
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, 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;
-}
+/* Possibly override the decision to export class TYPE. Upon entry
+ IMPORT_EXPORT will contain 1 if the class is going to be exported,
+ -1 if it is going to be imported and 0 otherwise. This function
+ should return the modified value and perform any other actions
+ necessary to support the backend's targeted operating system. */
int
-symbian_import_export_class (tree ctype, int import_export)
+sh_symbian_import_export_class (tree ctype, int import_export)
{
const char *attr_name = NULL;
@@ -832,14 +487,14 @@ symbian_import_export_class (tree ctype, int import_export)
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);
+ if (sh_symbian_class_needs_attribute (ctype, attr_name))
+ sh_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");
+ sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
/* Make sure that the class and its vtable are exported. */
import_export = 1;
@@ -877,18 +532,131 @@ symbian_import_export_class (tree ctype, int import_export)
return import_export;
}
-/* Dummy definition of this array for cc1 building purposes. */
-tree cp_global_trees[CPTI_MAX] __attribute__((weak));
+/* 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 (OPT_Wattributes, "%qs 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 (OPT_Wattributes, "%qs attribute ignored", attr);
+ *no_add_attrs = true;
+ }
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+ 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 ("variable %q+D definition is marked dllimport",
+ node);
+ *no_add_attrs = true;
+ }
-/* Dummy version of this G++ function for building cc1. */
-void lang_check_failed (const char *, int, const char *) __attribute__((weak));
+ /* `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;
+ }
+ }
-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);
+ /* If the node is an overloaded constructor or destructor, then we must
+ make sure that the attribute is propagated 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;
+ }
+
+ sh_symbian_add_attribute (function, attr);
+
+ /* Propagate the attribute to any function thunks as well. */
+ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+ if (TREE_CODE (thunk) == FUNCTION_DECL)
+ sh_symbian_add_attribute (thunk, attr);
+ }
+ }
+
+ if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
+ {
+ /* Propagate the attribute to any thunks of this function. */
+ for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
+ if (TREE_CODE (thunk) == FUNCTION_DECL)
+ sh_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 ("external linkage required for symbol %q+D because of %qE attribute",
+ node, 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;
}
-#endif /* ENABLE_TREE_CHECKING */
diff --git a/gcc/config/sh/symbian-post.h b/gcc/config/sh/symbian-post.h
index d8d56b1..a4497b9 100644
--- a/gcc/config/sh/symbian-post.h
+++ b/gcc/config/sh/symbian-post.h
@@ -31,8 +31,8 @@
#define SYMBIAN_EXPORT_NAME(NAME,FILE,DECL) \
do \
{ \
- if ((DECL && sh_symbian_dllexport_p (DECL)) \
- || sh_symbian_dllexport_name_p (NAME)) \
+ if ((DECL && sh_symbian_is_dllexported (DECL)) \
+ || sh_symbian_is_dllexported_name (NAME)) \
{ \
fprintf ((FILE), "\t.pushsection .directive\n"); \
fprintf ((FILE), "\t.asciz \"EXPORT %s\\n\"\n", \
diff --git a/gcc/config/sh/t-symbian b/gcc/config/sh/t-symbian
index 1698b72..f0b7dab 100644
--- a/gcc/config/sh/t-symbian
+++ b/gcc/config/sh/t-symbian
@@ -21,6 +21,28 @@ sh-c.o: $(srcdir)/config/sh/sh-c.c \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/sh/sh-c.c
+symbian-cxx.o: \
+ $(srcdir)/config/sh/symbian-cxx.c \
+ $(srcdir)/config/sh/sh-symbian.h \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
+ toplev.h output.h coretypes.h flags.h expr.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+symbian-c.o: \
+ $(srcdir)/config/sh/symbian-c.c \
+ $(srcdir)/config/sh/sh-symbian.h \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
+ toplev.h output.h coretypes.h flags.h expr.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+symbian-base.o: \
+ $(srcdir)/config/sh/symbian-base.c \
+ $(srcdir)/config/sh/sh-symbian.h \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
+ toplev.h output.h coretypes.h flags.h expr.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+
LIB1ASMSRC = sh/lib1funcs.asm
LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
_movstr_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \