diff options
author | Andrew Haley <aph@redhat.com> | 2007-10-03 12:59:57 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2007-10-03 12:59:57 +0000 |
commit | 6d2c26dec4f9bc41c92f25326cedb60509d2aa1a (patch) | |
tree | 5cc89dbc00bbc10b8f999101d2d2ff45011e340d /gcc/java/class.c | |
parent | 448d2cd2f73e2e16e2bdd5c407174afebf3ed845 (diff) | |
download | gcc-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.c | 57 |
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); |