Bug 473317 - [compiler][resource] AutoCloseable used in enhanced for
loop not flagged as "never closed"

Change-Id: I213e88f530fd82b45f91632aabf4efe77db61271
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
index 59f8347..765e10d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
@@ -5355,4 +5355,86 @@
 		"----------\n",
 		options);
 }
+public void testBug473317() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // using diamond
+	Map<String, String> compilerOptions = getCompilerOptions();
+	compilerOptions.put(JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION, JavaCore.IGNORE);
+	runLeakTest(
+		new String[] {
+			"AutoCloseableEnhancedForTest.java",
+			"import java.util.Iterator;\n" + 
+			"\n" + 
+			"public class AutoCloseableEnhancedForTest\n" + 
+			"{\n" + 
+			"   private static class MyIterator<T> implements Iterator<T>\n" + 
+			"   {\n" + 
+			"      private T value;\n" + 
+			"      \n" + 
+			"      public MyIterator(T value)\n" + 
+			"      {\n" + 
+			"         this.value = value;\n" + 
+			"      }\n" + 
+			"      \n" + 
+			"      @Override\n" + 
+			"      public boolean hasNext()\n" + 
+			"      {\n" + 
+			"         return false;\n" + 
+			"      }\n" + 
+			"\n" + 
+			"      @Override\n" + 
+			"      public T next()\n" + 
+			"      {\n" + 
+			"         return value;\n" + 
+			"      }\n" + 
+			"   }\n" + 
+			"   \n" + 
+			"   private static class MyIterable<T> implements Iterable<T>, AutoCloseable\n" + 
+			"   {\n" + 
+			"      @Override\n" + 
+			"      public Iterator<T> iterator()\n" + 
+			"      {\n" + 
+			"         return new MyIterator<>(null);\n" + 
+			"      }\n" + 
+			"      \n" + 
+			"      @Override\n" + 
+			"      public void close() throws Exception\n" + 
+			"      {\n" + 
+			"      }\n" + 
+			"   }\n" + 
+			"   \n" + 
+			"   public static void main(String[] args)\n" + 
+			"   {\n" + 
+			"      // Not flagged as \"never closed.\"\n" + 
+			"      for (Object value : new MyIterable<>())\n" + 
+			"      {\n" + 
+			"         System.out.println(String.valueOf(value));\n" + 
+			"         \n" + 
+			"         break;\n" + 
+			"      }\n" + 
+			"      \n" + 
+			"      // Flagged as \"never closed.\"\n" + 
+			"      MyIterable<Object> iterable = new MyIterable<>();\n" + 
+			"      \n" + 
+			"      for (Object value : iterable)\n" + 
+			"      {\n" + 
+			"         System.out.println(String.valueOf(value));\n" + 
+			"         \n" + 
+			"         break;\n" + 
+			"      }\n" + 
+			"   }\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. WARNING in AutoCloseableEnhancedForTest.java (at line 44)\n" + 
+		"	for (Object value : new MyIterable<>())\n" + 
+		"	                    ^^^^^^^^^^^^^^^^^^\n" + 
+		"Resource leak: \'<unassigned Closeable value>\' is never closed\n" + 
+		"----------\n" + 
+		"2. WARNING in AutoCloseableEnhancedForTest.java (at line 52)\n" + 
+		"	MyIterable<Object> iterable = new MyIterable<>();\n" + 
+		"	                   ^^^^^^^^\n" + 
+		"Resource leak: \'iterable\' is never closed\n" + 
+		"----------\n",
+		compilerOptions);
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index edbc221..26e30f7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -131,6 +131,10 @@
 
 			if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) {
 				actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy();
+				if (this.action instanceof Block) {
+					// action.analyseCode() missed the following check due to identical scopes of ForeachStatement and Block:
+					this.scope.checkUnclosedCloseables(actionInfo, loopingContext, null, null);
+				}
 			}
 
 			// code generation can be optimized when no need to continue in the loop
@@ -147,6 +151,9 @@
 			}
 		} else {
 			exitBranch = condInfo.initsWhenFalse();
+			if (this.action instanceof Block && !this.action.isEmptyBlock()) {
+				this.scope.checkUnclosedCloseables(actionInfo, loopingContext, null, null);
+			}
 		}
 
 		// we need the variable to iterate the collection even if the