85 lines
2.5 KiB
Diff
85 lines
2.5 KiB
Diff
|
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.
|
||
|
|
||
|
--- gcc/java/class.c (revision 128980)
|
||
|
+++ gcc/java/class.c (revision 128981)
|
||
|
@@ -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);
|