Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java82
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java7
2 files changed, 89 insertions, 0 deletions
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 59f8347905..765e10dfac 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 @@ public void testBug396575() {
"----------\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 edbc2216a5..26e30f772b 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 @@ public class ForeachStatement extends Statement {
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 @@ public class ForeachStatement extends Statement {
}
} 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

Back to the top