diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java index 5c83d04..3d7afcd 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java @@ -10,6 +10,7 @@ * Stephan Herrmann - Contributions for * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used * bug 349326 - [1.7] new warning for missing try-with-resources + * bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -30,6 +31,7 @@ public class FlowAnalysisTest extends AbstractRegressionTest { static { +// TESTS_NAMES = new String[] { "testLocalClassInInitializer1" }; // TESTS_NUMBERS = new int[] { 69 }; } public FlowAnalysisTest(String name) { @@ -2408,6 +2410,35 @@ }, ""); } +// Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) +// return/break/continue inside anonymous class inside try-catch inside initializer +public void testLocalClassInInitializer1() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " static {\n" + + " final int i=4;\n" + + " try {\n" + + " Runnable runner = new Runnable() {\n" + + " public void run() {\n" + + " switch (i) {" + + " case 4: break;\n" + + " }\n" + + " int j = i;\n" + + " while (j++ < 10) {\n" + + " if (j == 2) continue;\n" + + " if (j == 4) break;\n" + + " if (j == 6) return;\n" + + " }\n" + + " }\n" + + " };\n" + + " } catch (RuntimeException re) {}\n" + + " }\n" + + "}\n" + }, + ""); +} public static Class testClass() { return FlowAnalysisTest.class; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java index ca1e277..f2b6010 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java @@ -10,6 +10,7 @@ * Stephan Herrmann - Contributions for * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 349326 - [1.7] new warning for missing try-with-resources + * bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -37,6 +38,8 @@ // lookup the label, this should answer the returnContext + MethodScope methodScope = currentScope.methodScope(); + AbstractMethodDeclaration referenceMethod = methodScope.referenceMethod(); if (this.expression != null) { flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo); if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) { @@ -44,7 +47,7 @@ } FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression); if (trackingVariable != null) { - if (currentScope.methodScope() != trackingVariable.methodScope) + if (methodScope != trackingVariable.methodScope) trackingVariable.markClosedInNestedMethod(); // don't report issues concerning this local, since by returning // the method passes the responsibility to the caller: @@ -52,7 +55,7 @@ } } this.initStateIndex = - currentScope.methodScope().recordInitializationStates(flowInfo); + methodScope.recordInitializationStates(flowInfo); // compute the return sequence (running the finally blocks) FlowContext traversedContext = flowContext; int subCount = 0; @@ -89,13 +92,15 @@ } saveValueNeeded = true; this.initStateIndex = - currentScope.methodScope().recordInitializationStates(flowInfo); + methodScope.recordInitializationStates(flowInfo); } } } else if (traversedContext instanceof InitializationFlowContext) { currentScope.problemReporter().cannotReturnInInitializer(this); return FlowInfo.DEAD_END; } + if (traversedContext.associatedNode == referenceMethod) + break; // don't traverse beyond the enclosing method (see https://bugs.eclipse.org/360328). } while ((traversedContext = traversedContext.parent) != null); // resize subroutines