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

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java (-1 / +52 lines)
Lines 2437-2443 Link Here
2437
				"    }\n" +
2437
				"    }\n" +
2438
				"}\n"
2438
				"}\n"
2439
			}, 
2439
			}, 
2440
			"");	
2440
			"");
2441
}
2442
// Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
2443
// return/break/continue inside anonymous class inside try-catch inside initializer
2444
public void testLocalClassInInitializer2() {
2445
	this.runNegativeTest(
2446
			new String[] {
2447
				"X.java",
2448
				"public class X {\n" +
2449
				"    void f () {\n" +
2450
				"        while (true) {\n" +
2451
				"            class Inner1 {\n" +
2452
				"                { if (true) break; }\n" +
2453
				"            }\n" +
2454
				"            new Inner1();\n" +
2455
				"        }\n" +
2456
				"    } \n" +
2457
				"    void g () {\n" +
2458
				"        outer: for (int i=1;true;i++) {\n" +
2459
				"            class Inner2 {\n" +
2460
				"                int j = 3;\n" +
2461
				"                void foo () {\n" +
2462
				"                  if (2 == j) continue outer;\n" +
2463
				"                  else continue;\n" +
2464
				"                }\n" +
2465
				"            }\n" +
2466
				"            new Inner2().foo();\n" +
2467
				"        }\n" +
2468
				"    } \n" +
2469
				"}\n"
2470
			}, 
2471
			"----------\n" + 
2472
			"1. ERROR in X.java (at line 5)\n" + 
2473
			"	{ if (true) break; }\n" + 
2474
			"	            ^^^^^^\n" + 
2475
			"break cannot be used outside of a loop or a switch\n" + 
2476
			"----------\n" + 
2477
			"2. WARNING in X.java (at line 11)\n" + 
2478
			"	outer: for (int i=1;true;i++) {\n" + 
2479
			"	^^^^^\n" + 
2480
			"The label outer is never explicitly referenced\n" + 
2481
			"----------\n" + 
2482
			"3. ERROR in X.java (at line 15)\n" + 
2483
			"	if (2 == j) continue outer;\n" + 
2484
			"	            ^^^^^^^^^^^^^^^\n" + 
2485
			"The label outer is missing\n" + 
2486
			"----------\n" + 
2487
			"4. ERROR in X.java (at line 16)\n" + 
2488
			"	else continue;\n" + 
2489
			"	     ^^^^^^^^^\n" + 
2490
			"continue cannot be used outside of a loop\n" + 
2491
			"----------\n");
2441
}
2492
}
2442
public static Class testClass() {
2493
public static Class testClass() {
2443
	return FlowAnalysisTest.class;
2494
	return FlowAnalysisTest.class;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 72-78 Link Here
72
			targetContext.recordBreakFrom(flowInfo);
72
			targetContext.recordBreakFrom(flowInfo);
73
			break;
73
			break;
74
		}
74
		}
75
	} while ((traversedContext = traversedContext.parent) != null);
75
	} while ((traversedContext = traversedContext.getLocalParent()) != null);
76
76
77
	// resize subroutines
77
	// resize subroutines
78
	if (subCount != this.subroutines.length) {
78
	if (subCount != this.subroutines.length) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 75-81 Link Here
75
			targetContext.recordContinueFrom(flowContext, flowInfo);
75
			targetContext.recordContinueFrom(flowContext, flowInfo);
76
			break;
76
			break;
77
		}
77
		}
78
	} while ((traversedContext = traversedContext.parent) != null);
78
	} while ((traversedContext = traversedContext.getLocalParent()) != null);
79
79
80
	// resize subroutines
80
	// resize subroutines
81
	if (subCount != this.subroutines.length) {
81
	if (subCount != this.subroutines.length) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (-3 / +1 lines)
Lines 99-107 Link Here
99
				currentScope.problemReporter().cannotReturnInInitializer(this);
99
				currentScope.problemReporter().cannotReturnInInitializer(this);
100
				return FlowInfo.DEAD_END;
100
				return FlowInfo.DEAD_END;
101
		}
101
		}
102
		if (traversedContext.associatedNode == referenceMethod)
102
	} while ((traversedContext = traversedContext.getLocalParent()) != null);
103
			break; // don't traverse beyond the enclosing method (see https://bugs.eclipse.org/360328).
