namespace namespace
Andrew Haley
aph@redhat.com
Mon Jun 29 17:39:00 GMT 2009
It turns out that the mangling of C++ keywords used by gcj is completely
broken:
In particular, when a member name is a C++ keyword, "$" is appended to the
name. However, this is results in an illegal mangled name so it is not
possible to refer to the member from CNI code.
Also, the set of C++ keywords in gjavah is different from the set in gcj.
Also, types are not checked for C++ keywords, so javax.xml.namespace.* cannot
be referenced from CNI code.
This patch fixes the problem.
This is an ABI change. However, the ABI was almost completely broken
anyway.
Andrew.
2009-06-29 Andrew Haley <aph@redhat.com>
PR java/40590
* tools/gnu/classpath/tools/javah/FieldHelper.java (print):
Use printName().
* tools/gnu/classpath/tools/javah/MethodHelper.java (print):
Use printName().
* tools/gnu/classpath/tools/javah/CniStubPrinter.java (printDecl):
Use printName().
* tools/gnu/classpath/tools/javah/Keywords.java (words): Replace
with keywords list from gcc/java/mangle.c.
* tools/gnu/classpath/tools/javah/ClassWrapper.java (printMethods):
Don't pre-convert a C++ keyword.
(print(CniPrintStream)): Call CniPrintStream.printName().
(printContents): Likewise.
* tools/gnu/classpath/tools/javah/CniPrintStream.java
(getClassName): Don't call replaceAll("/", "::").
(print(Type)): Add ""::" befor name, " *" after. Use printName(), not
print.
(printName(PrintStream, String), printName(String), printlnName):
New methods.
(moveToPackage): Use printName().
2009-06-29 Andrew Haley <aph@redhat.com>
PR java/40590
* java-tree.h (cxx_keyword_p): New declaration.
* mangle_name.c (utf8_cmp): Move here from mangle.c.
(cxx_keywords): Likewise.
(cxx_keyword_p): Likewise.
(MANGLE_CXX_KEYWORDS): New macro.
(append_gpp_mangled_name): Use MANGLE_CXX_KEYWORDS.
(append_gpp_mangled_name): Likewise.
* mangle.c: Move code to mangle_name.c.
(mangle_member_name): Don't call cxx_keyword_p.
Index: gcc/java/mangle_name.c
===================================================================
--- gcc/java/mangle_name.c (revision 149053)
+++ gcc/java/mangle_name.c (working copy)
@@ -41,6 +41,183 @@
extern struct obstack *mangle_obstack;
+static int
+utf8_cmp (const unsigned char *str, int length, const char *name)
+{
+ const unsigned char *limit = str + length;
+ int i;
+
+ for (i = 0; name[i]; ++i)
+ {
+ int ch = UTF8_GET (str, limit);
+ if (ch != name[i])
+ return ch - name[i];
+ }
+
+ return str == limit ? 0 : 1;
+}
+
+/* A sorted list of all C++ keywords. */
+static const char *const cxx_keywords[] =
+{
+ "_Complex",
+ "__alignof",
+ "__alignof__",
+ "__asm",
+ "__asm__",
+ "__attribute",
+ "__attribute__",
+ "__builtin_va_arg",
+ "__complex",
+ "__complex__",
+ "__const",
+ "__const__",
+ "__extension__",
+ "__imag",
+ "__imag__",
+ "__inline",
+ "__inline__",
+ "__label__",
+ "__null",
+ "__real",
+ "__real__",
+ "__restrict",
+ "__restrict__",
+ "__signed",
+ "__signed__",
+ "__typeof",
+ "__typeof__",
+ "__volatile",
+ "__volatile__",
+ "and",
+ "and_eq",
+ "asm",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "class",
+ "compl",
+ "const",
+ "const_cast",
+ "continue",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "else",
+ "enum",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "goto",
+ "if",
+ "inline",
+ "int",
+ "long",
+ "mutable",
+ "namespace",
+ "new",
+ "not",
+ "not_eq",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_cast",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "typeof",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "xor",
+ "xor_eq"
+};
+
+/* Return true if NAME is a C++ keyword. */
+int
+cxx_keyword_p (const char *name, int length)
+{
+ int last = ARRAY_SIZE (cxx_keywords);
+ int first = 0;
+ int mid = (last + first) / 2;
+ int old = -1;
+
+ for (mid = (last + first) / 2;
+ mid != old;
+ old = mid, mid = (last + first) / 2)
+ {
+ int kwl = strlen (cxx_keywords[mid]);
+ int min_length = kwl > length ? length : kwl;
+ int r = utf8_cmp ((const unsigned char *) name, min_length, cxx_keywords[mid]);
+
+ if (r == 0)
+ {
+ int i;
+ /* We've found a match if all the remaining characters are `$'. */
+ for (i = min_length; i < length && name[i] == '$'; ++i)
+ ;
+ if (i == length)
+ return 1;
+ r = 1;
+ }
+
+ if (r < 0)
+ last = mid;
+ else
+ first = mid;
+ }
+ return 0;
+}
+
+/* If NAME happens to be a C++ keyword, add `$'. */
+#define MANGLE_CXX_KEYWORDS(NAME, LEN) \
+do \
+ { \
+ if (cxx_keyword_p ((NAME), (LEN))) \
+ { \
+ char *tmp_buf = (char *)alloca ((LEN)+1); \
+ memcpy (tmp_buf, (NAME), (LEN)); \
+ tmp_buf[LEN]= '$'; \
+ (NAME) = tmp_buf; \
+ (LEN)++; \
+ } \
+ } \
+while (0)
+
+
/* If the assembler doesn't support UTF8 in symbol names, some
characters might need to be escaped. */
@@ -54,10 +231,14 @@
void
append_gpp_mangled_name (const char *name, int len)
{
- int encoded_len = unicode_mangling_length (name, len);
- int needs_escapes = encoded_len > 0;
+ int encoded_len, needs_escapes;
char buf[6];
+ MANGLE_CXX_KEYWORDS (name, len);
+
+ encoded_len = unicode_mangling_length (name, len);
+ needs_escapes = encoded_len > 0;
+
sprintf (buf, "%d", (needs_escapes ? encoded_len : len));
obstack_grow (mangle_obstack, buf, strlen (buf));
@@ -195,10 +376,14 @@
append_gpp_mangled_name (const char *name, int len)
{
const unsigned char *ptr;
- const unsigned char *limit = (const unsigned char *)name + len;
+ const unsigned char *limit;
int encoded_len;
char buf [6];
+ MANGLE_CXX_KEYWORDS (name, len);
+
+ limit = (const unsigned char *)name + len;
+
/* Compute the length of the string we wish to mangle. */
for (encoded_len = 0, ptr = (const unsigned char *) name;
ptr < limit; encoded_len++)
Index: gcc/java/mangle.c
===================================================================
--- gcc/java/mangle.c (revision 149053)
+++ gcc/java/mangle.c (working copy)
@@ -72,167 +72,6 @@
/* atms: array template mangled string. */
static GTY(()) tree atms;
-static int
-utf8_cmp (const unsigned char *str, int length, const char *name)
-{
- const unsigned char *limit = str + length;
- int i;
-
- for (i = 0; name[i]; ++i)
- {
- int ch = UTF8_GET (str, limit);
- if (ch != name[i])
- return ch - name[i];
- }
-
- return str == limit ? 0 : 1;
-}
-
-/* A sorted list of all C++ keywords. */
-static const char *const cxx_keywords[] =
-{
- "_Complex",
- "__alignof",
- "__alignof__",
- "__asm",
- "__asm__",
- "__attribute",
- "__attribute__",
- "__builtin_va_arg",
- "__complex",
- "__complex__",
- "__const",
- "__const__",
- "__extension__",
- "__imag",
- "__imag__",
- "__inline",
- "__inline__",
- "__label__",
- "__null",
- "__real",
- "__real__",
- "__restrict",
- "__restrict__",
- "__signed",
- "__signed__",
- "__typeof",
- "__typeof__",
- "__volatile",
- "__volatile__",
- "and",
- "and_eq",
- "asm",
- "auto",
- "bitand",
- "bitor",
- "bool",
- "break",
- "case",
- "catch",
- "char",
- "class",
- "compl",
- "const",
- "const_cast",
- "continue",
- "default",
- "delete",
- "do",
- "double",
- "dynamic_cast",
- "else",
- "enum",
- "explicit",
- "export",
- "extern",
- "false",
- "float",
- "for",
- "friend",
- "goto",
- "if",
- "inline",
- "int",
- "long",
- "mutable",
- "namespace",
- "new",
- "not",
- "not_eq",
- "operator",
- "or",
- "or_eq",
- "private",
- "protected",
- "public",
- "register",
- "reinterpret_cast",
- "return",
- "short",
- "signed",
- "sizeof",
- "static",
- "static_cast",
- "struct",
- "switch",
- "template",
- "this",
- "throw",
- "true",
- "try",
- "typedef",
- "typeid",
- "typename",
- "typeof",
- "union",
- "unsigned",
- "using",
- "virtual",
- "void",
- "volatile",
- "wchar_t",
- "while",
- "xor",
- "xor_eq"
-};
-
-/* Return true if NAME is a C++ keyword. */
-static int
-cxx_keyword_p (const char *name, int length)
-{
- int last = ARRAY_SIZE (cxx_keywords);
- int first = 0;
- int mid = (last + first) / 2;
- int old = -1;
-
- for (mid = (last + first) / 2;
- mid != old;
- old = mid, mid = (last + first) / 2)
- {
- int kwl = strlen (cxx_keywords[mid]);
- int min_length = kwl > length ? length : kwl;
- int r = utf8_cmp ((const unsigned char *) name, min_length, cxx_keywords[mid]);
-
- if (r == 0)
- {
- int i;
- /* We've found a match if all the remaining characters are `$'. */
- for (i = min_length; i < length && name[i] == '$'; ++i)
- ;
- if (i == length)
- return 1;
- r = 1;
- }
-
- if (r < 0)
- last = mid;
- else
- first = mid;
- }
- return 0;
-}
-
/* This is the mangling interface: a decl, a class field (.class) and
the vtable. */
@@ -392,10 +231,6 @@
{
append_gpp_mangled_name (IDENTIFIER_POINTER (name),
IDENTIFIER_LENGTH (name));
-
- /* If NAME happens to be a C++ keyword, add `$'. */
- if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
- obstack_1grow (mangle_obstack, '$');
}
/* Append the mangled name of TYPE onto OBSTACK. */
Index: gcc/java/java-tree.h
===================================================================
--- gcc/java/java-tree.h (revision 149053)
+++ gcc/java/java-tree.h (working copy)
@@ -1224,6 +1224,8 @@
extern void rewrite_reflection_indexes (void *);
+int cxx_keyword_p (const char *name, int length);
+
#define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
/* Access flags etc for a method (a FUNCTION_DECL): */
Index: libjava/classpath/tools/gnu/classpath/tools/javah/CniPrintStream.java
===================================================================
--- libjava/classpath/tools/gnu/classpath/tools/javah/CniPrintStream.java (revision 148903)
+++ libjava/classpath/tools/gnu/classpath/tools/javah/CniPrintStream.java (working copy)
@@ -125,9 +125,10 @@
// Add the plain class name; we'll handle it when
// we process namespaces.
allClasses.add(name);
- return "::" + name.replaceAll("/", "::") + " *";
+ return name;
}
+ // Print the C++ form of TYPE, mangling C++ keywords.
public void print(Type type)
{
int arrayCount = 0;
@@ -141,7 +142,9 @@
}
if (type.getSort() == Type.OBJECT)
{
- print(getClassName(type));
+ print("::");
+ printName(getClassName(type));
+ print(" *");
}
else
{
@@ -156,6 +159,34 @@
}
}
+ // Print NAME, converting into C++ syntax and mangling C++ keywords
+ // as we go.
+ public final static void printName(PrintStream out, String name)
+ {
+ String[] parts = name.split("::|/");
+ for (int i = 0; i < parts.length; i++)
+ {
+ if (i != 0)
+ out.print("::");
+ out.print(Keywords.getCxxName(parts[i]));
+ }
+ }
+
+ // Println NAME, converting into C++ syntax and mangling C++
+ // keywords as we go.
+ public final static void printlnName(PrintStream out, String name)
+ {
+ printName(out, name);
+ out.println();
+ }
+
+ // Print NAME, converting into C++ syntax and mangling C++ keywords
+ // as we go.
+ final void printName(String name)
+ {
+ printName(this, name);
+ }
+
private void indent(PrintStream out, int n)
{
for (int i = 0; i < n; ++i)
@@ -186,7 +217,7 @@
{
indent(out, j + 1);
out.print("namespace ");
- out.println(pkgParts[j]);
+ printlnName(out, pkgParts[j]);
indent(out, j + 1);
out.println("{");
}
@@ -202,7 +233,7 @@
moveToPackage(out, pkgParts);
indent(out, pkgParts.length + 2);
out.print("class ");
- out.print(className);
+ printName(out, className);
out.println(";");
}
Index: libjava/classpath/tools/gnu/classpath/tools/javah/ClassWrapper.java
===================================================================
--- libjava/classpath/tools/gnu/classpath/tools/javah/ClassWrapper.java (revision 148903)
+++ libjava/classpath/tools/gnu/classpath/tools/javah/ClassWrapper.java (working copy)
@@ -260,7 +260,7 @@
if (bridgeTargets.contains(sum))
nameToUse = (String) methodNameMap.get(sum);
else
- nameToUse = Keywords.getCxxName(m.name);
+ nameToUse = m.name;
methodNameMap.put(sum, nameToUse);
MethodHelper.print(out, m, this, nameToUse);
}
@@ -291,7 +291,8 @@
public void print(CniPrintStream out)
{
- out.print("::" + name.replaceAll("/", "::"));
+ out.print("::");
+ out.printName(name);
}
// This prints the body of a class to a CxxPrintStream.
@@ -303,7 +304,7 @@
out.print("class ");
// Don't use our print() -- we don't want the leading "::".
- out.print(name.replaceAll("/", "::"));
+ out.printName(name);
if (superClass != null)
{
out.print(" : public ");
Index: libjava/classpath/tools/gnu/classpath/tools/javah/Keywords.java
===================================================================
--- libjava/classpath/tools/gnu/classpath/tools/javah/Keywords.java (revision 148903)
+++ libjava/classpath/tools/gnu/classpath/tools/javah/Keywords.java (working copy)
@@ -42,28 +42,115 @@
public class Keywords
{
- private static final String[] words = { "and", "and_eq", "asm", "auto",
- "bitand", "bitor", "bool", "break",
- "case", "catch", "char", "class",
- "compl", "const", "const_cast",
- "continue", "default", "delete", "do",
- "double", "dynamic_cast", "else",
- "enum", "explicit", "export",
- "extern", "false", "float", "for",
- "friend", "goto", "if", "inline",
- "int", "long", "mutable", "namespace",
- "new", "not", "not_eq", "operator",
- "or", "or_eq", "private", "protected",
- "public", "register",
- "reinterpret_cast", "return", "short",
- "signed", "sizeof", "static",
- "static_cast", "struct", "switch",
- "template", "this", "throw", "true",
- "try", "typedef", "typeid",
- "typename", "typeof", "union",
- "unsigned", "using", "virtual",
- "void", "volatile", "wchar_t",
- "while", "xor", "xor_eq" };
+/* A sorted list of all C++ keywords. This is identical to the list
+ in gcc/java/mangle.c. */
+ private static final String[] words =
+ {
+ "_Complex",
+ "__alignof",
+ "__alignof__",
+ "__asm",
+ "__asm__",
+ "__attribute",
+ "__attribute__",
+ "__builtin_va_arg",
+ "__complex",
+ "__complex__",
+ "__const",
+ "__const__",
+ "__extension__",
+ "__imag",
+ "__imag__",
+ "__inline",
+ "__inline__",
+ "__label__",
+ "__null",
+ "__real",
+ "__real__",
+ "__restrict",
+ "__restrict__",
+ "__signed",
+ "__signed__",
+ "__typeof",
+ "__typeof__",
+ "__volatile",
+ "__volatile__",
+ "and",
+ "and_eq",
+ "asm",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "class",
+ "compl",
+ "const",
+ "const_cast",
+ "continue",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "else",
+ "enum",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "goto",
+ "if",
+ "inline",
+ "int",
+ "long",
+ "mutable",
+ "namespace",
+ "new",
+ "not",
+ "not_eq",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_cast",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "typeof",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "xor",
+ "xor_eq"
+ };
private static final HashSet keywords;
static
Index: libjava/classpath/tools/gnu/classpath/tools/javah/CniStubPrinter.java
===================================================================
--- libjava/classpath/tools/gnu/classpath/tools/javah/CniStubPrinter.java (revision 148903)
+++ libjava/classpath/tools/gnu/classpath/tools/javah/CniStubPrinter.java (working copy)
@@ -59,9 +59,9 @@
private void printDecl(CniPrintStream out, String className, MethodNode method)
{
- out.print(className);
+ out.printName(className);
out.print("::");
- out.print(method.name);
+ out.printName(method.name);
out.print("(");
Type[] argTypes = Type.getArgumentTypes(method.desc);
for (int j = 0; j < argTypes.length; ++j)
Index: libjava/classpath/tools/gnu/classpath/tools/javah/MethodHelper.java
===================================================================
--- libjava/classpath/tools/gnu/classpath/tools/javah/MethodHelper.java (revision 148903)
+++ libjava/classpath/tools/gnu/classpath/tools/javah/MethodHelper.java (working copy)
@@ -97,14 +97,14 @@
{
out.print(Type.getReturnType(meth.desc));
out.print(" ");
- out.print(realMethodName);
+ out.printName(realMethodName);
}
else
{
String name = declarer.name;
int index = name.lastIndexOf('/');
name = name.substring(index + 1);
- out.print(name);
+ out.printName(name);
}
out.print("(");
Type[] argTypes = Type.getArgumentTypes(meth.desc);
Index: libjava/classpath/tools/gnu/classpath/tools/javah/FieldHelper.java
===================================================================
--- libjava/classpath/tools/gnu/classpath/tools/javah/FieldHelper.java (revision 148903)
+++ libjava/classpath/tools/gnu/classpath/tools/javah/FieldHelper.java (working copy)
@@ -66,7 +66,7 @@
out.print(")))) ");
result = true;
}
- out.print(Keywords.getCxxName(field.name));
+ out.printName(field.name);
if (hasMethodName)
out.print("__");
if (Modifier.isStatic(field.access))
More information about the Java-patches
mailing list