how do I stop gcjh from generating function bodies?

Tom Tromey tromey@redhat.com
Sun Nov 4 10:40:00 GMT 2001


>>>>> "Adam" == Adam Megacz <gcj@lists.megacz.com> writes:

Adam> public class C implements I {
Adam> public I returnSelfAsI() { return this; }
Adam> }
Adam> ...but gcjh generates a body for it in the .h file, except that
Adam> CNI doesn't grok interfaces, so the generated .h doesn't compile
Thanks again for finding this.
I wrote a patch to gcjh which should fix this bug.
Could you try it out?
It is appended. If it works for you I will check it in.
Tom
2001年11月12日 Tom Tromey <tromey@redhat.com>
	* gjavah.c (method_signature): New global.
	(HANDLE_METHOD): Set it.
	(decompile_return_statement): New function.
	(decompile_method): Use it.
	(print_method_info): Removed `synth' argument.
Index: gjavah.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/gjavah.c,v
retrieving revision 1.74
diff -u -r1.74 gjavah.c
--- gjavah.c 2001年10月22日 03:58:19 1.74
+++ gjavah.c 2001年11月12日 21:05:30
@@ -120,7 +120,7 @@
 static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
 static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int));
 static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int));
-static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2, int));
+static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
 static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *,
 				 int));
 static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int,
@@ -151,6 +151,7 @@
 static int overloaded_jni_method_exists_p PARAMS ((const unsigned char *, int,
 						 const char *, int));
 static void jni_print_char PARAMS ((FILE *, int));
+static void decompile_return_statement PARAMS ((FILE *, JCF *, int, int, int));
 
 JCF_u2 current_field_name;
 JCF_u2 current_field_value;
@@ -187,9 +188,12 @@
 static int method_access = 0;
 static int method_printed = 0;
 static int method_synthetic = 0;
+static int method_signature = 0;
+
 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT)	\
 {									\
 method_synthetic = 0;						\
+ method_signature = SIGNATURE;					\
 if (ATTRIBUTE_COUNT)						\
 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT,		\
 				 (const char *)"Synthetic", 9);	\
@@ -207,12 +211,12 @@
 	decompiled = 0; method_printed = 0;				\
 	if (out)							\
 	 print_method_info (out, jcf, NAME, SIGNATURE,			\
-			 ACCESS_FLAGS, method_synthetic);		\
+			 ACCESS_FLAGS);				\
 }									\
 else if (!method_synthetic)						\
 {									\
 	print_method_info (NULL, jcf, NAME, SIGNATURE,			\
-			 ACCESS_FLAGS, method_synthetic);		\
+			 ACCESS_FLAGS);				\
 	if (! stubs && ! flag_jni)					\
 	 add_class_decl (out, jcf, SIGNATURE);				\
 }									\
@@ -784,9 +788,9 @@
 
 
 static void
-DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth),
+DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
 FILE *stream AND JCF* jcf
- AND int name_index AND int sig_index AND JCF_u2 flags AND int synth)
+ AND int name_index AND int sig_index AND JCF_u2 flags)
 {
 const unsigned char *str;
 int length, is_init = 0;
@@ -799,10 +803,6 @@
 str = JPOOL_UTF_DATA (jcf, name_index);
 length = JPOOL_UTF_LENGTH (jcf, name_index);
 
- /* Ignore synthetic methods. */
- if (synth)
- return;
-
 if (str[0] == '<')
 {
 /* Ignore the internally generated method <clinit>. However,
@@ -892,6 +892,132 @@
 free (override);
 }
 
+/* A helper for the decompiler which prints a `return' statement where
+ the type is a reference type. If METHODTYPE and OBJECTTYPE are not
+ identical, we emit a cast. We do this because the C++ compiler
+ doesn't know that a reference can be cast to the type of an
+ interface it implements. METHODTYPE is the index of the method's
+ signature. NAMEINDEX is the index of the field name; -1 for
+ `this'. OBJECTTYPE is the index of the object's type. */
+static void
+decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
+ FILE *out;
+ JCF *jcf;
+ int methodtype, nameindex, objecttype;
+{
+ int cast = 0;
+ int obj_name_len, method_name_len;
+ const unsigned char *obj_data, *method_data;
+
+ obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
+ obj_data = JPOOL_UTF_DATA (jcf, objecttype);
+
+ method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
+ method_data = JPOOL_UTF_DATA (jcf, methodtype);
+
+ /* Skip forward to return type part of method. */
+ while (*method_data != ')')
+ {
+ ++method_data;
+ --method_name_len;
+ }
+ /* Skip past `)'. */
+ ++method_data;
+ --method_name_len;
+
+ /* If we see an `L', skip it and the trailing `;'. */
+ if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
+ {
+ ++method_data;
+ method_name_len -= 2;
+ }
+ if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
+ {
+ ++obj_data;
+ obj_name_len -= 2;
+ }
+
+ /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
+ need a cast. Right now there is no way to determine if this is
+ the case. */
+ if (method_name_len != obj_name_len)
+ cast = 1;
+ else
+ {
+ int i;
+ for (i = 0; i < method_name_len; ++i)
+	{
+	 if (method_data[i] != obj_data[i])
+	 {
+	 cast = 1;
+	 break;
+	 }
+	}
+ }
+
+ fputs (" { return ", out);
+
+ if (cast)
+ {
+ int array_depth = 0;
+ const unsigned char *limit;
+
+ fputs ("reinterpret_cast<", out);
+
+ while (*method_data == '[')
+	{
+	 ++method_data;
+	 ++array_depth;
+	 --method_name_len;
+	 fputs ("JArray<", out);
+	}
+
+ fputs ("::", out);
+
+ /* If we see an `L', skip it and the trailing `;'. Only do this
+	 if we've seen an array specification. If we don't have an
+	 array then the `L' was stripped earlier. */
+ if (array_depth && method_data[0] == 'L'
+	 && method_data[method_name_len - 1] == ';')
+	{
+	 ++method_data;
+	 method_name_len -= 2;
+	}
+
+ limit = method_data + method_name_len;
+ while (method_data < limit)
+	{
+	 int ch = UTF8_GET (method_data, limit);
+	 if (ch == '/')
+	 fputs ("::", out);
+	 else
+	 jcf_print_char (out, ch);
+	}
+ fputs (" *", out);
+
+ /* Close each array. */
+ while (array_depth > 0)
+	{
+	 fputs ("> *", out);
+	 --array_depth;
+	}
+
+ /* Close the cast. */
+ fputs ("> (", out);
+ }
+
+ if (nameindex == -1)
+ fputs ("this", out);
+ else
+ print_field_name (out, jcf, nameindex, 0);
+
+ if (cast)
+ fputs (")", out);
+
+ fputs ("; }", out);
+}
+
+
 /* Try to decompile a method body. Right now we just try to handle a
 simple case that we can do. Expand as desired. */
 static void