104
	} while ((traversedContext = traversedContext.parent) != null);
105
103
106
	// resize subroutines
104
	// resize subroutines
107
	if ((this.subroutines != null) && (subCount != this.subroutines.length)) {
105
	if ((this.subroutines != null) && (subCount != this.subroutines.length)) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java (-2 / +2 lines)
Lines 70-81 Link Here
70
		// any reference reported at this level is removed from the parent context
70
		// any reference reported at this level is removed from the parent context
71
		// where it could also be reported again
71
		// where it could also be reported again
72
		if (complained) {
72
		if (complained) {
73
			FlowContext currentContext = this.parent;
73
			FlowContext currentContext = this.getLocalParent();
74
			while (currentContext != null) {
74
			while (currentContext != null) {
75
				//if (currentContext.isSubRoutine()) {
75
				//if (currentContext.isSubRoutine()) {
76
				currentContext.removeFinalAssignmentIfAny(this.finalAssignments[i]);
76
				currentContext.removeFinalAssignmentIfAny(this.finalAssignments[i]);
77
				//}
77
				//}
78
				currentContext = currentContext.parent;
78
				currentContext = currentContext.getLocalParent();
79
			}
79
			}
80
		}
80
		}
81
	}
81
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (-10 / +21 lines)
Lines 12-20 Link Here
12
package org.eclipse.jdt.internal.compiler.flow;
12
package org.eclipse.jdt.internal.compiler.flow;
13
13
14
import java.util.ArrayList;
14
import java.util.ArrayList;
15
15
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
17
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
17
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
18
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
18
import org.eclipse.jdt.internal.compiler.ast.Expression;
19
import org.eclipse.jdt.internal.compiler.ast.Expression;
19
import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
20
import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
20
import org.eclipse.jdt.internal.compiler.ast.Reference;
21
import org.eclipse.jdt.internal.compiler.ast.Reference;
Lines 207-213 Link Here
207
				}
208
				}
208
			}
209
			}
209
		}
210
		}
210
		traversedContext = traversedContext.parent;
211
		traversedContext = traversedContext.getLocalParent();
211
	}
212
	}
212
	// if reaches this point, then there are some remaining unhandled exception types.
213
	// if reaches this point, then there are some remaining unhandled exception types.
213
	if (isExceptionOnAutoClose) {
214
	if (isExceptionOnAutoClose) {
Lines 353-359 Link Here
353
				flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
354
				flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
354
			}
355
			}
355
		}
356
		}
356
		traversedContext = traversedContext.parent;
357
		traversedContext = traversedContext.getLocalParent();
357
	}
358
	}
358
	// if reaches this point, then there are some remaining unhandled exception types.
359
	// if reaches this point, then there are some remaining unhandled exception types.
359
	nextReport: for (int i = 0; i < raisedCount; i++) {
360
	nextReport: for (int i = 0; i < raisedCount; i++) {
Lines 385-393 Link Here
385
			current = initializationContext.initializationParent;
386
			current = initializationContext.initializationParent;
386
		} else if (current instanceof ExceptionHandlingFlowContext) {
387
		} else if (current instanceof ExceptionHandlingFlowContext) {
387
			ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) current;
388
			ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) current;
388
			current = exceptionContext.initializationParent == null ? exceptionContext.parent : exceptionContext.initializationParent;
389
			current = exceptionContext.initializationParent == null ? exceptionContext.getLocalParent() : exceptionContext.initializationParent;
389
		} else {
390
		} else {
390
			current = current.parent;
391
			current = current.getLocalParent();
391
		}
392
		}
392
	} while (current != null);
393
	} while (current != null);
393
	// not found
394
	// not found
Lines 411-417 Link Here
411
				return current;
412
				return current;
412
			return lastNonReturningSubRoutine;
413
			return lastNonReturningSubRoutine;
413
		}
414
		}
414
		current = current.parent;
415
		current = current.getLocalParent();
415
	}
416
	}
416
	// not found
417
	// not found
417
	return null;
418
	return null;
Lines 448-454 Link Here
448
			// label is found, but not a continuable location
449
			// label is found, but not a continuable location
449
			return FlowContext.NotContinuableContext;
450
			return FlowContext.NotContinuableContext;
450
		}
