aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/class.c
diff options
context:
space:
mode:
authorAndrew Haley <aph@redhat.com>2007-10-03 12:59:57 +0000
committerAndrew Haley <aph@gcc.gnu.org>2007-10-03 12:59:57 +0000
commit6d2c26dec4f9bc41c92f25326cedb60509d2aa1a (patch)
tree5cc89dbc00bbc10b8f999101d2d2ff45011e340d /gcc/java/class.c
parent448d2cd2f73e2e16e2bdd5c407174afebf3ed845 (diff)
downloadgcc-6d2c26dec4f9bc41c92f25326cedb60509d2aa1a.zip
gcc-6d2c26dec4f9bc41c92f25326cedb60509d2aa1a.tar.gz
gcc-6d2c26dec4f9bc41c92f25326cedb60509d2aa1a.tar.bz2
re PR java/33639 (gcj generates assembler errors)
2007-10-03 Andrew Haley <aph@redhat.com> PR java/33639 * class.c (mangled_classname): Detect and replace illegal characters in assembly language symbols. (gen_indirect_dispatch_tables): Call mangled_classname() on the type. From-SVN: r128981
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r--gcc/java/class.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 82b71b4..75ee58a 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -314,10 +314,63 @@ identifier_subst (const tree old_id,
tree
mangled_classname (const char *prefix, tree type)
{
+ tree result;
tree ident = TYPE_NAME (type);
if (TREE_CODE (ident) != IDENTIFIER_NODE)
ident = DECL_NAME (ident);
- return identifier_subst (ident, prefix, '.', '_', "");
+ result = identifier_subst (ident, prefix, '.', '_', "");
+
+ /* Replace any characters that aren't in the set [0-9a-zA-Z_$] with
+ "_0xXX". Class names containing such chracters are uncommon, but
+ they do sometimes occur in class files. Without this check,
+ these names cause assembly errors.
+
+ There is a possibility that a real class name could conflict with
+ the identifier we generate, but it is unlikely and will
+ immediately be detected as an assembler error. At some point we
+ should do something more elaborate (perhaps using the full
+ unicode mangling scheme) in order to prevent such a conflict. */
+ {
+ int i;
+ const int len = IDENTIFIER_LENGTH (result);
+ const char *p = IDENTIFIER_POINTER (result);
+ int illegal_chars = 0;
+
+ /* Make two passes over the identifier. The first pass is merely
+ to count illegal characters; we need to do this in order to
+ allocate a buffer. */
+ for (i = 0; i < len; i++)
+ {
+ char c = p[i];
+ illegal_chars += (! ISALNUM (c) && c != '_' && c != '$');
+ }
+
+ /* And the second pass, which is rarely executed, does the
+ rewriting. */
+ if (illegal_chars != 0)
+ {
+ char *buffer = alloca (illegal_chars * 4 + len + 1);
+ int j;
+
+ for (i = 0, j = 0; i < len; i++)
+ {
+ char c = p[i];
+ if (! ISALNUM (c) && c != '_' && c != '$')
+ {
+ buffer[j++] = '_';
+ sprintf (&buffer[j], "0x%02x", c);
+ j += 4;
+ }
+ else
+ buffer[j++] = c;
+ }
+
+ buffer[j] = 0;
+ result = get_identifier (buffer);
+ }
+ }
+
+ return result;
}
tree
@@ -389,7 +442,7 @@ while (0)
void
gen_indirect_dispatch_tables (tree type)
{
- const char *typename = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ const char *typename = IDENTIFIER_POINTER (mangled_classname ("", type));
{
tree field = NULL;
char *buf = alloca (strlen (typename) + strlen ("_catch_classes_") + 1);