diff options
author | aph <aph@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-03 12:59:57 +0000 |
---|---|---|
committer | aph <aph@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-03 12:59:57 +0000 |
commit | 07cc3a26eae15a67863804d2113f8184f475a823 (patch) | |
tree | 5cc89dbc00bbc10b8f999101d2d2ff45011e340d /gcc/java | |
parent | ec530640a071c3bf2b99a9bb70b12380f7f23955 (diff) | |
download | gcc-07cc3a26eae15a67863804d2113f8184f475a823.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128981 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/java')
-rw-r--r-- | gcc/java/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/java/class.c | 57 |
2 files changed, 63 insertions, 2 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index bb22fdc36d0..4378b8f26d8 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,11 @@ +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. + 2007-09-27 Jakub Jelinek <jakub@redhat.com> * lang.c (java_print_error_function): Add third argument. diff --git a/gcc/java/class.c b/gcc/java/class.c index 82b71b4df18..75ee58aaedd 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); |