@@ -918,24 +1044,29 @@
 	 || codes[4] == OPCODE_lreturn))
 {
 /* Found code like `return FIELD'. */
- fputs (" { return ", out);
 index = (codes[2] << 8) | codes[3];
 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
- /* FIXME: ensure that the field's class is this class. */
 name_and_type = JPOOL_USHORT2 (jcf, index);
 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
 name = JPOOL_USHORT1 (jcf, name_and_type);
- /* FIXME: flags. */
- print_field_name (out, jcf, name, 0);
- fputs ("; }", out);
+ if (codes[4] == OPCODE_areturn)
+	decompile_return_statement (out, jcf, method_signature,
+				 name, JPOOL_USHORT2 (jcf, name_and_type));
+ else
+	{
+	 fputs (" { return ", out);
+	 /* FIXME: flags. */
+	 print_field_name (out, jcf, name, 0);
+	 fputs ("; }", out);
+	}
 decompiled = 1;
 }
 else if (code_len == 2
 	 && codes[0] == OPCODE_aload_0
 	 && codes[1] == OPCODE_areturn)
 {
- /* Found `return this'. */
- fputs (" { return this; }", out);
+ decompile_return_statement (out, jcf, method_signature, -1,
+				 JPOOL_USHORT1 (jcf, jcf->this_class));
 decompiled = 1;
 }
 else if (code_len == 1 && codes[0] == OPCODE_return)


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /