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