Community
Participate
Working Groups
The compiler seems to optimize an empty for-each loop body by removing the complete for statement, so the initialization, which may have side effects, is skipped. The compiler behaves different with basic for loops where the init part is executed even if the body is empty. More important, the Sun compiler (1.5_05) does not remove the for-each init. Since the JLS states that "The meaning of the enhanced for statement is given by translation into a basic for statement" here http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.14.2 that must be a bug due to the different behavior of a for-each loop compared to the same loop translated to a basic for. Here is a demo class which behaves different when compiled with the Eclipse or the Sun compiler: ============================== public class Demo { public static void main(String[] args) { for (Object o : initForEach()) { // System.out.println("for-each loop"); } for (Iterator<Object> iter = initBasicFor().iterator(); iter.hasNext(); ) { // System.out.println("for loop"); iter.next(); // exact translation of for-each. Can be omitted when iter.isEmpty() and even then initBasicFor() is called. } } static Set<Object> initForEach() { System.out.println("initForEach"); return new HashSet<Object>(); } static Set<Object> initBasicFor() { System.out.println("initBasicEach"); return new HashSet<Object>(); } } ============================== The init() method is only called if the for-each loop is not empty when compiled by Eclipse whereas it is always called when compiled by Sun. Sun output: initForEach initBasicEach Eclipse output: initBasicEach
This clearly would be our bug. I will investigate.
I have a fix for it. I'll test it tonight and I will attach it tomorrow.
I'll provide two flavours of the fix.
Created attachment 46069 [details] Proposed fix First patch. An empty block is not seen as a specific case. I prefer this one. It looks more natural.
Created attachment 46070 [details] Another proposal Another patch that sees the empty block as a special case. In this case we do the possible side-effect from the inits and the condition.
Created attachment 46072 [details] Regression test
Created attachment 46078 [details] Better patch
Created attachment 46079 [details] Regression tests Good candidate for 3.2.1.
Patch and regression test released for 3.3 M1 in HEAD Patch and regression test released for 3.2.1 in R3_2_maintenance branch.
+1 for 3.2.1.
Reopening. Need more work for optimizing the code gen in the array case.
Created attachment 46180 [details] Last patch
Created attachment 46181 [details] Regression tests
Patch and regression tests released for 3.3 M1 in HEAD Patch and regression tests released for 3.2.1 in R3_2_maintenance branch. Regression tests are org.eclipse.jdt.core.tests.compiler.regression.ForeachStatementTest.test039/test046.
Verified for 3.3 M1 using build I20060807-2000. Note that: 1) ForeachStatementTest #test045 & #test046 do not fail with R3_2 version 2) Demo output with 3.2 build (M20060629-1905, v_671) is: initForEach initBasicEach 3) Demo output with 3.2M6 build is: initBasicEach
Verified for 3.2.1 using build M20060908-1655