View | Details | Raw Unified | Return to bug 176472 | Differences between
and this patch

Collapse All | Expand All

(-)org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java (-1 / +7 lines)
Lines 46-51 Link Here
46
	FlowContext traversedContext = flowContext;
46
	FlowContext traversedContext = flowContext;
47
	int subCount = 0;
47
	int subCount = 0;
48
	this.subroutines = new SubRoutineStatement[5];
48
	this.subroutines = new SubRoutineStatement[5];
49
	boolean deferRecordBreakFrom = false;
49
	
50
	
50
	do {
51
	do {
51
		SubRoutineStatement sub;
52
		SubRoutineStatement sub;
Lines 68-75 Link Here
68
			}
69
			}
69
		} else if (traversedContext == targetContext) {
70
		} else if (traversedContext == targetContext) {
70
			// only record break info once accumulated through subroutines, and only against target context
71
			// only record break info once accumulated through subroutines, and only against target context
71
			targetContext.recordBreakFrom(flowInfo);
72
			if (! deferRecordBreakFrom) {
73
				targetContext.recordBreakFrom(flowInfo);
74
			}
72
			break;
75
			break;
76
		} else if (! deferRecordBreakFrom && traversedContext.preemptNullDiagnostic) {
77
			traversedContext.recordBreakFrom(flowInfo.unconditionalInitsWithoutSideEffect(), targetContext);
78
			deferRecordBreakFrom = true;
73
		}
79
		}
74
	} while ((traversedContext = traversedContext.parent) != null);
80
	} while ((traversedContext = traversedContext.parent) != null);
75
	
81
	
(-)org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java (-1 / +1 lines)
Lines 89-95 Link Here
89
			(this.action == null
89
			(this.action == null
90
				? actionInfo
90
				? actionInfo
91
				: (actionInfo.mergedWith(loopingContext.initsOnContinue))).copy());
91
				: (actionInfo.mergedWith(loopingContext.initsOnContinue))).copy());
