OSDN Git Service

2007-10-03 Andrew Haley <aph@redhat.com>
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Oct 2007 12:59:57 +0000 (12:59 +0000)
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Oct 2007 12:59:57 +0000 (12:59 +0000)
        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

gcc/java/ChangeLog
gcc/java/class.c

index bb22fdc..4378b8f 100644 (file)
@@ -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.
index 82b71b4..75ee58a 100644 (file)
@@ -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);