Community
Participate
Working Groups
Run this code under Eclipse: public class PostIncrementTest { public static void main(String[] args) { int a = 1; a = a++; System.out.println("a="+a); int b = 1; System.out.println(b = b++); System.out.println("b="+b); } } Result is: a=1 1 b=2 then compile and run this code using only javac and java commands, result is: a=1 1 b=1
Indeed it looks like we have a bug. We tagged b = b++ as having no effect (with a warning), but we change its value. I will check the bytecodes we produce.
The problem comes from the optimization for the assignment has no effect. In this case we generate the expression b++, but doing that this has a side effect if b is reloaded afterwards. And this is exactly what happens:` 0 iconst_1 1 istore_1 [a] 2 getstatic java.lang.System.out : java.io.PrintStream [16] 5 new java.lang.StringBuilder [22] 8 dup 9 ldc <String "a="> [24] 11 invokespecial java.lang.StringBuilder(java.lang.String) [26] 14 iload_1 [a] 15 invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [29] 18 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33] 21 invokevirtual java.io.PrintStream.println(java.lang.String) : void [37] 24 iconst_1 25 istore_2 [b] 26 getstatic java.lang.System.out : java.io.PrintStream [16] 29 iload_2 [b] 30 iinc 2 1 [b] <===== increments b 33 invokevirtual java.io.PrintStream.println(int) : void [42] 36 getstatic java.lang.System.out : java.io.PrintStream [16] 39 new java.lang.StringBuilder [22] 42 dup 43 ldc <String "b="> [45] 45 invokespecial java.lang.StringBuilder(java.lang.String) [26] 48 iload_2 [b] <===== reload b 49 invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [29] 52 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33] 55 invokevirtual java.io.PrintStream.println(java.lang.String) : void [37] 58 return the case with a works fine, because no value is required, so we don't generate a++. Philippe, we might want to turn the optimization off in case the expression is a postfix expression or we generate the left hand side in this case. Turning off the optimization fixed the issue.
b = b++; has no effect only if the assignment is complete generated. You need to assign the value back in b after generating the right hand side not to have an effect on b. Otherwise b has been incremented. So I think we should change only the code gen and preserves the actual warning for assignment with no effect.
Created attachment 28029 [details] Proposed fix Apply on the org.eclipse.jdt.internal.compiler.ast package. It seems that the patch wizard doesn't create unified patch anymore.
Created attachment 28031 [details] Proposed fix Same patch, but this one can be applied directly on the project.
In "b = b++", the assignment per se *has* some effect. It is nulling out the effect of "b++". So as opposed to other cases where assignment has no effect, the entire expression should be discarded. When value is still required, generating the lhs should suffice (no need to perform entire assignment). However, I am rather enclined to disable the check for this situation (which got added for bug 84480). Indeed, either we produce a different problem description: expression has no effect; rather than just assignment has no effect, since clients may be fooled into thinking they should remove only the assignment from source, and leave "b++" in the code. I don't think the code pattern is frequent enough it is worth it. Fixed, added AssignmentTest#test039, tuned Assignment#test035.
Backported to 3.1.maintenance (> 3.1.1)
*** Bug 118417 has been marked as a duplicate of this bug. ***
Verified for 3.2M4 in I20051212-2000
Verified for 3.1.2 in M20060109-0800.
Note that "a = ++a" could still be complained against. Added note to bug 100369