Bug 38393 - bytecode generated for evaluation with parentheses is wrong
Summary: bytecode generated for evaluation with parentheses is wrong
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.1   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.0 M2   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-06-03 19:02 EDT by Chris Tait CLA
Modified: 2003-07-16 06:50 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Tait CLA 2003-06-03 19:02:56 EDT
Expression evaluation should occur from left to right, but when parentheses are 
added to the right hand side of an expression, the bytecode generated by the 
JDT dictates that the RHS evaluation is first.

Consider the following java code:
public class EvalTest
{
	private static String n = null;
	
	public static void test1()
	{
		if (n == null || n.equals("") || true)
			System.out.println("null or \"\"");
		else
			System.out.println("other");
	}
	
	public static void test2()
	{
		if (n == null || (n.equals("") || true))  // *** note - extra 
set of parentheses in this line
			System.out.println("null or \"\"");
		else
			System.out.println("other");
	}
	
	public static void main(String[] args)
	{
		System.out.println("test1:");
		test1();
		System.out.println("test2:");
		test2();
	}
}

I would expect both of the above methods to evaluate the 'n == null' test first 
and since that evaluation returns true, they shouldn't evaluate the rest.  If I 
compile the above class using JAVAC then it works that way (the bytecode for 
test1 and test2 are identical).  If I compile it using the eclipse JDT then the 
bytecode for test1 is different to test2.  The test2 bytecode evaluates 
the 'n.equals("")' test first, which generates a NullPointerException.

Here's the bytecode produced by eclipse for the test1 and test2 methods:
Method void test1()
   0 getstatic #11 <Field java.lang.String n>
   3 ifnull 15
   6 getstatic #11 <Field java.lang.String n>
   9 ldc #21 <String "">
  11 invokevirtual #27 <Method boolean equals(java.lang.Object)>
  14 pop
  15 getstatic #33 <Field java.io.PrintStream out>
  18 ldc #35 <String "null or """>
  20 invokevirtual #41 <Method void println(java.lang.String)>
  23 return

Method void test2()
   0 getstatic #11 <Field java.lang.String n>
   3 ldc #21 <String "">
   5 invokevirtual #27 <Method boolean equals(java.lang.Object)>
   8 pop
   9 getstatic #33 <Field java.io.PrintStream out>
  12 ldc #35 <String "null or """>
  14 invokevirtual #41 <Method void println(java.lang.String)>
  17 return
Comment 1 Philipe Mulet CLA 2003-06-05 08:06:30 EDT
Given Java is left associate,

(n == null || n.equals("") || true)

is strictly equivalent to

((n == null || n.equal("")) || true)

however, I agree we have a bug, since in the end it shouldn't make a difference 
on this very example. The nuance however explains why we have this bug in this 
case (and in this case only).
Comment 2 Philipe Mulet CLA 2003-06-05 08:52:57 EDT
Similar defect on:

(n != null && (n.equal("")) && false))


Fix under testing.
Comment 3 Philipe Mulet CLA 2003-06-05 10:46:50 EDT
Fixed (will release after 3.0M1 is declared)
Comment 4 David Audel CLA 2003-07-16 06:50:57 EDT
Verified.