### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java,v retrieving revision 1.38 diff -u -r1.38 LoopingFlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 6 Mar 2007 02:38:48 -0000 1.38 +++ compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 30 Mar 2007 09:23:41 -0000 @@ -32,6 +32,8 @@ private LoopingFlowContext innerFlowContexts[] = null; private UnconditionalFlowInfo innerFlowInfos[] = null; private int innerFlowContextsNb = 0; + private LabelFlowContext breakTargetContexts[] = null; + public int breakTargetsNb = 0; Reference finalAssignments[]; VariableBinding finalVariables[]; @@ -101,9 +103,9 @@ /** * Perform deferred checks relative to the null status of local variables. * @param scope the scope to which this context is associated - * @param flowInfo the flow info against which checks must be performed + * @param callerFlowInfo the flow info against which checks must be performed */ -public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo flowInfo) { +public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo) { for (int i = 0 ; i < this.innerFlowContextsNb ; i++) { this.upstreamNullFlowInfo. addPotentialNullInfoFrom( @@ -111,9 +113,8 @@ addPotentialNullInfoFrom(this.innerFlowInfos[i]); } this.innerFlowContextsNb = 0; - flowInfo = this.upstreamNullFlowInfo. - addPotentialNullInfoFrom( - flowInfo.unconditionalInitsWithoutSideEffect()); + UnconditionalFlowInfo flowInfo = this.upstreamNullFlowInfo. + addPotentialNullInfoFrom(callerFlowInfo.unconditionalInitsWithoutSideEffect()); if (this.deferNullDiagnostic) { // check only immutable null checks on innermost looping context for (int i = 0; i < this.nullCount; i++) { @@ -247,6 +248,10 @@ } } } + // propagate breaks + for (int i = 0; i < this.breakTargetsNb; i++) { + this.breakTargetContexts[i].initsOnBreak.addPotentialNullInfoFrom(flowInfo); + } } public BranchLabel continueLabel() { @@ -270,6 +275,18 @@ return initsOnContinue != FlowInfo.DEAD_END; } +public void recordBreakTo(FlowContext targetContext) { + if (targetContext instanceof LabelFlowContext) { + int current; + if ((current = this.breakTargetsNb++) == 0) { + this.breakTargetContexts = new LabelFlowContext[2]; + } else if (current == this.breakTargetContexts.length) { + System.arraycopy(this.breakTargetContexts, 0, this.breakTargetContexts = new LabelFlowContext[current + 2], 0, current); + } + this.breakTargetContexts[current] = (LabelFlowContext) targetContext; + } +} + public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { if ((initsOnContinue.tagBits & FlowInfo.UNREACHABLE) == 0) { Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java,v retrieving revision 1.56 diff -u -r1.56 FlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 6 Mar 2007 02:38:48 -0000 1.56 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 30 Mar 2007 09:23:40 -0000 @@ -422,6 +422,10 @@ // default implementation: do nothing } +public void recordBreakTo(FlowContext targetContext) { + // default implementation: do nothing +} + public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) { // default implementation: do nothing } Index: compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java,v retrieving revision 1.8 diff -u -r1.8 BreakStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java 23 Aug 2006 16:32:56 -0000 1.8 +++ compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java 30 Mar 2007 09:23:40 -0000 @@ -59,6 +59,7 @@ } } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); + traversedContext.recordBreakTo(targetContext); if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java,v retrieving revision 1.20 diff -u -r1.20 FlowAnalysisTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java 6 Dec 2006 16:56:38 -0000 1.20 +++ src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java 30 Mar 2007 09:23:47 -0000 @@ -1343,6 +1343,24 @@ }, "1"); } +// do while and named labels +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test047() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public void foo() {\n" + + " done: do\n" + + " break done;\n" + + " while (false);\n" + + " System.out.println();\n" + + " }\n" + + "}\n", + }, + ""); +} public static Class testClass() { return FlowAnalysisTest.class; } Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java,v retrieving revision 1.57 diff -u -r1.57 NullReferenceTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 27 Mar 2007 08:57:24 -0000 1.57 +++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 30 Mar 2007 09:24:02 -0000 @@ -3874,7 +3874,7 @@ // null analysis - while // https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 // extraneous error in case of a labeled while(true) statement -public void _test0460_while_explicit_label() { +public void test0460_while_explicit_label() { this.runConformTest( new String[] { "X.java", @@ -3900,17 +3900,55 @@ // null analysis - while // https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 // extraneous error in case of a labeled while(true) statement -public void _test0461_while_explicit_label() { +public void test0461_while_explicit_label() { this.runConformTest( new String[] { "X.java", - "public class X {\n" + - " void foo(boolean b) {\n" + + "public class X {\n" + + " boolean test() {\n" + + " return true;\n" + + " }\n" + + " void foo() {\n" + " Object o = null;\n" + " done: while (true) {\n" + - " if (b) {\n" + + " if (test()) {\n" + " break done;\n" + - " }\n" + + " }\n" + + " o = new Object();\n" + + " }\n" + + " if (o == null) {\n" + + " }\n" + + " }\n" + + "}\n"}, + ""); +} + +// null analysis - while +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test0462_while_explicit_label() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " boolean test() {\n" + + " return true;\n" + + " }\n" + + " void foo() {\n" + + " Object o = null;\n" + + " done: while (true) {\n" + + " try {\n" + + " while (true) {\n" + + " if (test()) {\n" + + " break done;\n" + + " }\n" + + " }\n" + + " }\n" + + " finally {\n" + + " if (test()) {\n" + + " o = new Object();\n" + + " }\n" + + " }\n" + " }\n" + " if (o == null) {\n" + " }\n" + @@ -5698,6 +5736,59 @@ ); } +// null analysis - do while +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test0616_do_while_explicit_label() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(int i) {\n" + + " Object o = null;\n" + + " done: do {\n" + + " switch (i) {\n" + + " case 0:\n" + + " o = new Object();\n" + + " break;\n" + + " case 1:\n" + + " break done;\n" + + " }\n" + + " } while (true);\n" + + " if (o == null) {\n" + + " }\n" + + " }\n" + + "}\n"}, + ""); +} + +// null analysis - do while +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test0617_do_while_explicit_label() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " boolean test() {\n" + + " return true;\n" + + " }\n" + + " void foo() {\n" + + " Object o = null;\n" + + " done: do {\n" + + " if (test()) {\n" + + " break done;\n" + + " }\n" + + " o = new Object();\n" + + " } while (true);\n" + + " if (o == null) {\n" + + " }\n" + + " }\n" + + "}\n"}, + ""); +} + + // null analysis -- for public void test0701_for() { this.runNegativeTest( @@ -6540,6 +6631,87 @@ } } +// null analysis - for +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test0740_for_explicit_label() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(int i) {\n" + + " Object o = null;\n" + + " done: for (;;) {\n" + + " switch (i) {\n" + + " case 0:\n" + + " o = new Object();\n" + + " break;\n" + + " case 1:\n" + + " break done;\n" + + " }\n" + + " }\n" + + " if (o == null) {\n" + + " }\n" + + " }\n" + + "}\n"}, + ""); +} + +// null analysis - for +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test0741_for_explicit_label() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " boolean test() {\n" + + " return true;\n" + + " }\n" + + " void foo() {\n" + + " Object o = null;\n" + + " done: for (;;) {\n" + + " if (test()) {\n" + + " break done;\n" + + " }\n" + + " o = new Object();\n" + + " }\n" + + " if (o == null) {\n" + + " }\n" + + " }\n" + + "}\n"}, + ""); +} + +// null analysis - for +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472 +// variant +public void test0742_for_explicit_label() { + if (COMPLIANCE_1_5.compareTo(this.complianceLevel) <= 0) { + this.runConformTest( + new String[] { + "X.java", + "import java.util.List;\n" + + "public class X {\n" + + " void foo(int i, List l) {\n" + + " Object o = null;\n" + + " done: for (Object j: l) {\n" + + " switch (i) {\n" + + " case 0:\n" + + " o = new Object();\n" + + " break;\n" + + " case 1:\n" + + " break done;\n" + + " }\n" + + " }\n" + + " if (o == null) {\n" + + " }\n" + + " }\n" + + "}\n"}, + ""); + } +} + // null analysis -- switch public void test0800_switch() { this.runConformTest(