Unspecified behaviour in java/gjavah.c

Diego Novillo dnovillo@redhat.com
Mon Nov 25 03:19:00 GMT 2002


After the latest merge from basic-improvements to tree-ssa, I
started getting failures building libjava:

-----------------------------------------------------------------------------
+ ../../gcc/gcjh -classpath '' -bootclasspath . java/lang/ThreadLocal
Premature end of .class file ./java/lang/ThreadLocal.class.
-----------------------------------------------------------------------------

I tracked down the problem to java/jcf-reader.c:skip_attribute.  The
.i file contains this:

-----------------------------------------------------------------------------
     1	static void
     2	skip_attribute (jcf, number_of_attribute)
     3	     JCF *jcf;
     4	     int number_of_attribute;
     5	{
     6	  while (number_of_attribute--)
     7	    {
     8	      ((jcf)->read_end-(jcf)->read_ptr >= (6) ? 0 : (*(jcf)->filbuf)(jcf, 6));
     9	      (void) ((jcf)->read_ptr += 2, ((((jcf)->read_ptr-2)[0] << 8) | (((jcf)->read_ptr-2)[1])));
    10	      ((jcf)->read_ptr += (((jcf)->read_ptr += 4, (((unsigned long)((jcf)->read_ptr-4)[0] << 24) | ((unsigned long)((jcf)->read_ptr-4)[1] << 16) | ((unsigned long)((jcf)->read_ptr-4)[2] << 8) | ((unsigned long)((jcf)->read_ptr-4)[3])))));
    11	    }
    12	}
-----------------------------------------------------------------------------

The problematic line is 10.  When we convert it to GIMPLE form,
the pre-merge version works fine, but the post-merge version
causes gjh to mess up the file pointer.  After discussing it with
a few folks, the consensus is that the code is invoking
unspecified behaviour.

Below is a minimal test case that exhibits the same problem:

-----------------------------------------------------------------------------
struct JCF {
  char *read_ptr;
} *jcf;

foo()
{
  jcf->read_ptr += (jcf->read_ptr += 4, 5);
}
-----------------------------------------------------------------------------

This is how the gimplified version looks like with the pre-merged
(good, on the left) and post-merged (bad, on the right) branch:

-----------------------------------------------------------------------------
$ diff -y -W80 good.c.t04.simple bad.c.t04.simple 
foo()                                   foo()
{                                       {
  char * T.1;                             char * T.1;
  char * T.2;                             char * T.2;

  T.1 = jcf->read_ptr;                    T.1 = jcf->read_ptr;
  jcf->read_ptr = T.1 + 4B;           <
  T.2 = jcf->read_ptr;                    T.2 = jcf->read_ptr;
  jcf->read_ptr = T.2 + 5B            |   jcf->read_ptr = T.2 + 4B;
                                      >   jcf->read_ptr = T.1 + 5B
}                                       }
-----------------------------------------------------------------------------

The reason why the two versions get gimplified differently is
because the front end is actually emitting different trees.  This
is the tree that the pre-merge gimplifier receives:

--- Pre-merge ---------------------------------------------------------------
Breakpoint 1, simplify_function_tree (fndecl=0x40079740)
    at /home/dnovillo/tree-ssa/src/gcc/gimplify.c:122
[ ... ]
(gdb) call print_c_tree(stdout,fnbody)
{ 
  jcf->read_ptr = jcf->read_ptr = jcf->read_ptr + 4B, jcf->read_ptr + 5B;
}
-----------------------------------------------------------------------------

And this is the tree that the post-merge gimplifier receives:

--- Post-merge --------------------------------------------------------------
Breakpoint 1, simplify_function_tree (fndecl=0x4007c4fc)
    at /home/dnovillo/merge-tree-ssa/src/gcc/gimplify.c:122
[ ... ]
(gdb) call print_c_tree (stdout,fnbody)
{
  jcf->read_ptr = jcf->read_ptr + (jcf->read_ptr = jcf->read_ptr + 4B, 5B);
}
-----------------------------------------------------------------------------

I have modified jcf-reader.c to avoid this, but I don't know the
code very well.  Is the patch below appropriate?


Thanks.  Diego.


	* java/jcf-reader.c: Don't expand JCF_readu4 inside the
	expansion of JCF_SKIP.

Index: jcf-reader.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-reader.c,v
retrieving revision 1.15
diff -d -u -p -r1.15 jcf-reader.c
--- jcf-reader.c	23 Mar 2001 19:42:25 -0000	1.15
+++ jcf-reader.c	25 Nov 2002 00:27:23 -0000
@@ -96,9 +96,11 @@ skip_attribute (jcf, number_of_attribute
 {
   while (number_of_attribute--)
     {
+      JCF_u4 N;
       JCF_FILL (jcf, 6);
       (void) JCF_readu2 (jcf);
-      JCF_SKIP (jcf, JCF_readu4 (jcf));
+      N = JCF_readu4 (jcf);
+      JCF_SKIP (jcf, N);
     }
 }
 #endif



More information about the Java mailing list