92
	if (!isConditionOptimizedFalse && this.continueLabel != null) {
92
	if (!isConditionOptimizedFalse && this.continueLabel != null || loopingContext.breakTargetsNb != 0) {
93
		loopingContext.complainOnDeferredFinalChecks(currentScope, condInfo);
93
		loopingContext.complainOnDeferredFinalChecks(currentScope, condInfo);
94
		condLoopContext.complainOnDeferredFinalChecks(currentScope, condInfo);
94
		condLoopContext.complainOnDeferredFinalChecks(currentScope, condInfo);
95
		loopingContext.complainOnDeferredNullChecks(currentScope, 
95
		loopingContext.complainOnDeferredNullChecks(currentScope, 
(-)org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java (-1 / +1 lines)
Lines 121-127 Link Here
121
121
122
			if ((actionInfo.tagBits & 
122
			if ((actionInfo.tagBits & 
123
					loopingContext.initsOnContinue.tagBits &
123
					loopingContext.initsOnContinue.tagBits &
124
					FlowInfo.UNREACHABLE) != 0) {
124
					FlowInfo.UNREACHABLE) != 0 && loopingContext.breakTargetsNb == 0) {
125
				continueLabel = null;
125
				continueLabel = null;
126
				exitBranch.addInitializationsFrom(condInfo.initsWhenFalse());
126
				exitBranch.addInitializationsFrom(condInfo.initsWhenFalse());
127
			} else {
127
			} else {
(-)org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (-5 / +41 lines)
Lines 13-18 Link Here
13
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
13
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
14
import org.eclipse.jdt.internal.compiler.ast.Expression;
14
import org.eclipse.jdt.internal.compiler.ast.Expression;
15
import org.eclipse.jdt.internal.compiler.ast.Reference;
15
import org.eclipse.jdt.internal.compiler.ast.Reference;
16
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
16
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
17
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
17
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
Lines 32-37 Link Here
32
	private LoopingFlowContext innerFlowContexts[] = null;
33
	private LoopingFlowContext innerFlowContexts[] = null;
33
	private UnconditionalFlowInfo innerFlowInfos[] = null;
34
	private UnconditionalFlowInfo innerFlowInfos[] = null;
34
	private int innerFlowContextsNb = 0;
35
	private int innerFlowContextsNb = 0;
36
	private FlowContext breakTargetContexts[] = null;
37
	private UnconditionalFlowInfo breakTargetsInfo[] = null;
38
	public int breakTargetsNb = 0;
35
	
39
	
36
	Reference finalAssignments[];
40
	Reference finalAssignments[];
37
	VariableBinding finalVariables[];
41
	VariableBinding finalVariables[];
Lines 101-109 Link Here
101
/**
105
/**
102
 * Perform deferred checks relative to the null status of local variables.
106
 * Perform deferred checks relative to the null status of local variables.
103
 * @param scope the scope to which this context is associated
107
 * @param scope the scope to which this context is associated
104
 * @param flowInfo the flow info against which checks must be performed
108
 * @param callerFlowInfo the flow info against which checks must be performed
105
 */
109
 */
106
public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo flowInfo) {
110
public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo) {
107
	for (int i = 0 ; i < this.innerFlowContextsNb ; i++) {
111
	for (int i = 0 ; i < this.innerFlowContextsNb ; i++) {
108
		this.upstreamNullFlowInfo.
112
		this.upstreamNullFlowInfo.
109
			addPotentialNullInfoFrom(
113
			addPotentialNullInfoFrom(
Lines 111-119 Link Here
111
			addPotentialNullInfoFrom(this.innerFlowInfos[i]);
115
			addPotentialNullInfoFrom(this.innerFlowInfos[i]);
112
	}
116
	}
113
	this.innerFlowContextsNb = 0;
117
	this.innerFlowContextsNb = 0;
114
	flowInfo = this.upstreamNullFlowInfo.
118
	UnconditionalFlowInfo flowInfo = this.upstreamNullFlowInfo.
115
		addPotentialNullInfoFrom(
119
		addPotentialNullInfoFrom(callerFlowInfo.unconditionalInitsWithoutSideEffect());
116
			flowInfo.unconditionalInitsWithoutSideEffect());
117
	if (this.deferNullDiagnostic) {
120
	if (this.deferNullDiagnostic) {
118
		// check only immutable null checks on innermost looping context
121
		// check only immutable null checks on innermost looping context
119
		for (int i = 0; i < this.nullCount; i++) {
122
		for (int i = 0; i < this.nullCount; i++) {
Lines 247-252 Link Here
247
			}
250
			}
248
		}
251
		}
249
	}
252
	}
253
	// propagate breaks - see BreakStatement#analyseCode
254
	for (int i = 0; i < this.breakTargetsNb; i++) {
255
		UnconditionalFlowInfo breakFlowInfo = this.breakTargetsInfo[i].addPotentialNullInfoFrom(flowInfo);
256
		FlowContext traversedContext = this;
257
		do {
258
			if (traversedContext instanceof InsideSubRoutineFlowContext) {
259
				ASTNode node = traversedContext.associatedNode;
260
				if (node instanceof TryStatement) {
261
					TryStatement tryStatement = (TryStatement) node;
262
					breakFlowInfo.addInitializationsFrom(tryStatement.subRoutineInits);			
263
				}
264
			} else if (traversedContext == this.breakTargetContexts[i]) {
265
				traversedContext.recordBreakFrom(breakFlowInfo);
266
				break;
267
			} else if (traversedContext != this && traversedContext.preemptNullDiagnostic) {
268
				traversedContext.recordBreakFrom(breakFlowInfo, this.breakTargetContexts[i]);
269
				break;
270
			}
271
		} while ((traversedContext = traversedContext.parent) != null);
272
	}
250
}
273
}
251
	
274
	
252
	public BranchLabel continueLabel() {
275
	public BranchLabel continueLabel() {
Lines 270-275 Link Here
270
		return initsOnContinue != FlowInfo.DEAD_END;
293
		return initsOnContinue != FlowInfo.DEAD_END;
271
	}
294
	}
272
295
296
public void recordBreakFrom(UnconditionalFlowInfo flowInfo, FlowContext targetContext) {
297
	int current;
298
	if ((current = this.breakTargetsNb++) == 0) {
299
		this.breakTargetsInfo = new UnconditionalFlowInfo[2];
300
		this.breakTargetContexts = new FlowContext[2];
301
	} else if (current == this.breakTargetsInfo.length) {
302
		System.arraycopy(this.breakTargetsInfo, 0, this.breakTargetsInfo = new UnconditionalFlowInfo[current + 2], 0, current);
303
		System.arraycopy(this.breakTargetContexts, 0, this.breakTargetContexts = new FlowContext[current + 2], 0, current);
304
	}
305
	this.breakTargetsInfo[current] = flowInfo;
306
	this.breakTargetContexts[current] = targetContext;
307
}
308
273
public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) {
309
public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) {
274
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
310
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
275
	if ((initsOnContinue.tagBits & FlowInfo.UNREACHABLE) == 0) {
311
	if ((initsOnContinue.tagBits & FlowInfo.UNREACHABLE) == 0) {
(-)org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (-1 / +5 lines)
Lines 42-48 Link Here
42
		// only used within try blocks; remembers upstream flow info mergedWith
42
		// only used within try blocks; remembers upstream flow info mergedWith
43
		// any null related operation happening within the try block
43
		// any null related operation happening within the try block
44
		
44
		
45
boolean deferNullDiagnostic, preemptNullDiagnostic;
45
public boolean deferNullDiagnostic, preemptNullDiagnostic;
46
46
47
public FlowContext(FlowContext parent, ASTNode associatedNode) {
47
public FlowContext(FlowContext parent, ASTNode associatedNode) {
48
	this.parent = parent;
48
	this.parent = parent;
Lines 422-427 Link Here
422
	// default implementation: do nothing
422
	// default implementation: do nothing
423
}
423
}
424
424
425
public void recordBreakFrom(UnconditionalFlowInfo flowInfo, FlowContext targetContext) {
426
	// default implementation: do nothing
427
}
428
425
public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) {
429
public void recordContinueFrom(FlowContext innerFlowContext, FlowInfo flowInfo) {
426
	// default implementation: do nothing
430
	// default implementation: do nothing
427
}
431
}
(-)org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java (+18 lines)
Lines 1343-1348 Link Here
1343
		},
1343
		},
1344
		"1");
1344
		"1");
1345
}
1345
}
1346
// do while and named labels
1347
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
1348
// variant
1349
public void test047() {
1350
	this.runConformTest(
1351
		new String[] {
1352
			"X.java",
1353
			"public class X {\n" + 
1354
			"  public void foo() {\n" + 
1355
			"    done: do\n" + 
1356
			"      break done;\n" + 
1357
			"    while (false);\n" +
1358
			"    System.out.println();\n" + 
1359
			"  }\n" + 
1360
			"}\n",
1361
		},
1362
		"");
1363
}
1346
public static Class testClass() {
1364
public static Class testClass() {
1347
	return FlowAnalysisTest.class;
1365
	return FlowAnalysisTest.class;
1348
}
1366
}
(-)org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-6 / +144 lines)
Lines 3874-3880 Link Here
3874
// null analysis - while
3874
// null analysis - while
3875
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
3875
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
3876
// extraneous error in case of a labeled while(true) statement
3876
// extraneous error in case of a labeled while(true) statement
3877
public void _test0460_while_explicit_label() {
3877
public void test0460_while_explicit_label() {
3878
	this.runConformTest(
3878
	this.runConformTest(
3879
		new String[] {
3879
		new String[] {
3880
			"X.java",
3880
			"X.java",
Lines 3900-3916 Link Here
3900
// null analysis - while
3900
// null analysis - while
3901
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
3901
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
3902
// extraneous error in case of a labeled while(true) statement
3902
// extraneous error in case of a labeled while(true) statement
3903
public void _test0461_while_explicit_label() {
3903
public void test0461_while_explicit_label() {
3904
	this.runConformTest(
3904
	this.runConformTest(
3905
		new String[] {
3905
		new String[] {
3906
			"X.java",
3906
			"X.java",
3907
			"public class X {\n" + 
3907
			"public class X {\n" +
3908
			"  void foo(boolean b) {\n" + 
3908
			"  boolean test() {\n" +
3909
			"    return true;\n" +
3910
			"  }\n" + 
3911
			"  void foo() {\n" + 
3909
			"    Object o = null;\n" + 
3912
			"    Object o = null;\n" + 
3910
			"    done: while (true) {\n" + 
3913
			"    done: while (true) {\n" + 
3911
			"      if (b) {\n" + 
3914
			"      if (test()) {\n" + 
3912
			"        break done;\n" + 
3915
			"        break done;\n" + 
3913
			"      }\n" + 
3916
			"      }\n" +
3917
			"      o = new Object();\n" + 
3914
			"    }\n" + 
3918
			"    }\n" + 
3915
			"    if (o == null) {\n" + 
3919
			"    if (o == null) {\n" + 
3916
			"    }\n" + 
3920
			"    }\n" + 
Lines 5679-5684 Link Here
5679
	);
5683
	);
5680
}
5684
}
5681
5685
5686
// null analysis - do while
5687
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
5688
// variant
5689
public void test0616_do_while_explicit_label() {
5690
	this.runConformTest(
5691
		new String[] {
5692
			"X.java",
5693
			"public class X {\n" + 
5694
			"  void foo(int i) {\n" + 
5695
			"    Object o = null;\n" + 
5696
			"    done: do {\n" + 
5697
			"      switch (i) {\n" + 
5698
			"        case 0:\n" + 
5699
			"          o = new Object();\n" + 
5700
			"          break;\n" + 
5701
			"        case 1:\n" + 
5702
			"          break done;\n" + 
5703
			"      }\n" + 
5704
			"    } while (true);\n" + 
5705
			"    if (o == null) {\n" + 
5706
			"    }\n" + 
5707
			"  }\n" + 
5708
			"}\n"},
5709
		"");
5710
} 
5711
5712
// null analysis - do while
5713
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
5714
// variant
5715
public void test0617_do_while_explicit_label() {
5716
	this.runConformTest(
5717
		new String[] {
5718
			"X.java",
5719
			"public class X {\n" +
5720
			"  boolean test() {\n" +
5721
			"    return true;\n" +
5722
			"  }\n" + 
5723
			"  void foo() {\n" + 
5724
			"    Object o = null;\n" + 
5725
			"    done: do {\n" + 
5726
			"      if (test()) {\n" + 
5727
			"        break done;\n" + 
5728
			"      }\n" +
5729
			"      o = new Object();\n" + 
5730
			"    } while (true);\n" + 
5731
			"    if (o == null) {\n" + 
5732
			"    }\n" + 
5733
			"  }\n" + 
5734
			"}\n"},
5735
		"");
5736
} 
5737
5738
5682
// null analysis -- for
5739
// null analysis -- for
5683
public void test0701_for() {
5740
public void test0701_for() {
5684
	this.runNegativeTest(
5741
	this.runNegativeTest(
Lines 6496-6501 Link Here
6496
		"");
6553
		"");
6497
}
6554
}
6498
6555
6556
// null analysis - for
6557
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
6558
// variant
6559
public void test0739_for_explicit_label() {
6560
	this.runConformTest(
6561
		new String[] {
6562
			"X.java",
6563
			"public class X {\n" + 
6564
			"  void foo(int i) {\n" + 
6565
			"    Object o = null;\n" + 
6566
			"    done: for (;;) {\n" + 
6567
			"      switch (i) {\n" + 
6568
			"        case 0:\n" + 
6569
			"          o = new Object();\n" + 
6570
			"          break;\n" + 
6571
			"        case 1:\n" + 
6572
			"          break done;\n" + 
6573
			"      }\n" + 
6574
			"    }\n" + 
6575
			"    if (o == null) {\n" + 
6576
			"    }\n" + 
6577
			"  }\n" + 
6578
			"}\n"},
6579
		"");
6580
} 
6581
6582
// null analysis - for
6583
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
6584
// variant
6585
public void test0740_for_explicit_label() {
6586
	this.runConformTest(
6587
		new String[] {
6588
			"X.java",
6589
			"public class X {\n" +
6590
			"  boolean test() {\n" +
6591
			"    return true;\n" +
6592
			"  }\n" + 
6593
			"  void foo() {\n" + 
6594
			"    Object o = null;\n" + 
6595
			"    done: for (;;) {\n" + 
6596
			"      if (test()) {\n" + 
6597
			"        break done;\n" + 
6598
			"      }\n" +
6599
			"      o = new Object();\n" + 
6600
			"    }\n" + 
6601
			"    if (o == null) {\n" + 
6602
			"    }\n" + 
6603
			"  }\n" + 
6604
			"}\n"},
6605
		"");
6606
} 
6607
6608
// null analysis - for
6609
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=176472
6610
// variant
6611
public void test0741_for_explicit_label() {
6612
	if (COMPLIANCE_1_5.compareTo(this.complianceLevel) <= 0) {
6613
		this.runConformTest(
6614
			new String[] {
6615
				"X.java",
6616
				"import java.util.List;\n" + 
6617
				"public class X {\n" + 
6618
				"  void foo(int i, List<Object> l) {\n" + 
6619
				"    Object o = null;\n" + 
6620
				"    done: for (Object j: l) {\n" + 
6621
				"      switch (i) {\n" + 
6622
				"        case 0:\n" + 
6623
				"          o = new Object();\n" + 
6624
				"          break;\n" + 
6625
				"        case 1:\n" + 
6626
				"          break done;\n" + 
6627
				"      }\n" + 
6628
				"    }\n" + 
6629
				"    if (o == null) {\n" + 
6630
				"    }\n" + 
6631
				"  }\n" + 
6632
				"}\n"},
6633
			"");
6634
	}
6635
} 
6636
6499
// null analysis -- switch
6637
// null analysis -- switch
6500
public void test0800_switch() {
6638
public void test0800_switch() {
6501
	this.runConformTest(
6639
	this.runConformTest(

Return to bug 176472