451
		}
451
		current = current.parent;
452
		current = current.getLocalParent();
452
	}
453
	}
453
	// not found
454
	// not found
454
	return null;
455
	return null;
Lines 467-473 Link Here
467
			if (lastNonReturningSubRoutine == null) return current;
468
			if (lastNonReturningSubRoutine == null) return current;
468
			return lastNonReturningSubRoutine;
469
			return lastNonReturningSubRoutine;
469
		}
470
		}
470
		current = current.parent;
471
		current = current.getLocalParent();
471
	}
472
	}
472
	// not found
473
	// not found
473
	return null;
474
	return null;
Lines 487-496 Link Here
487
				return current;
488
				return current;
488
			return lastNonReturningSubRoutine;
489
			return lastNonReturningSubRoutine;
489
		}
490
		}
490
		current = current.parent;
491
		current = current.getLocalParent();
491
	}
492
	}
492
	// not found
493
	// not found
493
	return null;
494
	return null;
495
}
496
497
/** 
498
 * Answer the parent flow context but be careful not to cross the boundary of a nested type,
499
 * or null if no such parent exists. 
500
 */
501
public FlowContext getLocalParent() {
502
	if (this.associatedNode instanceof AbstractMethodDeclaration || this.associatedNode instanceof TypeDeclaration)
503
		return null;
504
	return this.parent;
494
}
505
}
495
506
496
public String individualToString() {
507
public String individualToString() {
Lines 570-576 Link Here
570
		if (!context.recordFinalAssignment(variable, finalReference)) {
581
		if (!context.recordFinalAssignment(variable, finalReference)) {
571
			break; // no need to keep going
582
			break; // no need to keep going
572
		}
583
		}
573
		context = context.parent;
584
		context = context.getLocalParent();
574
	}
585
	}
575
	}
586
	}
576
}
587
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java (-3 / +3 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 31-44 Link Here
31
31
32
void checkLabelValidity(BlockScope scope) {
32
void checkLabelValidity(BlockScope scope) {
33
	// check if label was already defined above
33
	// check if label was already defined above
34
	FlowContext current = this.parent;
34
	FlowContext current = this.getLocalParent();
35
	while (current != null) {
35
	while (current != null) {
36
		char[] currentLabelName;
36
		char[] currentLabelName;
37
		if (((currentLabelName = current.labelName()) != null)
37
		if (((currentLabelName = current.labelName()) != null)
38
			&& CharOperation.equals(currentLabelName, this.labelName)) {
38
			&& CharOperation.equals(currentLabelName, this.labelName)) {
39
			scope.problemReporter().alreadyDefinedLabel(this.labelName, this.associatedNode);
39
			scope.problemReporter().alreadyDefinedLabel(this.labelName, this.associatedNode);
40
		}
40
		}
41
		current = current.parent;
41
		current = current.getLocalParent();
42
	}
42
	}
43
}
43
}
44
44
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (-2 / +3 lines)
Lines 112-121 Link Here
112
		// any reference reported at this level is removed from the parent context where it
112
		// any reference reported at this level is removed from the parent context where it
113
		// could also be reported again
113
		// could also be reported again
114
		if (complained) {
114
		if (complained) {
115
			FlowContext context = this.parent;
115
			FlowContext context = this.getLocalParent();
116
			while (context != null) {
116
			while (context != null) {
117
				context.removeFinalAssignmentIfAny(this.finalAssignments[i]);
117
				context.removeFinalAssignmentIfAny(this.finalAssignments[i]);
118
				context = context.parent;
118
				context = context.getLocalParent();
119
			}
119
			}
120
		}
120
		}
121
	}
121
	}
Lines 396-401 Link Here
396
		FlowContext inner = innerFlowContext;
396
		FlowContext inner = innerFlowContext;
397
		while (inner != this && !(inner instanceof LoopingFlowContext)) {
397
		while (inner != this && !(inner instanceof LoopingFlowContext)) {
398
			inner = inner.parent;
398
			inner = inner.parent;
399
			// we know that inner is reachable from this without crossing a type boundary 
399
		}
400
		}
400
		if (inner == this) {
401
		if (inner == this) {
401
			this.upstreamNullFlowInfo.
402
			this.upstreamNullFlowInfo.

Return to bug 360328