Bug 150074 - [compiler] init part of for each loop with empty body is not executed
Summary: [compiler] init part of for each loop with empty body is not executed
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.2.1   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-07-08 04:10 EDT by Sebastian Scheid CLA
Modified: 2006-09-12 04:47 EDT (History)
2 users (show)

See Also:


Attachments
Proposed fix (5.40 KB, patch)
2006-07-11 09:46 EDT, Olivier Thomann CLA
no flags Details | Diff
Another proposal (3.94 KB, patch)
2006-07-11 09:47 EDT, Olivier Thomann CLA
no flags Details | Diff
Regression test (3.64 KB, patch)
2006-07-11 09:48 EDT, Olivier Thomann CLA
no flags Details | Diff
Better patch (4.59 KB, patch)
2006-07-11 10:38 EDT, Olivier Thomann CLA
no flags Details | Diff
Regression tests (4.84 KB, patch)
2006-07-11 10:39 EDT, Olivier Thomann CLA
no flags Details | Diff
Last patch (6.31 KB, patch)
2006-07-12 12:02 EDT, Olivier Thomann CLA
no flags Details | Diff
Regression tests (22.51 KB, patch)
2006-07-12 12:02 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Sebastian Scheid CLA 2006-07-08 04:10:52 EDT
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
Comment 1 Philipe Mulet CLA 2006-07-08 06:42:38 EDT
This clearly would be our bug. I will investigate.
Comment 2 Olivier Thomann CLA 2006-07-10 13:30:01 EDT
I have a fix for it.
I'll test it tonight and I will attach it tomorrow.
Comment 3 Olivier Thomann CLA 2006-07-11 09:44:17 EDT
I'll provide two flavours of the fix.
Comment 4 Olivier Thomann CLA 2006-07-11 09:46:05 EDT
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.
Comment 5 Olivier Thomann CLA 2006-07-11 09:47:14 EDT
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.
Comment 6 Olivier Thomann CLA 2006-07-11 09:48:34 EDT
Created attachment 46072 [details]
Regression test
Comment 7 Olivier Thomann CLA 2006-07-11 10:38:25 EDT
Created attachment 46078 [details]
Better patch
Comment 8 Olivier Thomann CLA 2006-07-11 10:39:02 EDT
Created attachment 46079 [details]
Regression tests

Good candidate for 3.2.1.
Comment 9 Olivier Thomann CLA 2006-07-11 12:09:30 EDT
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.

Comment 10 Philipe Mulet CLA 2006-07-11 12:11:42 EDT
+1 for 3.2.1.
Comment 11 Olivier Thomann CLA 2006-07-12 05:54:50 EDT
Reopening. Need more work for optimizing the code gen in the array case.
Comment 12 Olivier Thomann CLA 2006-07-12 12:02:26 EDT
Created attachment 46180 [details]
Last patch
Comment 13 Olivier Thomann CLA 2006-07-12 12:02:59 EDT
Created attachment 46181 [details]
Regression tests
Comment 14 Olivier Thomann CLA 2006-07-12 12:04:09 EDT
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.
Comment 15 Frederic Fusier CLA 2006-08-08 05:08:51 EDT
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
Comment 16 David Audel CLA 2006-09-12 04:47:03 EDT
Verified for 3.2.1 using build M20060908-1655