Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 247564 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/core/compiler/IProblem.java (-1 / +21 lines)
Lines 359-365 Link Here
359
	int DuplicateBlankFinalFieldInitialization = FieldRelated + 82;
359
	int DuplicateBlankFinalFieldInitialization = FieldRelated + 82;
360
	/** @since 3.6 */
360
	/** @since 3.6 */
361
	int UnresolvedVariable = FieldRelated + 83;
361
	int UnresolvedVariable = FieldRelated + 83;
362
362
	
363
	// variable hiding
363
	// variable hiding
364
	/** @since 3.0 */
364
	/** @since 3.0 */
365
	int LocalVariableHidingLocalVariable = Internal + 90;
365
	int LocalVariableHidingLocalVariable = Internal + 90;
Lines 1245-1250 Link Here
1245
    /** @since 3.4 */
1245
    /** @since 3.4 */
1246
    int UnusedTypeArgumentsForConstructorInvocation = MethodRelated + 660;
1246
    int UnusedTypeArgumentsForConstructorInvocation = MethodRelated + 660;
1247
1247
1248
    /**
1249
	 * Null analysis for fields
1250
	 */
1251
    /** @since 3.7 */
1252
	int NullFieldReference = Internal + FieldRelated + 670;
1253
	/** @since 3.7 */
1254
	int PotentialNullFieldReference = Internal + FieldRelated + 671;
1255
	/** @since 3.7 */
1256
	int RedundantNullCheckOnNullField = Internal + FieldRelated + 672;
1257
	/** @since 3.7 */
1258
	int NullFieldComparisonYieldsFalse = Internal + FieldRelated + 673;
1259
	/** @since 3.7 */
1260
	int RedundantNullCheckOnNonNullField = Internal + FieldRelated + 674;
1261
	/** @since 3.7 */
1262
	int NonNullFieldComparisonYieldsFalse = Internal + FieldRelated + 675;
1263
	/** @since 3.7 */
1264
	int RedundantFieldNullAssignment = Internal + FieldRelated + 676;
1265
	/** @since 3.7 */
1266
	int NullFieldInstanceofYieldsFalse = Internal + FieldRelated + 677;
1267
	
1248
	/**
1268
	/**
1249
	 * Corrupted binaries
1269
	 * Corrupted binaries
1250
	 */
1270
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-3 / +13 lines)
Lines 38-44 Link Here
38
	// record setting a variable: various scenarii are possible, setting an array reference,
38
	// record setting a variable: various scenarii are possible, setting an array reference,
39
// a field reference, a blank final field reference, a field of an enclosing instance or
39
// a field reference, a blank final field reference, a field of an enclosing instance or
40
// just a local variable.
40
// just a local variable.
41
	LocalVariableBinding local = this.lhs.localVariableBinding();
41
	VariableBinding local = this.lhs.variableBinding();
42
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
42
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
43
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
43
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
44
	}
44
	}
Lines 53-61 Link Here
53
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
53
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
54
		.unconditionalInits();
54
		.unconditionalInits();
55
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
55
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
56
		flowInfo.markNullStatus(local, nullStatus);
56
		boolean isSynchronised = currentScope.isOuterMostMethodSynchronised();
57
		flowInfo.markNullStatus(local, nullStatus, isSynchronised);
57
		if (flowContext.initsOnFinally != null)
58
		if (flowContext.initsOnFinally != null)
58
			flowContext.initsOnFinally.markNullStatus(local, nullStatus);
59
			flowContext.initsOnFinally.markNullStatus(local, nullStatus, isSynchronised);
60
		if (local instanceof FieldBinding && local.isFinal() && ((FieldBinding) local).isStatic()) {
61
			// static final field being assigned. Record its null status for future reference
62
			// since the flowInfo from a constructor or static block wont be available in a method
63
			FieldBinding fieldBinding = (FieldBinding) local;
64
			fieldBinding.setNullStatusForStaticFinalField(nullStatus);
65
		}
59
	}
66
	}
60
	return flowInfo;
67
	return flowInfo;
61
}
68
}
Lines 205-208 Link Here
205
public LocalVariableBinding localVariableBinding() {
212
public LocalVariableBinding localVariableBinding() {
206
	return this.lhs.localVariableBinding();
213
	return this.lhs.localVariableBinding();
207
}
214
}
215
public VariableBinding variableBinding() {
216
	return this.lhs.variableBinding();
217
}
208
}
218
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Block.java (-1 / +3 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 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 36-41 Link Here
36
			flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo);
36
			flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo);
37
		}
37
		}
38
	}
38
	}
39
	// don't let the flow info collected for fields from this block persist.
40
	flowInfo.resetNullInfoForFields();
39
	return flowInfo;
41
	return flowInfo;
40
}
42
}
41
/**
43
/**
(-)compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java (+8 lines)
Lines 32-37 Link Here
32
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
32
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
33
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
33
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
34
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
34
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
35
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
35
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
36
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
36
37
37
public class CastExpression extends Expression {
38
public class CastExpression extends Expression {
Lines 444-449 Link Here
444
	return this.expression.localVariableBinding();
445
	return this.expression.localVariableBinding();
445
}
446
}
446
447
448
/**
449
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#variableBinding()
450
 */
451
public VariableBinding variableBinding() {
452
	return this.expression.variableBinding();
453
}
454
447
public int nullStatus(FlowInfo flowInfo) {
455
public int nullStatus(FlowInfo flowInfo) {
448
	return this.expression.nullStatus(flowInfo);
456
	return this.expression.nullStatus(flowInfo);
449
}
457
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java (-8 / +9 lines)
Lines 24-51 Link Here
24
	}
24
	}
25
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
25
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
26
26
27
		LocalVariableBinding local = this.left.localVariableBinding();
27
		VariableBinding local = this.left.variableBinding();
28
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
28
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
29
			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, this.right.nullStatus(flowInfo), this.left);
29
			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, this.right.nullStatus(flowInfo), this.left);
30
		}
30
		}
31
		local = this.right.localVariableBinding();
31
		local = this.right.variableBinding();
32
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
32
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
33
			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, this.left.nullStatus(flowInfo), this.right);
33
			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, this.left.nullStatus(flowInfo), this.right);
34
		}
34
		}
35
	}
35
	}
36
	private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
36
	private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, VariableBinding local, int nullStatus, Expression reference) {
37
		boolean isSynchronised = scope.isOuterMostMethodSynchronised();
37
		switch (nullStatus) {
38
		switch (nullStatus) {
38
			case FlowInfo.NULL :
39
			case FlowInfo.NULL :
39
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
40
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
40
					flowContext.recordUsingNullReference(scope, local, reference,
41
					flowContext.recordUsingNullReference(scope, local, reference,
41
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo);
42
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo);
42
					initsWhenTrue.markAsComparedEqualToNull(local); // from thereon it is set
43
					initsWhenTrue.markAsComparedEqualToNull(local, isSynchronised); // from thereon it is set
43
					initsWhenFalse.markAsComparedEqualToNonNull(local); // from thereon it is set
44
					initsWhenFalse.markAsComparedEqualToNonNull(local, isSynchronised ); // from thereon it is set
44
				} else {
45
				} else {
45
					flowContext.recordUsingNullReference(scope, local, reference,
46
					flowContext.recordUsingNullReference(scope, local, reference,
46
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
47
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
47
					initsWhenTrue.markAsComparedEqualToNonNull(local); // from thereon it is set
48
					initsWhenTrue.markAsComparedEqualToNonNull(local, isSynchronised); // from thereon it is set
48
					initsWhenFalse.markAsComparedEqualToNull(local); // from thereon it is set
49
					initsWhenFalse.markAsComparedEqualToNull(local, isSynchronised); // from thereon it is set
49
				}
50
				}
50
				if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
51
				if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
51
					flowInfo.markedAsNullOrNonNullInAssertExpression(local);
52
					flowInfo.markedAsNullOrNonNullInAssertExpression(local);
Lines 55-61 Link Here
55
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
56
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
56
					flowContext.recordUsingNullReference(scope, local, reference,
57
					flowContext.recordUsingNullReference(scope, local, reference,
57
							FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
58
							FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
58
					initsWhenTrue.markAsComparedEqualToNonNull(local); // from thereon it is set
59
					initsWhenTrue.markAsComparedEqualToNonNull(local, isSynchronised); // from thereon it is set
59
					if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
60
					if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
60
						initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local);
61
						initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local);
61
					}
62
					}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java (-4 / +14 lines)
Lines 35-40 Link Here
35
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
35
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
39
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
39
import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
40
import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
40
import org.eclipse.jdt.internal.compiler.util.Messages;
41
import org.eclipse.jdt.internal.compiler.util.Messages;
Lines 503-522 Link Here
503
 * @param flowInfo the upstream flow info; caveat: may get modified
504
 * @param flowInfo the upstream flow info; caveat: may get modified
504
 */
505
 */
505
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
506
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
506
	LocalVariableBinding local = localVariableBinding();
507
	VariableBinding local = variableBinding();
507
	if (local != null &&
508
	if (local != null &&
508
			(local.type.tagBits & TagBits.IsBaseType) == 0) {
509
			(local.type.tagBits & TagBits.IsBaseType) == 0) {
509
		if ((this.bits & ASTNode.IsNonNull) == 0) {
510
		if ((this.bits & ASTNode.IsNonNull) == 0) {
510
			flowContext.recordUsingNullReference(scope, local, this,
511
			flowContext.recordUsingNullReference(scope, local, this,
511
					FlowContext.MAY_NULL, flowInfo);
512
					FlowContext.MAY_NULL, flowInfo);
512
		}
513
		}
513
		flowInfo.markAsComparedEqualToNonNull(local);
514
		boolean isSynchronised = scope.isOuterMostMethodSynchronised();
515
		flowInfo.markAsComparedEqualToNonNull(local, isSynchronised );
514
			// from thereon it is set
516
			// from thereon it is set
515
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
517
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
516
			flowInfo.markedAsNullOrNonNullInAssertExpression(local);
518
			flowInfo.markedAsNullOrNonNullInAssertExpression(local);
517
		}
519
		}
518
		if (flowContext.initsOnFinally != null) {
520
		if (flowContext.initsOnFinally != null) {
519
			flowContext.initsOnFinally.markAsComparedEqualToNonNull(local);
521
			flowContext.initsOnFinally.markAsComparedEqualToNonNull(local, isSynchronised);
520
			if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
522
			if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
521
				flowContext.initsOnFinally.markedAsNullOrNonNullInAssertExpression(local);
523
				flowContext.initsOnFinally.markedAsNullOrNonNullInAssertExpression(local);
522
			}
524
			}
Lines 843-849 Link Here
843
		this.constant != null && this.constant != Constant.NotAConstant)
845
		this.constant != null && this.constant != Constant.NotAConstant)
844
	return FlowInfo.NON_NULL; // constant expression cannot be null
846
	return FlowInfo.NON_NULL; // constant expression cannot be null
845
847
846
	LocalVariableBinding local = localVariableBinding();
848
	VariableBinding local = variableBinding();
847
	if (local != null)
849
	if (local != null)
848
		return flowInfo.nullStatus(local);
850
		return flowInfo.nullStatus(local);
849
	return FlowInfo.NON_NULL;
851
	return FlowInfo.NON_NULL;
Lines 1049-1052 Link Here
1049
public void traverse(ASTVisitor visitor, ClassScope scope) {
1051
public void traverse(ASTVisitor visitor, ClassScope scope) {
1050
	// nothing to do
1052
	// nothing to do
1051
}
1053
}
1054
1055
/**
1056
 * Returns the field or local variable referenced by this node. Can be a direct reference (SingleNameReference)
1057
 * or thru a cast expression etc...
1058
 */
1059
public VariableBinding variableBinding() {
1060
	return null;
1061
}
1052
}
1062
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java (+7 lines)
Lines 74-79 Link Here
74
				.analyseCode(initializationScope, flowContext, flowInfo)
74
				.analyseCode(initializationScope, flowContext, flowInfo)
75
				.unconditionalInits();
75
				.unconditionalInits();
76
		flowInfo.markAsDefinitelyAssigned(this.binding);
76
		flowInfo.markAsDefinitelyAssigned(this.binding);
77
		if (this.binding.isFinal() && this.binding.isStatic()) {
78
			int nullStatus = this.initialization.nullStatus(flowInfo);
79
			// static final field being initialized. Record its null status for future reference
80
			// since the flowInfo from an initialization wont be available in a method
81
			
82
			this.binding.setNullStatusForStaticFinalField(nullStatus);
83
		}
77
	}
84
	}
78
	return flowInfo;
85
	return flowInfo;
79
}
86
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (+6 lines)
Lines 35-40 Link Here
35
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
35
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
38
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
38
39
39
public class FieldReference extends Reference implements InvocationSite {
40
public class FieldReference extends Reference implements InvocationSite {
40
41
Lines 668-671 Link Here
668
	}
669
	}
669
	visitor.endVisit(this, scope);
670
	visitor.endVisit(this, scope);
670
}
671
}
672
673
public VariableBinding variableBinding() {
674
	return this.binding;
675
}
676
671
}
677
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java (-5 / +6 lines)
Lines 31-46 Link Here
31
}
31
}
32
32
33
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
33
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
34
	LocalVariableBinding local = this.expression.localVariableBinding();
34
	VariableBinding variable = this.expression.variableBinding();
35
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
35
	if (variable != null && (variable.type.tagBits & TagBits.IsBaseType) == 0) {
36
		flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo).
36
		flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo).
37
			unconditionalInits();
37
			unconditionalInits();
38
		FlowInfo initsWhenTrue = flowInfo.copy();
38
		FlowInfo initsWhenTrue = flowInfo.copy();
39
		initsWhenTrue.markAsComparedEqualToNonNull(local);
39
		boolean isSynchronised = currentScope.isOuterMostMethodSynchronised();
40
		initsWhenTrue.markAsComparedEqualToNonNull(variable, isSynchronised );
40
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
41
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
41
			initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local);
42
			initsWhenTrue.markedAsNullOrNonNullInAssertExpression(variable);
42
		}
43
		}
43
		flowContext.recordUsingNullReference(currentScope, local,
44
		flowContext.recordUsingNullReference(currentScope, variable,
44
				this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo);
45
				this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo);
45
		// no impact upon enclosing try context
46
		// no impact upon enclosing try context
46
		return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
47
		return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
(-)compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-1 / +2 lines)
Lines 81-87 Link Here
81
	}
81
	}
82
	flowInfo.markAsDefinitelyAssigned(this.binding);
82
	flowInfo.markAsDefinitelyAssigned(this.binding);
83
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
83
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
84
		flowInfo.markNullStatus(this.binding, nullStatus);
84
		boolean isSynchronised = currentScope.isOuterMostMethodSynchronised();
85
		flowInfo.markNullStatus(this.binding, nullStatus, isSynchronised );
85
		// no need to inform enclosing try block since its locals won't get
86
		// no need to inform enclosing try block since its locals won't get
86
		// known by the finally block
87
		// known by the finally block
87
	}
88
	}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (+3 lines)
Lines 95-100 Link Here
95
		//               NullReferenceTest#test0510
95
		//               NullReferenceTest#test0510
96
	}
96
	}
97
	manageSyntheticAccessIfNecessary(currentScope, flowInfo);
97
	manageSyntheticAccessIfNecessary(currentScope, flowInfo);
98
	// a method call can result in changed values for fields, 
99
	// so wipe out null info for fields collected till now.
100
	flowInfo.resetNullInfoForFields();
98
	return flowInfo;
101
	return flowInfo;
99
}
102
}
100
/**
103
/**
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java (+2 lines)
Lines 134-139 Link Here
134
				}
134
				}
135
					
135
					
136
			}
136
			}
137
			// don't let the flow info collected for fields from this method persist.
138
			flowInfo.resetNullInfoForFields();
137
		} catch (AbortMethod e) {
139
		} catch (AbortMethod e) {
138
			this.ignoreFurtherInvestigation = true;
140
			this.ignoreFurtherInvestigation = true;
139
		}
141
		}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-2 / +3 lines)
Lines 235-247 Link Here
235
				flowContext.recordUsingNullReference(scope, local, this,
235
				flowContext.recordUsingNullReference(scope, local, this,
236
					FlowContext.MAY_NULL, flowInfo);
236
					FlowContext.MAY_NULL, flowInfo);
237
			}
237
			}
238
			flowInfo.markAsComparedEqualToNonNull(local);
238
			boolean isSynchronised = scope.isOuterMostMethodSynchronised();
239
			flowInfo.markAsComparedEqualToNonNull(local, isSynchronised );
239
			// from thereon it is set
240
			// from thereon it is set
240
			if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
241
			if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
241
				flowInfo.markedAsNullOrNonNullInAssertExpression(local);
242
				flowInfo.markedAsNullOrNonNullInAssertExpression(local);
242
			}
243
			}
243
			if (flowContext.initsOnFinally != null) {
244
			if (flowContext.initsOnFinally != null) {
244
				flowContext.initsOnFinally.markAsComparedEqualToNonNull(local);
245
				flowContext.initsOnFinally.markAsComparedEqualToNonNull(local, isSynchronised);
245
				if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
246
				if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
246
					flowContext.initsOnFinally.markedAsNullOrNonNullInAssertExpression(local);
247
					flowContext.initsOnFinally.markedAsNullOrNonNullInAssertExpression(local);
247
				}
248
				}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-4 / +12 lines)
Lines 807-812 Link Here
807
	return null;
807
	return null;
808
}
808
}
809
809
810
public VariableBinding variableBinding() {
811
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
812
		case Binding.FIELD : 
813
			// reading a field
814
		case Binding.LOCAL : // reading a local variable
815
			return (VariableBinding) this.binding;
816
	}
817
	return null;
818
}
810
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
819
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
811
	//If inlinable field, forget the access emulation, the code gen will directly target it
820
	//If inlinable field, forget the access emulation, the code gen will directly target it
812
	if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) {
821
	if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) {
Lines 859-869 Link Here
859
	}
868
	}
860
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
869
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
861
		case Binding.FIELD : // reading a field
870
		case Binding.FIELD : // reading a field
862
			return FlowInfo.UNKNOWN;
863
		case Binding.LOCAL : // reading a local variable
871
		case Binding.LOCAL : // reading a local variable
864
			LocalVariableBinding local = (LocalVariableBinding) this.binding;
872
			VariableBinding variable = (VariableBinding) this.binding;
865
			if (local != null)
873
			if (variable != null)
866
				return flowInfo.nullStatus(local);
874
				return flowInfo.nullStatus(variable);
867
	}
875
	}
868
	return FlowInfo.NON_NULL; // never get there
876
	return FlowInfo.NON_NULL; // never get there
869
}
877
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-2 / +3 lines)
Lines 80-85 Link Here
80
	if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
80
	if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
81
		this.returnAddressVariable.useFlag = LocalVariableBinding.USED;
81
		this.returnAddressVariable.useFlag = LocalVariableBinding.USED;
82
	}
82
	}
83
	boolean isSynchronised = currentScope.isOuterMostMethodSynchronised();
83
	if (this.subRoutineStartLabel == null) {
84
	if (this.subRoutineStartLabel == null) {
84
		// no finally block -- this is a simplified copy of the else part
85
		// no finally block -- this is a simplified copy of the else part
85
		// process the try block in a context handling the local exceptions.
86
		// process the try block in a context handling the local exceptions.
Lines 141-147 Link Here
141
				// catch var is always set
142
				// catch var is always set
142
				LocalVariableBinding catchArg = this.catchArguments[i].binding;
143
				LocalVariableBinding catchArg = this.catchArguments[i].binding;
143
				catchInfo.markAsDefinitelyAssigned(catchArg);
144
				catchInfo.markAsDefinitelyAssigned(catchArg);
144
				catchInfo.markAsDefinitelyNonNull(catchArg);
145
				catchInfo.markAsDefinitelyNonNull(catchArg, isSynchronised);
145
				/*
146
				/*
146
				"If we are about to consider an unchecked exception handler, potential inits may have occured inside
147
				"If we are about to consider an unchecked exception handler, potential inits may have occured inside
147
				the try block that need to be detected , e.g.
148
				the try block that need to be detected , e.g.
Lines 250-256 Link Here
250
				// catch var is always set
251
				// catch var is always set
251
				LocalVariableBinding catchArg = this.catchArguments[i].binding;
252
				LocalVariableBinding catchArg = this.catchArguments[i].binding;
252
				catchInfo.markAsDefinitelyAssigned(catchArg);
253
				catchInfo.markAsDefinitelyAssigned(catchArg);
253
				catchInfo.markAsDefinitelyNonNull(catchArg);
254
				catchInfo.markAsDefinitelyNonNull(catchArg, isSynchronised);
254
				/*
255
				/*
255
				"If we are about to consider an unchecked exception handler, potential inits may have occured inside
256
				"If we are about to consider an unchecked exception handler, potential inits may have occured inside
256
				the try block that need to be detected , e.g.
257
				the try block that need to be detected , e.g.
(-)compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java (+26 lines)
Lines 1086-1091 Link Here
1086
		if (this.maxFieldCount < localMaxFieldCount) {
1086
		if (this.maxFieldCount < localMaxFieldCount) {
1087
			this.maxFieldCount = localMaxFieldCount;
1087
			this.maxFieldCount = localMaxFieldCount;
1088
		}
1088
		}
1089
		
1090
        // field count from supertypes should be included in maxFieldCount,
1091
		// so that a field from supertype doesn't end up with same id as a local variable
1092
		// in a method being analyzed.
1093
		ReferenceBinding superClassBinding = this.binding.superclass;
1094
		while (superClassBinding != null) {
1095
			FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields();
1096
			if (unResolvedFields != null) {
1097
				this.maxFieldCount += unResolvedFields.length;
1098
			}
1099
			superClassBinding = superClassBinding.superclass();
1100
		}
1101
		ReferenceBinding[] superInterfacesBinding = this.binding.superInterfaces;
1102
		this.maxFieldCount += findFieldCountFromSuperInterfaces(superInterfacesBinding);
1103
		
1089
		if (needSerialVersion) {
1104
		if (needSerialVersion) {
1090
			//check that the current type doesn't extend javax.rmi.CORBA.Stub
1105
			//check that the current type doesn't extend javax.rmi.CORBA.Stub
1091
			TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4);
1106
			TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4);
Lines 1172-1177 Link Here
1172
	}
1187
	}
1173
}
1188
}
1174
1189
1190
private int findFieldCountFromSuperInterfaces(ReferenceBinding[] superinterfaces) {
1191
	int numOfFields = 0;
1192
	if (superinterfaces == null)
1193
		return numOfFields ;
1194
	for (int i = 0; i < superinterfaces.length; i++) {
1195
		numOfFields += superinterfaces[i].fieldCount();
1196
		numOfFields += findFieldCountFromSuperInterfaces(superinterfaces[i].superInterfaces());		
1197
	}
1198
	return numOfFields;
1199
}
1200
1175
/**
1201
/**
1176
 * Resolve a local type declaration
1202
 * Resolve a local type declaration
1177
 */
1203
 */
(-)compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java (-27 / +33 lines)
Lines 13-18 Link Here
13
13
14
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
14
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
15
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
15
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
16
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
16
17
17
/**
18
/**
18
 * Record conditional initialization status during definite assignment analysis
19
 * Record conditional initialization status during definite assignment analysis
Lines 85-101 Link Here
85
			&& this.initsWhenFalse.isDefinitelyAssigned(local);
86
			&& this.initsWhenFalse.isDefinitelyAssigned(local);
86
}
87
}
87
88
88
public boolean isDefinitelyNonNull(LocalVariableBinding local) {
89
public boolean isDefinitelyNonNull(VariableBinding local) {
89
	return this.initsWhenTrue.isDefinitelyNonNull(local)
90
	return this.initsWhenTrue.isDefinitelyNonNull(local)
90
			&& this.initsWhenFalse.isDefinitelyNonNull(local);
91
			&& this.initsWhenFalse.isDefinitelyNonNull(local);
91
}
92
}
92
93
93
public boolean isDefinitelyNull(LocalVariableBinding local) {
94
public boolean isDefinitelyNull(VariableBinding local) {
94
	return this.initsWhenTrue.isDefinitelyNull(local)
95
	return this.initsWhenTrue.isDefinitelyNull(local)
95
			&& this.initsWhenFalse.isDefinitelyNull(local);
96
			&& this.initsWhenFalse.isDefinitelyNull(local);
96
}
97
}
97
98
98
public boolean isDefinitelyUnknown(LocalVariableBinding local) {
99
public boolean isDefinitelyUnknown(VariableBinding local) {
99
	return this.initsWhenTrue.isDefinitelyUnknown(local)
100
	return this.initsWhenTrue.isDefinitelyUnknown(local)
100
			&& this.initsWhenFalse.isDefinitelyUnknown(local);
101
			&& this.initsWhenFalse.isDefinitelyUnknown(local);
101
}
102
}
Lines 110-148 Link Here
110
			|| this.initsWhenFalse.isPotentiallyAssigned(local);
111
			|| this.initsWhenFalse.isPotentiallyAssigned(local);
111
}
112
}
112
113
113
public boolean isPotentiallyNonNull(LocalVariableBinding local) {
114
public boolean isPotentiallyNonNull(VariableBinding local) {
114
	return this.initsWhenTrue.isPotentiallyNonNull(local)
115
	return this.initsWhenTrue.isPotentiallyNonNull(local)
115
		|| this.initsWhenFalse.isPotentiallyNonNull(local);
116
		|| this.initsWhenFalse.isPotentiallyNonNull(local);
116
}
117
}
117
118
118
public boolean isPotentiallyNull(LocalVariableBinding local) {
119
public boolean isPotentiallyNull(VariableBinding local) {
119
	return this.initsWhenTrue.isPotentiallyNull(local)
120
	return this.initsWhenTrue.isPotentiallyNull(local)
120
		|| this.initsWhenFalse.isPotentiallyNull(local);
121
		|| this.initsWhenFalse.isPotentiallyNull(local);
121
}
122
}
122
123
123
public boolean isPotentiallyUnknown(LocalVariableBinding local) {
124
public boolean isPotentiallyUnknown(VariableBinding local) {
124
	return this.initsWhenTrue.isPotentiallyUnknown(local)
125
	return this.initsWhenTrue.isPotentiallyUnknown(local)
125
		|| this.initsWhenFalse.isPotentiallyUnknown(local);
126
		|| this.initsWhenFalse.isPotentiallyUnknown(local);
126
}
127
}
127
128
128
public boolean isProtectedNonNull(LocalVariableBinding local) {
129
public boolean isProtectedNonNull(VariableBinding local) {
129
	return this.initsWhenTrue.isProtectedNonNull(local)
130
	return this.initsWhenTrue.isProtectedNonNull(local)
130
		&& this.initsWhenFalse.isProtectedNonNull(local);
131
		&& this.initsWhenFalse.isProtectedNonNull(local);
131
}
132
}
132
133
133
public boolean isProtectedNull(LocalVariableBinding local) {
134
public boolean isProtectedNull(VariableBinding local) {
134
	return this.initsWhenTrue.isProtectedNull(local)
135
	return this.initsWhenTrue.isProtectedNull(local)
135
		&& this.initsWhenFalse.isProtectedNull(local);
136
		&& this.initsWhenFalse.isProtectedNull(local);
136
}
137
}
137
138
138
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
139
public void markAsComparedEqualToNonNull(VariableBinding local, boolean isSynchronised) {
139
	this.initsWhenTrue.markAsComparedEqualToNonNull(local);
140
	this.initsWhenTrue.markAsComparedEqualToNonNull(local, isSynchronised);
140
	this.initsWhenFalse.markAsComparedEqualToNonNull(local);
141
	this.initsWhenFalse.markAsComparedEqualToNonNull(local, isSynchronised);
141
}
142
}
142
143
143
public void markAsComparedEqualToNull(LocalVariableBinding local) {
144
public void markAsComparedEqualToNull(VariableBinding local, boolean isSynchronised) {
144
	this.initsWhenTrue.markAsComparedEqualToNull(local);
145
	this.initsWhenTrue.markAsComparedEqualToNull(local, isSynchronised);
145
    this.initsWhenFalse.markAsComparedEqualToNull(local);
146
    this.initsWhenFalse.markAsComparedEqualToNull(local, isSynchronised);
146
}
147
}
147
148
148
public void markAsDefinitelyAssigned(FieldBinding field) {
149
public void markAsDefinitelyAssigned(FieldBinding field) {
Lines 155-191 Link Here
155
	this.initsWhenFalse.markAsDefinitelyAssigned(local);
156
	this.initsWhenFalse.markAsDefinitelyAssigned(local);
156
}
157
}
157
158
158
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
159
public void markAsDefinitelyNonNull(VariableBinding local, boolean isSynchronised) {
159
	this.initsWhenTrue.markAsDefinitelyNonNull(local);
160
	this.initsWhenTrue.markAsDefinitelyNonNull(local, isSynchronised);
160
	this.initsWhenFalse.markAsDefinitelyNonNull(local);
161
	this.initsWhenFalse.markAsDefinitelyNonNull(local, isSynchronised);
161
}
162
}
162
163
163
public void markAsDefinitelyNull(LocalVariableBinding local) {
164
public void markAsDefinitelyNull(VariableBinding local, boolean isSynchronised) {
164
	this.initsWhenTrue.markAsDefinitelyNull(local);
165
	this.initsWhenTrue.markAsDefinitelyNull(local, isSynchronised);
165
	this.initsWhenFalse.markAsDefinitelyNull(local);
166
	this.initsWhenFalse.markAsDefinitelyNull(local, isSynchronised);
166
}
167
}
167
168
168
public void resetNullInfo(LocalVariableBinding local) {
169
public void resetNullInfo(VariableBinding local) {
169
	this.initsWhenTrue.resetNullInfo(local);
170
	this.initsWhenTrue.resetNullInfo(local);
170
	this.initsWhenFalse.resetNullInfo(local);
171
	this.initsWhenFalse.resetNullInfo(local);
171
}
172
}
172
173
173
public void markPotentiallyNullBit(LocalVariableBinding local) {
174
public void resetNullInfoForFields() {
175
	this.initsWhenTrue.resetNullInfoForFields();
176
	this.initsWhenFalse.resetNullInfoForFields();
177
}
178
179
public void markPotentiallyNullBit(VariableBinding local) {
174
	this.initsWhenTrue.markPotentiallyNullBit(local);
180
	this.initsWhenTrue.markPotentiallyNullBit(local);
175
	this.initsWhenFalse.markPotentiallyNullBit(local);
181
	this.initsWhenFalse.markPotentiallyNullBit(local);
176
}
182
}
177
183
178
public void markPotentiallyNonNullBit(LocalVariableBinding local) {
184
public void markPotentiallyNonNullBit(VariableBinding local) {
179
	this.initsWhenTrue.markPotentiallyNonNullBit(local);
185
	this.initsWhenTrue.markPotentiallyNonNullBit(local);
180
	this.initsWhenFalse.markPotentiallyNonNullBit(local);
186
	this.initsWhenFalse.markPotentiallyNonNullBit(local);
181
}
187
}
182
188
183
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
189
public void markAsDefinitelyUnknown(VariableBinding local) {
184
	this.initsWhenTrue.markAsDefinitelyUnknown(local);
190
	this.initsWhenTrue.markAsDefinitelyUnknown(local);
185
	this.initsWhenFalse.markAsDefinitelyUnknown(local);
191
	this.initsWhenFalse.markAsDefinitelyUnknown(local);
186
}
192
}
187
193
188
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
194
public void markPotentiallyUnknownBit(VariableBinding local) {
189
	this.initsWhenTrue.markPotentiallyUnknownBit(local);
195
	this.initsWhenTrue.markPotentiallyUnknownBit(local);
190
	this.initsWhenFalse.markPotentiallyUnknownBit(local);
196
	this.initsWhenFalse.markPotentiallyUnknownBit(local);
191
}
197
}
Lines 243-254 Link Here
243
			mergedWith(this.initsWhenFalse.unconditionalInits());
249
			mergedWith(this.initsWhenFalse.unconditionalInits());
244
}
250
}
245
251
246
public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
252
public void markedAsNullOrNonNullInAssertExpression(VariableBinding local) {
247
	this.initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local);
253
	this.initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local);
248
	this.initsWhenFalse.markedAsNullOrNonNullInAssertExpression(local);
254
	this.initsWhenFalse.markedAsNullOrNonNullInAssertExpression(local);
249
}
255
}
250
256
251
public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
257
public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding local) {
252
	return (this.initsWhenTrue.isMarkedAsNullOrNonNullInAssertExpression(local)
258
	return (this.initsWhenTrue.isMarkedAsNullOrNonNullInAssertExpression(local)
253
		|| this.initsWhenFalse.isMarkedAsNullOrNonNullInAssertExpression(local));
259
		|| this.initsWhenFalse.isMarkedAsNullOrNonNullInAssertExpression(local));
254
}
260
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java (-45 / +45 lines)
Lines 30-36 Link Here
30
	VariableBinding[] finalVariables;
30
	VariableBinding[] finalVariables;
31
	int assignCount;
31
	int assignCount;
32
32
33
	LocalVariableBinding[] nullLocals;
33
	VariableBinding[] nullVariables;
34
	Expression[] nullReferences;
34
	Expression[] nullReferences;
35
	int[] nullCheckTypes;
35
	int[] nullCheckTypes;
36
	int nullCount;
36
	int nullCount;
Lines 83-89 Link Here
83
	// check inconsistent null checks
83
	// check inconsistent null checks
84
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
84
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
85
		for (int i = 0; i < this.nullCount; i++) {
85
		for (int i = 0; i < this.nullCount; i++) {
86
			this.parent.recordUsingNullReference(scope, this.nullLocals[i],
86
			this.parent.recordUsingNullReference(scope, this.nullVariables[i],
87
					this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
87
					this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
88
		}
88
		}
89
	}
89
	}
Lines 91-108 Link Here
91
		for (int i = 0; i < this.nullCount; i++) {
91
		for (int i = 0; i < this.nullCount; i++) {
92
			Expression expression = this.nullReferences[i];
92
			Expression expression = this.nullReferences[i];
93
			// final local variable
93
			// final local variable
94
			LocalVariableBinding local = this.nullLocals[i];
94
			VariableBinding local = this.nullVariables[i];
95
			switch (this.nullCheckTypes[i]) {
95
			switch (this.nullCheckTypes[i]) {
96
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
96
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
97
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
97
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
98
					if (flowInfo.isDefinitelyNonNull(local)) {
98
					if (flowInfo.isDefinitelyNonNull(local)) {
99
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
99
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
100
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
100
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
101
								scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression);
101
								scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, expression);
102
							}
102
							}
103
						} else {
103
						} else {
104
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
104
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
105
								scope.problemReporter().localVariableNonNullComparedToNull(local, expression);
105
								scope.problemReporter().reportNonNullComparedToNullProblem(local, expression);
106
							}
106
							}
107
						}
107
						}
108
						continue;
108
						continue;
Lines 116-142 Link Here
116
						switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
116
						switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
117
							case FlowContext.IN_COMPARISON_NULL:
117
							case FlowContext.IN_COMPARISON_NULL:
118
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
118
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
119
									scope.problemReporter().localVariableNullReference(local, expression);
119
									scope.problemReporter().reportNullReferenceProblem(local, expression);
120
									continue;
120
									continue;
121
								}
121
								}
122
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
122
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
123
									scope.problemReporter().localVariableRedundantCheckOnNull(local, expression);
123
									scope.problemReporter().reportRedundantCheckOnNullProblem(local, expression);
124
								}
124
								}
125
								continue;
125
								continue;
126
							case FlowContext.IN_COMPARISON_NON_NULL:
126
							case FlowContext.IN_COMPARISON_NON_NULL:
127
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
127
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
128
									scope.problemReporter().localVariableNullReference(local, expression);
128
									scope.problemReporter().reportNullReferenceProblem(local, expression);
129
									continue;
129
									continue;
130
								}
130
								}
131
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
131
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
132
									scope.problemReporter().localVariableNullComparedToNonNull(local, expression);
132
									scope.problemReporter().reportNullComparedToNonNullProblem(local, expression);
133
								}
133
								}
134
								continue;
134
								continue;
135
							case FlowContext.IN_ASSIGNMENT:
135
							case FlowContext.IN_ASSIGNMENT:
136
								scope.problemReporter().localVariableRedundantNullAssignment(local, expression);
136
								scope.problemReporter().reportRedundantNullAssignmentProblem(local, expression);
137
								continue;
137
								continue;
138
							case FlowContext.IN_INSTANCEOF:
138
							case FlowContext.IN_INSTANCEOF:
139
								scope.problemReporter().localVariableNullInstanceof(local, expression);
139
								scope.problemReporter().reportNullInstanceofProblem(local, expression);
140
								continue;
140
								continue;
141
						}
141
						}
142
					} else if (flowInfo.isPotentiallyNull(local)) {
142
					} else if (flowInfo.isPotentiallyNull(local)) {
Lines 144-157 Link Here
144
							case FlowContext.IN_COMPARISON_NULL:
144
							case FlowContext.IN_COMPARISON_NULL:
145
								this.nullReferences[i] = null;
145
								this.nullReferences[i] = null;
146
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
146
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
147
									scope.problemReporter().localVariablePotentialNullReference(local, expression);
147
									scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
148
									continue;
148
									continue;
149
								}
149
								}
150
								break;
150
								break;
151
							case FlowContext.IN_COMPARISON_NON_NULL:
151
							case FlowContext.IN_COMPARISON_NON_NULL:
152
								this.nullReferences[i] = null;
152
								this.nullReferences[i] = null;
153
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
153
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
154
									scope.problemReporter().localVariablePotentialNullReference(local, expression);
154
									scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
155
									continue;
155
									continue;
156
								}
156
								}
157
								break;
157
								break;
Lines 160-170 Link Here
160
					break;
160
					break;
161
				case MAY_NULL:
161
				case MAY_NULL:
162
					if (flowInfo.isDefinitelyNull(local)) {
162
					if (flowInfo.isDefinitelyNull(local)) {
163
						scope.problemReporter().localVariableNullReference(local, expression);
163
						scope.problemReporter().reportNullReferenceProblem(local, expression);
164
						continue;
164
						continue;
165
					}
165
					}
166
					if (flowInfo.isPotentiallyNull(local)) {
166
					if (flowInfo.isPotentiallyNull(local)) {
167
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
167
						scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
168
					}
168
					}
169
					break;
169
					break;
170
				default:
170
				default:
Lines 212-218 Link Here
212
		return true;
212
		return true;
213
	}
213
	}
214
214
215
	public void recordUsingNullReference(Scope scope, LocalVariableBinding local,
215
	public void recordUsingNullReference(Scope scope, VariableBinding local,
216
			Expression reference, int checkType, FlowInfo flowInfo) {
216
			Expression reference, int checkType, FlowInfo flowInfo) {
217
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && !flowInfo.isDefinitelyUnknown(local))	{
217
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && !flowInfo.isDefinitelyUnknown(local))	{
218
			if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
218
			if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
Lines 226-239 Link Here
226
						if (flowInfo.cannotBeNull(local)) {
226
						if (flowInfo.cannotBeNull(local)) {
227
							if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
227
							if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
228
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
228
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
229
									scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
229
									scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, reference);
230
								}
230
								}
231
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
231
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
232
									flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
232
									flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
233
								}
233
								}
234
							} else if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
234
							} else if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
235
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
235
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
236
									scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
236
									scope.problemReporter().reportNonNullComparedToNullProblem(local, reference);
237
								}
237
								}
238
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
238
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
239
									flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
239
									flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
Lines 245-255 Link Here
245
							switch(checkType & CONTEXT_MASK) {
245
							switch(checkType & CONTEXT_MASK) {
246
								case FlowContext.IN_COMPARISON_NULL:
246
								case FlowContext.IN_COMPARISON_NULL:
247
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
247
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
248
										scope.problemReporter().localVariableNullReference(local, reference);
248
										scope.problemReporter().reportNullReferenceProblem(local, reference);
249
										return;
249
										return;
250
									}
250
									}
251
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
251
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
252
										scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
252
										scope.problemReporter().reportRedundantCheckOnNullProblem(local, reference);
253
									}
253
									}
254
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
254
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
255
										flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
255
										flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
Lines 257-290 Link Here
257
									return;
257
									return;
258
								case FlowContext.IN_COMPARISON_NON_NULL:
258
								case FlowContext.IN_COMPARISON_NON_NULL:
259
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
259
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
260
										scope.problemReporter().localVariableNullReference(local, reference);
260
										scope.problemReporter().reportNullReferenceProblem(local, reference);
261
										return;
261
										return;
262
									}
262
									}
263
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
263
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
264
										scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
264
										scope.problemReporter().reportNullComparedToNonNullProblem(local, reference);
265
									}
265
									}
266
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
266
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
267
										flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
267
										flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
268
									}
268
									}
269
									return;
269
									return;
270
								case FlowContext.IN_ASSIGNMENT:
270
								case FlowContext.IN_ASSIGNMENT:
271
									scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
271
									scope.problemReporter().reportRedundantNullAssignmentProblem(local, reference);
272
									return;
272
									return;
273
								case FlowContext.IN_INSTANCEOF:
273
								case FlowContext.IN_INSTANCEOF:
274
									scope.problemReporter().localVariableNullInstanceof(local, reference);
274
									scope.problemReporter().reportNullInstanceofProblem(local, reference);
275
									return;
275
									return;
276
							}
276
							}
277
						} else if (flowInfo.isPotentiallyNull(local)) {
277
						} else if (flowInfo.isPotentiallyNull(local)) {
278
							switch(checkType & CONTEXT_MASK) {
278
							switch(checkType & CONTEXT_MASK) {
279
								case FlowContext.IN_COMPARISON_NULL:
279
								case FlowContext.IN_COMPARISON_NULL:
280
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
280
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
281
										scope.problemReporter().localVariablePotentialNullReference(local, reference);
281
										scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
282
										return;
282
										return;
283
									}
283
									}
284
									break;
284
									break;
285
								case FlowContext.IN_COMPARISON_NON_NULL:
285
								case FlowContext.IN_COMPARISON_NON_NULL:
286
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
286
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
287
										scope.problemReporter().localVariablePotentialNullReference(local, reference);
287
										scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
288
										return;
288
										return;
289
									}
289
									}
290
									break;
290
									break;
Lines 296-302 Link Here
296
							return;
296
							return;
297
						}
297
						}
298
						if (flowInfo.canOnlyBeNull(local)) {
298
						if (flowInfo.canOnlyBeNull(local)) {
299
							scope.problemReporter().localVariableNullReference(local, reference);
299
							scope.problemReporter().reportNullReferenceProblem(local, reference);
300
							return;
300
							return;
301
						}
301
						}
302
						break;
302
						break;
Lines 311-324 Link Here
311
						if (flowInfo.isDefinitelyNonNull(local)) {
311
						if (flowInfo.isDefinitelyNonNull(local)) {
312
							if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
312
							if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
313
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
313
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
314
									scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
314
									scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, reference);
315
								}
315
								}
316
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
316
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
317
									flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
317
									flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
318
								}
318
								}
319
							} else {
319
							} else {
320
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
320
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
321
									scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
321
									scope.problemReporter().reportNonNullComparedToNullProblem(local, reference);
322
								}
322
								}
323
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
323
								if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
324
									flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
324
									flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
Lines 335-345 Link Here
335
							switch(checkType & CONTEXT_MASK) {
335
							switch(checkType & CONTEXT_MASK) {
336
								case FlowContext.IN_COMPARISON_NULL:
336
								case FlowContext.IN_COMPARISON_NULL:
337
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
337
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
338
										scope.problemReporter().localVariableNullReference(local, reference);
338
										scope.problemReporter().reportNullReferenceProblem(local, reference);
339
										return;
339
										return;
340
									}
340
									}
341
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
341
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
342
										scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
342
										scope.problemReporter().reportRedundantCheckOnNullProblem(local, reference);
343
									}
343
									}
344
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
344
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
345
										flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
345
										flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
Lines 347-380 Link Here
347
									return;
347
									return;
348
								case FlowContext.IN_COMPARISON_NON_NULL:
348
								case FlowContext.IN_COMPARISON_NON_NULL:
349
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
349
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
350
										scope.problemReporter().localVariableNullReference(local, reference);
350
										scope.problemReporter().reportNullReferenceProblem(local, reference);
351
										return;
351
										return;
352
									}
352
									}
353
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
353
									if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
354
										scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
354
										scope.problemReporter().reportNullComparedToNonNullProblem(local, reference);
355
									}
355
									}
356
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
356
									if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
357
										flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
357
										flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
358
									}
358
									}
359
									return;
359
									return;
360
								case FlowContext.IN_ASSIGNMENT:
360
								case FlowContext.IN_ASSIGNMENT:
361
									scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
361
									scope.problemReporter().reportRedundantNullAssignmentProblem(local, reference);
362
									return;
362
									return;
363
								case FlowContext.IN_INSTANCEOF:
363
								case FlowContext.IN_INSTANCEOF:
364
									scope.problemReporter().localVariableNullInstanceof(local, reference);
364
									scope.problemReporter().reportNullInstanceofProblem(local, reference);
365
									return;
365
									return;
366
							}
366
							}
367
						} else if (flowInfo.isPotentiallyNull(local)) {
367
						} else if (flowInfo.isPotentiallyNull(local)) {
368
							switch(checkType & CONTEXT_MASK) {
368
							switch(checkType & CONTEXT_MASK) {
369
								case FlowContext.IN_COMPARISON_NULL:
369
								case FlowContext.IN_COMPARISON_NULL:
370
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
370
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
371
										scope.problemReporter().localVariablePotentialNullReference(local, reference);
371
										scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
372
										return;
372
										return;
373
									}
373
									}
374
									break;
374
									break;
375
								case FlowContext.IN_COMPARISON_NON_NULL:
375
								case FlowContext.IN_COMPARISON_NON_NULL:
376
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
376
									if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
377
										scope.problemReporter().localVariablePotentialNullReference(local, reference);
377
										scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
378
										return;
378
										return;
379
									}
379
									}
380
									break;
380
									break;
Lines 383-393 Link Here
383
						break;
383
						break;
384
					case MAY_NULL :
384
					case MAY_NULL :
385
						if (flowInfo.isDefinitelyNull(local)) {
385
						if (flowInfo.isDefinitelyNull(local)) {
386
							scope.problemReporter().localVariableNullReference(local, reference);
386
							scope.problemReporter().reportNullReferenceProblem(local, reference);
387
							return;
387
							return;
388
						}
388
						}
389
						if (flowInfo.isPotentiallyNull(local)) {
389
						if (flowInfo.isPotentiallyNull(local)) {
390
							scope.problemReporter().localVariablePotentialNullReference(local, reference);
390
							scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
391
							return;
391
							return;
392
						}
392
						}
393
						if (flowInfo.isDefinitelyNonNull(local)) {
393
						if (flowInfo.isDefinitelyNonNull(local)) {
Lines 419-435 Link Here
419
		}
419
		}
420
	}
420
	}
421
421
422
protected void recordNullReference(LocalVariableBinding local,
422
protected void recordNullReference(VariableBinding local,
423
	Expression expression, int status) {
423
	Expression expression, int status) {
424
	if (this.nullCount == 0) {
424
	if (this.nullCount == 0) {
425
		this.nullLocals = new LocalVariableBinding[5];
425
		this.nullVariables = new VariableBinding[5];
426
		this.nullReferences = new Expression[5];
426
		this.nullReferences = new Expression[5];
427
		this.nullCheckTypes = new int[5];
427
		this.nullCheckTypes = new int[5];
428
	}
428
	}
429
	else if (this.nullCount == this.nullLocals.length) {
429
	else if (this.nullCount == this.nullVariables.length) {
430
		int newLength = this.nullCount * 2;
430
		int newLength = this.nullCount * 2;
431
		System.arraycopy(this.nullLocals, 0,
431
		System.arraycopy(this.nullVariables, 0,
432
			this.nullLocals = new LocalVariableBinding[newLength], 0,
432
			this.nullVariables = new VariableBinding[newLength], 0,
433
			this.nullCount);
433
			this.nullCount);
434
		System.arraycopy(this.nullReferences, 0,
434
		System.arraycopy(this.nullReferences, 0,
435
			this.nullReferences = new Expression[newLength], 0,
435
			this.nullReferences = new Expression[newLength], 0,
Lines 438-444 Link Here
438
			this.nullCheckTypes = new int[newLength], 0,
438
			this.nullCheckTypes = new int[newLength], 0,
439
			this.nullCount);
439
			this.nullCount);
440
	}
440
	}
441
	this.nullLocals[this.nullCount] = local;
441
	this.nullVariables[this.nullCount] = local;
442
	this.nullReferences[this.nullCount] = expression;
442
	this.nullReferences[this.nullCount] = expression;
443
	this.nullCheckTypes[this.nullCount++] = status;
443
	this.nullCheckTypes[this.nullCount++] = status;
444
}
444
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (-15 / +14 lines)
Lines 23-29 Link Here
23
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
23
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
24
import org.eclipse.jdt.internal.compiler.lookup.Binding;
24
import org.eclipse.jdt.internal.compiler.lookup.Binding;
25
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
25
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.Scope;
27
import org.eclipse.jdt.internal.compiler.lookup.Scope;
29
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
Lines 520-526 Link Here
520
 *      combined with a context indicator (one of {@link #IN_COMPARISON_NULL},
519
 *      combined with a context indicator (one of {@link #IN_COMPARISON_NULL},
521
 *      {@link #IN_COMPARISON_NON_NULL}, {@link #IN_ASSIGNMENT} or {@link #IN_INSTANCEOF})
520
 *      {@link #IN_COMPARISON_NON_NULL}, {@link #IN_ASSIGNMENT} or {@link #IN_INSTANCEOF})
522
 */
521
 */
523
protected void recordNullReference(LocalVariableBinding local,
522
protected void recordNullReference(VariableBinding local,
524
	Expression expression, int status) {
523
	Expression expression, int status) {
525
	// default implementation: do nothing
524
	// default implementation: do nothing
526
}
525
}
Lines 563-569 Link Here
563
 *  	be known at the time of calling this method (they are influenced by
562
 *  	be known at the time of calling this method (they are influenced by
564
 * 		code that follows the current point)
563
 * 		code that follows the current point)
565
 */
564
 */
566
public void recordUsingNullReference(Scope scope, LocalVariableBinding local,
565
public void recordUsingNullReference(Scope scope, VariableBinding local,
567
		Expression reference, int checkType, FlowInfo flowInfo) {
566
		Expression reference, int checkType, FlowInfo flowInfo) {
568
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 ||
567
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 ||
569
			flowInfo.isDefinitelyUnknown(local)) {
568
			flowInfo.isDefinitelyUnknown(local)) {
Lines 575-588 Link Here
575
			if (flowInfo.isDefinitelyNonNull(local)) {
574
			if (flowInfo.isDefinitelyNonNull(local)) {
576
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
575
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
577
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
576
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
578
						scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
577
						scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, reference);
579
					}
578
					}
580
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
579
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
581
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
580
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
582
					}
581
					}
583
				} else {
582
				} else {
584
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
583
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
585
						scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
584
						scope.problemReporter().reportNonNullComparedToNullProblem(local, reference);
586
					}
585
					}
587
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
586
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
588
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
587
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
Lines 602-612 Link Here
602
				switch(checkType & CONTEXT_MASK) {
601
				switch(checkType & CONTEXT_MASK) {
603
					case FlowContext.IN_COMPARISON_NULL:
602
					case FlowContext.IN_COMPARISON_NULL:
604
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
603
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
605
							scope.problemReporter().localVariableNullReference(local, reference);
604
							scope.problemReporter().reportNullReferenceProblem(local, reference);
606
							return;
605
							return;
607
						}
606
						}
608
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
607
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
609
							scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
608
							scope.problemReporter().reportRedundantCheckOnNullProblem(local, reference);
610
						}
609
						}
611
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
610
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
612
							flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
611
							flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
Lines 614-647 Link Here
614
						return;
613
						return;
615
					case FlowContext.IN_COMPARISON_NON_NULL:
614
					case FlowContext.IN_COMPARISON_NON_NULL:
616
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
615
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
617
							scope.problemReporter().localVariableNullReference(local, reference);
616
							scope.problemReporter().reportNullReferenceProblem(local, reference);
618
							return;
617
							return;
619
						}
618
						}
620
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
619
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
621
							scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
620
							scope.problemReporter().reportNullComparedToNonNullProblem(local, reference);
622
						}
621
						}
623
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
622
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
624
							flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
623
							flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
625
						}
624
						}
626
						return;
625
						return;
627
					case FlowContext.IN_ASSIGNMENT:
626
					case FlowContext.IN_ASSIGNMENT:
628
						scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
627
						scope.problemReporter().reportRedundantNullAssignmentProblem(local, reference);
629
						return;
628
						return;
630
					case FlowContext.IN_INSTANCEOF:
629
					case FlowContext.IN_INSTANCEOF:
631
						scope.problemReporter().localVariableNullInstanceof(local, reference);
630
						scope.problemReporter().reportNullInstanceofProblem(local, reference);
632
						return;
631
						return;
633
				}
632
				}
634
			} else if (flowInfo.isPotentiallyNull(local)) {
633
			} else if (flowInfo.isPotentiallyNull(local)) {
635
				switch(checkType & CONTEXT_MASK) {
634
				switch(checkType & CONTEXT_MASK) {
636
					case FlowContext.IN_COMPARISON_NULL:
635
					case FlowContext.IN_COMPARISON_NULL:
637
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
636
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
638
							scope.problemReporter().localVariablePotentialNullReference(local, reference);
637
							scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
639
							return;
638
							return;
640
						}
639
						}
641
						break;
640
						break;
642
					case FlowContext.IN_COMPARISON_NON_NULL:
641
					case FlowContext.IN_COMPARISON_NON_NULL:
643
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
642
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
644
							scope.problemReporter().localVariablePotentialNullReference(local, reference);
643
							scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
645
							return;
644
							return;
646
						}
645
						}
647
						break;
646
						break;
Lines 652-662 Link Here
652
			break;
651
			break;
653
		case MAY_NULL :
652
		case MAY_NULL :
654
			if (flowInfo.isDefinitelyNull(local)) {
653
			if (flowInfo.isDefinitelyNull(local)) {
655
				scope.problemReporter().localVariableNullReference(local, reference);
654
				scope.problemReporter().reportNullReferenceProblem(local, reference);
656
				return;
655
				return;
657
			}
656
			}
658
			if (flowInfo.isPotentiallyNull(local)) {
657
			if (flowInfo.isPotentiallyNull(local)) {
659
				scope.problemReporter().localVariablePotentialNullReference(local, reference);
658
				scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
660
				return;
659
				return;
661
			}
660
			}
662
			break;
661
			break;
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java (-91 / +105 lines)
Lines 17-22 Link Here
17
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
17
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
20
21
21
public abstract class FlowInfo {
22
public abstract class FlowInfo {
22
23
Lines 79-117 Link Here
79
	}
80
	}
80
81
81
/**
82
/**
82
 * Check whether a given local variable is known to be unable to gain a definite
83
 * Check whether a given field or local variable is known to be unable to gain a definite
83
 * non null or definite null status by the use of an enclosing flow info. The
84
 * non null or definite null status by the use of an enclosing flow info. The
84
 * semantics are that if the current flow info marks the variable as potentially
85
 * semantics are that if the current flow info marks the variable as potentially
85
 * unknown or else as being both potentially null and potentially non null,
86
 * unknown or else as being both potentially null and potentially non null,
86
 * then it won't ever be promoted as definitely null or definitely non null. (It
87
 * then it won't ever be promoted as definitely null or definitely non null. (It
87
 * could still get promoted to definite unknown).
88
 * could still get promoted to definite unknown).
88
 * @param local the variable to check
89
 * @param binding the field or local variable to check
89
 * @return true iff this flow info prevents local from being promoted to
90
 * @return true iff this flow info prevents field or local from being promoted to
90
 *         definite non null or definite null against an enclosing flow info
91
 *         definite non null or definite null against an enclosing flow info
91
 */
92
 */
92
public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) {
93
public boolean cannotBeDefinitelyNullOrNonNull(VariableBinding binding) {
93
	return isPotentiallyUnknown(local) ||
94
	return isPotentiallyUnknown(binding) ||
94
		isPotentiallyNonNull(local) && isPotentiallyNull(local);
95
		isPotentiallyNonNull(binding) && isPotentiallyNull(binding);
95
}
96
}
96
97
97
/**
98
/**
98
 * Check whether a given local variable is known to be non null, either because
99
 * Check whether a given field or local variable is known to be non null, either because
99
 * it is definitely non null, or because is has been tested against non null.
100
 * it is definitely non null, or because is has been tested against non null.
100
 * @param local the variable to ckeck
101
 * @param binding the field or local to check
101
 * @return true iff local cannot be null for this flow info
102
 * @return true iff field or local cannot be null for this flow info
102
 */
103
 */
103
public boolean cannotBeNull(LocalVariableBinding local) {
104
public boolean cannotBeNull(VariableBinding binding) {
104
	return isDefinitelyNonNull(local) || isProtectedNonNull(local);
105
	return isDefinitelyNonNull(binding) || isProtectedNonNull(binding);
105
}
106
}
106
107
107
/**
108
/**
108
 * Check whether a given local variable is known to be null, either because it
109
 * Check whether a given field or local variable is known to be null, either because it
109
 * is definitely null, or because is has been tested against null.
110
 * is definitely null, or because is has been tested against null. Note that for fields, 
110
 * @param local the variable to ckeck
111
 * this method only takes compile time analysis into account and there's no 
111
 * @return true iff local can only be null for this flow info
112
 * guarantee of the field being definitely null during runtime
113
 * since it can be modified in some other thread.
114
 * @param binding the field or local to check
115
 * @return true iff field or local can only be null for this flow info
112
 */
116
 */
113
public boolean canOnlyBeNull(LocalVariableBinding local) {
117
public boolean canOnlyBeNull(VariableBinding binding) {
114
	return isDefinitelyNull(local) || isProtectedNull(local);
118
	return isDefinitelyNull(binding) || isProtectedNull(binding);
115
}
119
}
116
120
117
/**
121
/**
Lines 159-183 Link Here
159
	public abstract boolean isDefinitelyAssigned(LocalVariableBinding local);
163
	public abstract boolean isDefinitelyAssigned(LocalVariableBinding local);
160
164
161
/**
165
/**
162
 * Check status of definite non-null value for a given local variable.
166
 * Check status of definite non-null value for a given field or local variable. Note that for fields, this method only
163
 * @param local the variable to ckeck
167
 * takes compile time analysis into account and there's no guarantee of the field being definitely non null during runtime
164
 * @return true iff local is definitely non null for this flow info
168
 * since it can be modified in some other thread.
169
 * @param binding the field or local to check
170
 * @return true iff field or local is definitely non null for this flow info
165
 */
171
 */
166
	public abstract boolean isDefinitelyNonNull(LocalVariableBinding local);
172
	public abstract boolean isDefinitelyNonNull(VariableBinding binding);
167
173
168
/**
174
/**
169
 * Check status of definite null value for a given local variable.
175
 * Check status of definite null value for a given field or local variable. Note that for fields, this method only
170
 * @param local the variable to ckeck
176
 * takes compile time analysis into account and there's no guarantee of the field being definitely null during runtime
171
 * @return true iff local is definitely null for this flow info
177
 * since it can be modified in some other thread.
178
 * @param binding the field or local to check
179
 * @return true iff field or local is definitely null for this flow info
172
 */
180
 */
173
public abstract boolean isDefinitelyNull(LocalVariableBinding local);
181
public abstract boolean isDefinitelyNull(VariableBinding binding);
174
182
175
/**
183
/**
176
 * Check status of definite unknown value for a given local variable.
184
 * Check status of definite unknown value for a given field or local variable.
177
 * @param local the variable to ckeck
185
 * @param binding the field or local to check
178
 * @return true iff local is definitely unknown for this flow info
186
 * @return true iff field or local is definitely unknown for this flow info
179
 */
187
 */
180
public abstract boolean isDefinitelyUnknown(LocalVariableBinding local);
188
public abstract boolean isDefinitelyUnknown(VariableBinding binding);
181
189
182
	/**
190
	/**
183
	 * Check status of potential assignment for a field.
191
	 * Check status of potential assignment for a field.
Lines 191-249 Link Here
191
	 abstract public boolean isPotentiallyAssigned(LocalVariableBinding field);
199
	 abstract public boolean isPotentiallyAssigned(LocalVariableBinding field);
192
200
193
/**
201
/**
194
 * Check status of potential null assignment for a local. Return true if there
202
 * Check status of potential null assignment for a field or local. Return true if there
195
 * is a reasonable expectation that the variable be non null at this point.
203
 * is a reasonable expectation that the variable be non null at this point.
196
 * @param local LocalVariableBinding - the binding for the checked local
204
 * @param binding VariableBinding - the binding for the checked field or local
197
 * @return true if there is a reasonable expectation that local be non null at
205
 * @return true if there is a reasonable expectation that the field or local be non null at
198
 * this point
206
 * this point
199
 */
207
 */
200
public abstract boolean isPotentiallyNonNull(LocalVariableBinding local);
208
public abstract boolean isPotentiallyNonNull(VariableBinding binding);
201
209
202
/**
210
/**
203
 * Check status of potential null assignment for a local. Return true if there
211
 * Check status of potential null assignment for a field or local. Return true if there
204
 * is a reasonable expectation that the variable be null at this point. This
212
 * is a reasonable expectation that the variable be null at this point. This
205
 * includes the protected null case, so as to augment diagnostics, but does not
213
 * includes the protected null case, so as to augment diagnostics, but does not
206
 * really check that someone deliberately assigned to null on any specific
214
 * really check that someone deliberately assigned to null on any specific
207
 * path
215
 * path
208
 * @param local LocalVariableBinding - the binding for the checked local
216
 * @param binding VariableBinding - the binding for the checked field or local
209
 * @return true if there is a reasonable expectation that local be null at
217
 * @return true if there is a reasonable expectation that the field or local be null at
210
 * this point
218
 * this point
211
 */
219
 */
212
public abstract boolean isPotentiallyNull(LocalVariableBinding local);
220
public abstract boolean isPotentiallyNull(VariableBinding binding);
213
221
214
/**
222
/**
215
 * Return true if the given local may have been assigned to an unknown value.
223
 * Return true if the given field or local may have been assigned to an unknown value.
216
 * @param local the local to check
224
 * @param binding the field or local to check
217
 * @return true if the given local may have been assigned to an unknown value
225
 * @return true if the given field or local may have been assigned to an unknown value
218
 */
226
 */
219
public abstract boolean isPotentiallyUnknown(LocalVariableBinding local);
227
public abstract boolean isPotentiallyUnknown(VariableBinding binding);
220
228
221
/**
229
/**
222
 * Return true if the given local is protected by a test against a non null
230
 * Return true if the given field or local is protected by a test against a non null
223
 * value.
231
 * value.
224
 * @param local the local to check
232
 * @param binding the field or local to check
225
 * @return true if the given local is protected by a test against a non null
233
 * @return true if the given field or local is protected by a test against a non null
226
 */
234
 */
227
public abstract boolean isProtectedNonNull(LocalVariableBinding local);
235
public abstract boolean isProtectedNonNull(VariableBinding binding);
228
236
229
/**
237
/**
230
 * Return true if the given local is protected by a test against null.
238
 * Return true if the given field or local is protected by a test against null.
231
 * @param local the local to check
239
 * @param binding the field or local to check
232
 * @return true if the given local is protected by a test against null
240
 * @return true if the given field or local is protected by a test against null
233
 */
241
 */
234
public abstract boolean isProtectedNull(LocalVariableBinding local);
242
public abstract boolean isProtectedNull(VariableBinding binding);
235
243
236
/**
244
/**
237
 * Record that a local variable got checked to be non null.
245
 * Record that a field or local variable got checked to be non null.
238
 * @param local the checked local variable
246
 * @param binding the checked field or local variable
247
 * @param isSynchronised whether the enclosing method is synchronized (needed for analysis of fields)
239
 */
248
 */
240
abstract public void markAsComparedEqualToNonNull(LocalVariableBinding local);
249
abstract public void markAsComparedEqualToNonNull(VariableBinding binding, boolean isSynchronised);
241
250
242
/**
251
/**
243
 * Record that a local variable got checked to be null.
252
 * Record that a field or local variable got checked to be null.
244
 * @param local the checked local variable
253
 * @param binding the checked field or local variable
254
 * @param isSynchronised whether the enclosing method is synchronized (needed for analysis of fields)
245
 */
255
 */
246
abstract public void markAsComparedEqualToNull(LocalVariableBinding local);
256
abstract public void markAsComparedEqualToNull(VariableBinding binding, boolean isSynchronised);
247
257
248
	/**
258
	/**
249
	 * Record a field got definitely assigned.
259
	 * Record a field got definitely assigned.
Lines 251-284 Link Here
251
	abstract public void markAsDefinitelyAssigned(FieldBinding field);
261
	abstract public void markAsDefinitelyAssigned(FieldBinding field);
252
262
253
	/**
263
	/**
254
	 * Record a local got definitely assigned to a non-null value.
264
	 * Record a field or local got definitely assigned to a non-null value.
255
	 */
265
	 */
256
	abstract public void markAsDefinitelyNonNull(LocalVariableBinding local);
266
	abstract public void markAsDefinitelyNonNull(VariableBinding binding, boolean isSynchronised);
257
267
258
	/**
268
	/**
259
	 * Record a local got definitely assigned to null.
269
	 * Record a field or local got definitely assigned to null.
260
	 */
270
	 */
261
	abstract public void markAsDefinitelyNull(LocalVariableBinding local);
271
	abstract public void markAsDefinitelyNull(VariableBinding binding, boolean isSynchronised);
262
272
263
	/**
273
	/**
264
	 * Reset all null-information about a given local.
274
	 * Reset all null-information about a given field or local.
265
	 */
275
	 */
266
	abstract public void resetNullInfo(LocalVariableBinding local);
276
	abstract public void resetNullInfo(VariableBinding binding);
267
277
268
	/**
278
	/**
269
	 * Record a local may have got assigned to unknown (set the bit on existing info).
279
	 *  variant of {@link #resetNullInfo(VariableBinding)} for resetting null info for all fields
270
	 */
280
	 */
271
	abstract public void markPotentiallyUnknownBit(LocalVariableBinding local);
281
	abstract public void resetNullInfoForFields();
282
	/**
283
	 * Record a field or local may have got assigned to unknown (set the bit on existing info).
284
	 */
285
	abstract public void markPotentiallyUnknownBit(VariableBinding binding);
272
286
273
	/**
287
	/**
274
	 * Record a local may have got assigned to null (set the bit on existing info).
288
	 * Record a field or local may have got assigned to null (set the bit on existing info).
275
	 */
289
	 */
276
	abstract public void markPotentiallyNullBit(LocalVariableBinding local);
290
	abstract public void markPotentiallyNullBit(VariableBinding binding);
277
291
278
	/**
292
	/**
279
	 * Record a local may have got assigned to non-null (set the bit on existing info).
293
	 * Record a field or local may have got assigned to non-null (set the bit on existing info).
280
	 */
294
	 */
281
	abstract public void markPotentiallyNonNullBit(LocalVariableBinding local);
295
	abstract public void markPotentiallyNonNullBit(VariableBinding binding);
282
296
283
	/**
297
	/**
284
	 * Record a local got definitely assigned.
298
	 * Record a local got definitely assigned.
Lines 286-344 Link Here
286
	abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
300
	abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
287
301
288
/**
302
/**
289
 * Record a local got definitely assigned to an unknown value.
303
 * Record a field or local got definitely assigned to an unknown value.
290
 */
304
 */
291
abstract public void markAsDefinitelyUnknown(LocalVariableBinding local);
305
abstract public void markAsDefinitelyUnknown(VariableBinding binding);
292
306
293
/**
307
/**
294
 * Mark the null status of the given local according to the given status
308
 * Mark the null status of the given field or local according to the given status
295
 * @param local
309
 * @param binding
296
 * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
310
 * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
297
 */
311
 */
298
public void markNullStatus(LocalVariableBinding local, int nullStatus) {
312
public void markNullStatus(VariableBinding binding, int nullStatus, boolean isSynchronised) {
299
	switch(nullStatus) {
313
	switch(nullStatus) {
300
		// definite status?
314
		// definite status?
301
		case FlowInfo.UNKNOWN :
315
		case FlowInfo.UNKNOWN :
302
			markAsDefinitelyUnknown(local);
316
			markAsDefinitelyUnknown(binding);
303
			break;
317
			break;
304
		case FlowInfo.NULL :
318
		case FlowInfo.NULL :
305
			markAsDefinitelyNull(local);
319
			markAsDefinitelyNull(binding, isSynchronised);
306
			break;
320
			break;
307
		case FlowInfo.NON_NULL :
321
		case FlowInfo.NON_NULL :
308
			markAsDefinitelyNonNull(local);
322
			markAsDefinitelyNonNull(binding, isSynchronised);
309
			break;
323
			break;
310
		default:
324
		default:
311
			// collect potential status:
325
			// collect potential status:
312
			resetNullInfo(local);
326
			resetNullInfo(binding);
313
			if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0)
327
			if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0)
314
				markPotentiallyUnknownBit(local);
328
				markPotentiallyUnknownBit(binding);
315
			if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
329
			if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
316
				markPotentiallyNullBit(local);
330
				markPotentiallyNullBit(binding);
317
			if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0)
331
			if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0)
318
				markPotentiallyNonNullBit(local);
332
				markPotentiallyNonNullBit(binding);
319
			if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0)
333
			if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0)
320
				markAsDefinitelyUnknown(local);
334
				markAsDefinitelyUnknown(binding);
321
	}
335
	}
322
}
336
}
323
337
324
/**
338
/**
325
 * Answer the null status of the given local
339
 * Answer the null status of the given field or local
326
 * @param local
340
 * @param binding
327
 * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
341
 * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
328
 */
342
 */
329
public int nullStatus(LocalVariableBinding local) {
343
public int nullStatus(VariableBinding binding) {
330
	if (isDefinitelyUnknown(local))
344
	if (isDefinitelyUnknown(binding))
331
		return FlowInfo.UNKNOWN;
345
		return FlowInfo.UNKNOWN;
332
	if (isDefinitelyNull(local))
346
	if (isDefinitelyNull(binding))
333
		return FlowInfo.NULL;
347
		return FlowInfo.NULL;
334
	if (isDefinitelyNonNull(local))
348
	if (isDefinitelyNonNull(binding))
335
		return FlowInfo.NON_NULL;
349
		return FlowInfo.NON_NULL;
336
	int status = 0;
350
	int status = 0;
337
	if (isPotentiallyUnknown(local))
351
	if (isPotentiallyUnknown(binding))
338
		status |= FlowInfo.POTENTIALLY_UNKNOWN;
352
		status |= FlowInfo.POTENTIALLY_UNKNOWN;
339
	if (isPotentiallyNull(local))
353
	if (isPotentiallyNull(binding))
340
		status |= FlowInfo.POTENTIALLY_NULL;
354
		status |= FlowInfo.POTENTIALLY_NULL;
341
	if (isPotentiallyNonNull(local))
355
	if (isPotentiallyNonNull(binding))
342
		status |= FlowInfo.POTENTIALLY_NON_NULL;
356
		status |= FlowInfo.POTENTIALLY_NON_NULL;
343
	if (status > 0)
357
	if (status > 0)
344
		return status;
358
		return status;
Lines 555-566 Link Here
555
 * where this variable is being checked against null
569
 * where this variable is being checked against null
556
 */
570
 */
557
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
571
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
558
abstract public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local);
572
abstract public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding);
559
573
560
/** 
574
/** 
561
 * Returns true if the local variable being checked for was marked as null or not null
575
 * Returns true if the local variable being checked for was marked as null or not null
562
 * inside an assert expression due to comparison against null.
576
 * inside an assert expression due to comparison against null.
563
 */
577
 */
564
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
578
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
565
abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local);
579
abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding);
566
}
580
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (-52 / +57 lines)
Lines 42-48 Link Here
42
	VariableBinding finalVariables[];
42
	VariableBinding finalVariables[];
43
	int assignCount = 0;
43
	int assignCount = 0;
44
44
45
	LocalVariableBinding[] nullLocals;
45
	VariableBinding[] nullVariables;
46
	Expression[] nullReferences;
46
	Expression[] nullReferences;
47
	int[] nullCheckTypes;
47
	int[] nullCheckTypes;
48
	int nullCount;
48
	int nullCount;
Lines 138-144 Link Here
138
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) {
138
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) {
139
		// check only immutable null checks on innermost looping context
139
		// check only immutable null checks on innermost looping context
140
		for (int i = 0; i < this.nullCount; i++) {
140
		for (int i = 0; i < this.nullCount; i++) {
141
			LocalVariableBinding local = this.nullLocals[i];
141
			VariableBinding local = this.nullVariables[i];
142
			Expression expression = this.nullReferences[i];
142
			Expression expression = this.nullReferences[i];
143
			// final local variable
143
			// final local variable
144
			switch (this.nullCheckTypes[i]) {
144
			switch (this.nullCheckTypes[i]) {
Lines 148-158 Link Here
148
						this.nullReferences[i] = null;
148
						this.nullReferences[i] = null;
149
						if (this.nullCheckTypes[i] == (CAN_ONLY_NON_NULL | IN_COMPARISON_NON_NULL)) {
149
						if (this.nullCheckTypes[i] == (CAN_ONLY_NON_NULL | IN_COMPARISON_NON_NULL)) {
150
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
150
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
151
								scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression);
151
								scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, expression);
152
							}
152
							}
153
						} else {
153
						} else {
154
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
154
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
155
								scope.problemReporter().localVariableNonNullComparedToNull(local, expression);
155
								scope.problemReporter().reportNonNullComparedToNullProblem(local, expression);
156
							}
156
							}
157
						}
157
						}
158
						continue;
158
						continue;
Lines 164-174 Link Here
164
						this.nullReferences[i] = null;
164
						this.nullReferences[i] = null;
165
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
165
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
166
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
166
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
167
								scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression);
167
								scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, expression);
168
							}
168
							}
169
						} else {
169
						} else {
170
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
170
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
171
								scope.problemReporter().localVariableNonNullComparedToNull(local, expression);
171
								scope.problemReporter().reportNonNullComparedToNullProblem(local, expression);
172
							}
172
							}
173
						}
173
						}
174
						continue;
174
						continue;
Lines 177-187 Link Here
177
						this.nullReferences[i] = null;
177
						this.nullReferences[i] = null;
178
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
178
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
179
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
179
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
180
								scope.problemReporter().localVariableRedundantCheckOnNull(local, expression);
180
								scope.problemReporter().reportRedundantCheckOnNullProblem(local, expression);
181
							}
181
							}
182
						} else {
182
						} else {
183
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
183
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
184
								scope.problemReporter().localVariableNullComparedToNonNull(local, expression);
184
								scope.problemReporter().reportNullComparedToNonNullProblem(local, expression);
185
							}
185
							}
186
						}
186
						}
187
						continue;
187
						continue;
Lines 196-222 Link Here
196
						switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
196
						switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
197
							case FlowContext.IN_COMPARISON_NULL:
197
							case FlowContext.IN_COMPARISON_NULL:
198
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
198
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
199
									scope.problemReporter().localVariableNullReference(local, expression);
199
									scope.problemReporter().reportNullReferenceProblem(local, expression);
200
									continue;
200
									continue;
201
								}
201
								}
202
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
202
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
203
									scope.problemReporter().localVariableRedundantCheckOnNull(local, expression);
203
									scope.problemReporter().reportRedundantCheckOnNullProblem(local, expression);
204
								}
204
								}
205
								continue;
205
								continue;
206
							case FlowContext.IN_COMPARISON_NON_NULL:
206
							case FlowContext.IN_COMPARISON_NON_NULL:
207
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
207
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
208
									scope.problemReporter().localVariableNullReference(local, expression);
208
									scope.problemReporter().reportNullReferenceProblem(local, expression);
209
									continue;
209
									continue;
210
								}
210
								}
211
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
211
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
212
									scope.problemReporter().localVariableNullComparedToNonNull(local, expression);
212
									scope.problemReporter().reportNullComparedToNonNullProblem(local, expression);
213
								}
213
								}
214
								continue;
214
								continue;
215
							case FlowContext.IN_ASSIGNMENT:
215
							case FlowContext.IN_ASSIGNMENT:
216
								scope.problemReporter().localVariableRedundantNullAssignment(local, expression);
216
								scope.problemReporter().reportRedundantNullAssignmentProblem(local, expression);
217
								continue;
217
								continue;
218
							case FlowContext.IN_INSTANCEOF:
218
							case FlowContext.IN_INSTANCEOF:
219
								scope.problemReporter().localVariableNullInstanceof(local, expression);
219
								scope.problemReporter().reportNullInstanceofProblem(local, expression);
220
								continue;
220
								continue;
221
						}
221
						}
222
					} else if (flowInfo.isPotentiallyNull(local)) {
222
					} else if (flowInfo.isPotentiallyNull(local)) {
Lines 224-237 Link Here
224
							case FlowContext.IN_COMPARISON_NULL:
224
							case FlowContext.IN_COMPARISON_NULL:
225
								this.nullReferences[i] = null;
225
								this.nullReferences[i] = null;
226
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
226
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
227
									scope.problemReporter().localVariablePotentialNullReference(local, expression);
227
									scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
228
									continue;
228
									continue;
229
								}
229
								}
230
								break;
230
								break;
231
							case FlowContext.IN_COMPARISON_NON_NULL:
231
							case FlowContext.IN_COMPARISON_NON_NULL:
232
								this.nullReferences[i] = null;
232
								this.nullReferences[i] = null;
233
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
233
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
234
									scope.problemReporter().localVariablePotentialNullReference(local, expression);
234
									scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
235
									continue;
235
									continue;
236
								}
236
								}
237
								break;
237
								break;
Lines 241-247 Link Here
241
				case MAY_NULL:
241
				case MAY_NULL:
242
					if (flowInfo.isDefinitelyNull(local)) {
242
					if (flowInfo.isDefinitelyNull(local)) {
243
						this.nullReferences[i] = null;
243
						this.nullReferences[i] = null;
244
						scope.problemReporter().localVariableNullReference(local, expression);
244
						scope.problemReporter().reportNullReferenceProblem(local, expression);
245
						continue;
245
						continue;
246
					}
246
					}
247
					break;
247
					break;
Lines 257-263 Link Here
257
		for (int i = 0; i < this.nullCount; i++) {
257
		for (int i = 0; i < this.nullCount; i++) {
258
			Expression expression = this.nullReferences[i];
258
			Expression expression = this.nullReferences[i];
259
			// final local variable
259
			// final local variable
260
			LocalVariableBinding local = this.nullLocals[i];
260
			VariableBinding local = this.nullVariables[i];
261
			switch (this.nullCheckTypes[i]) {
261
			switch (this.nullCheckTypes[i]) {
262
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
262
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
263
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
263
				case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
Lines 265-275 Link Here
265
						this.nullReferences[i] = null;
265
						this.nullReferences[i] = null;
266
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
266
						if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
267
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
267
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
268
								scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression);
268
								scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, expression);
269
							}
269
							}
270
						} else {
270
						} else {
271
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
271
							if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
272
								scope.problemReporter().localVariableNonNullComparedToNull(local, expression);
272
								scope.problemReporter().reportNonNullComparedToNullProblem(local, expression);
273
							}
273
							}
274
						}
274
						}
275
						continue;
275
						continue;
Lines 284-310 Link Here
284
						switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
284
						switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
285
							case FlowContext.IN_COMPARISON_NULL:
285
							case FlowContext.IN_COMPARISON_NULL:
286
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
286
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
287
									scope.problemReporter().localVariableNullReference(local, expression);
287
									scope.problemReporter().reportNullReferenceProblem(local, expression);
288
									continue;
288
									continue;
289
								}
289
								}
290
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
290
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
291
									scope.problemReporter().localVariableRedundantCheckOnNull(local, expression);
291
									scope.problemReporter().reportRedundantCheckOnNullProblem(local, expression);
292
								}
292
								}
293
								continue;
293
								continue;
294
							case FlowContext.IN_COMPARISON_NON_NULL:
294
							case FlowContext.IN_COMPARISON_NON_NULL:
295
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
295
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
296
									scope.problemReporter().localVariableNullReference(local, expression);
296
									scope.problemReporter().reportNullReferenceProblem(local, expression);
297
									continue;
297
									continue;
298
								}
298
								}
299
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
299
								if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
300
									scope.problemReporter().localVariableNullComparedToNonNull(local, expression);
300
									scope.problemReporter().reportNullComparedToNonNullProblem(local, expression);
301
								}
301
								}
302
								continue;
302
								continue;
303
							case FlowContext.IN_ASSIGNMENT:
303
							case FlowContext.IN_ASSIGNMENT:
304
								scope.problemReporter().localVariableRedundantNullAssignment(local, expression);
304
								if (local instanceof LocalVariableBinding) {
305
									scope.problemReporter().localVariableRedundantNullAssignment((LocalVariableBinding) local, expression);
306
								}
305
								continue;
307
								continue;
306
							case FlowContext.IN_INSTANCEOF:
308
							case FlowContext.IN_INSTANCEOF:
307
								scope.problemReporter().localVariableNullInstanceof(local, expression);
309
								if (local instanceof LocalVariableBinding) {
310
									scope.problemReporter().localVariableNullInstanceof((LocalVariableBinding) local, expression);
311
								}
308
								continue;
312
								continue;
309
						}
313
						}
310
					} else if (flowInfo.isPotentiallyNull(local)) {
314
					} else if (flowInfo.isPotentiallyNull(local)) {
Lines 312-325 Link Here
312
							case FlowContext.IN_COMPARISON_NULL:
316
							case FlowContext.IN_COMPARISON_NULL:
313
								this.nullReferences[i] = null;
317
								this.nullReferences[i] = null;
314
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
318
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
315
									scope.problemReporter().localVariablePotentialNullReference(local, expression);
319
									scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
316
									continue;
320
									continue;
317
								}
321
								}
318
								break;
322
								break;
319
							case FlowContext.IN_COMPARISON_NON_NULL:
323
							case FlowContext.IN_COMPARISON_NON_NULL:
320
								this.nullReferences[i] = null;
324
								this.nullReferences[i] = null;
321
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
325
								if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
322
									scope.problemReporter().localVariablePotentialNullReference(local, expression);
326
									scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
323
									continue;
327
									continue;
324
								}
328
								}
325
								break;
329
								break;
Lines 329-340 Link Here
329
				case MAY_NULL:
333
				case MAY_NULL:
330
					if (flowInfo.isDefinitelyNull(local)) {
334
					if (flowInfo.isDefinitelyNull(local)) {
331
						this.nullReferences[i] = null;
335
						this.nullReferences[i] = null;
332
						scope.problemReporter().localVariableNullReference(local, expression);
336
						scope.problemReporter().reportNullReferenceProblem(local, expression);
333
						continue;
337
						continue;
334
					}
338
					}
335
					if (flowInfo.isPotentiallyNull(local)) {
339
					if (flowInfo.isPotentiallyNull(local)) {
336
						this.nullReferences[i] = null;
340
						this.nullReferences[i] = null;
337
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
341
						scope.problemReporter().reportPotentialNullReferenceProblem(local, expression);
338
						continue;
342
						continue;
339
					}
343
					}
340
					break;
344
					break;
Lines 458-484 Link Here
458
		return true;
462
		return true;
459
	}
463
	}
460
464
461
protected void recordNullReference(LocalVariableBinding local,
465
protected void recordNullReference(VariableBinding local,
462
	Expression expression, int status) {
466
	Expression expression, int status) {
463
	if (this.nullCount == 0) {
467
	if (this.nullCount == 0) {
464
		this.nullLocals = new LocalVariableBinding[5];
468
		this.nullVariables = new VariableBinding[5];
465
		this.nullReferences = new Expression[5];
469
		this.nullReferences = new Expression[5];
466
		this.nullCheckTypes = new int[5];
470
		this.nullCheckTypes = new int[5];
467
	}
471
	}
468
	else if (this.nullCount == this.nullLocals.length) {
472
	else if (this.nullCount == this.nullVariables.length) {
469
		System.arraycopy(this.nullLocals, 0,
473
		System.arraycopy(this.nullVariables, 0,
470
			this.nullLocals = new LocalVariableBinding[this.nullCount * 2], 0, this.nullCount);
474
			this.nullVariables = new VariableBinding[this.nullCount * 2], 0, this.nullCount);
471
		System.arraycopy(this.nullReferences, 0,
475
		System.arraycopy(this.nullReferences, 0,
472
			this.nullReferences = new Expression[this.nullCount * 2], 0, this.nullCount);
476
			this.nullReferences = new Expression[this.nullCount * 2], 0, this.nullCount);
473
		System.arraycopy(this.nullCheckTypes, 0,
477
		System.arraycopy(this.nullCheckTypes, 0,
474
			this.nullCheckTypes = new int[this.nullCount * 2], 0, this.nullCount);
478
			this.nullCheckTypes = new int[this.nullCount * 2], 0, this.nullCount);
475
	}
479
	}
476
	this.nullLocals[this.nullCount] = local;
480
	this.nullVariables[this.nullCount] = local;
477
	this.nullReferences[this.nullCount] = expression;
481
	this.nullReferences[this.nullCount] = expression;
478
	this.nullCheckTypes[this.nullCount++] = status;
482
	this.nullCheckTypes[this.nullCount++] = status;
479
}
483
}
480
484
481
public void recordUsingNullReference(Scope scope, LocalVariableBinding local,
485
public void recordUsingNullReference(Scope scope, VariableBinding local,
482
		Expression reference, int checkType, FlowInfo flowInfo) {
486
		Expression reference, int checkType, FlowInfo flowInfo) {
483
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 ||
487
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 ||
484
			flowInfo.isDefinitelyUnknown(local)) {
488
			flowInfo.isDefinitelyUnknown(local)) {
Lines 490-503 Link Here
490
			if (flowInfo.isDefinitelyNonNull(local)) {
494
			if (flowInfo.isDefinitelyNonNull(local)) {
491
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
495
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
492
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
496
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
493
						scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
497
						scope.problemReporter().reportRedundantCheckOnNonNullProblem(local, reference);
494
					}
498
					}
495
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
499
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
496
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
500
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
497
					}
501
					}
498
				} else {
502
				} else {
499
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
503
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
500
						scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
504
						scope.problemReporter().reportNonNullComparedToNullProblem(local, reference);
501
					}
505
					}
502
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
506
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
503
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
507
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
Lines 506-526 Link Here
506
			} else if (flowInfo.isDefinitelyNull(local)) {
510
			} else if (flowInfo.isDefinitelyNull(local)) {
507
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
511
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
508
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
512
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
509
						scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
513
						scope.problemReporter().reportRedundantCheckOnNullProblem(local, reference);
510
					}
514
					}
511
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
515
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
512
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
516
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
513
					}
517
					}
514
				} else {
518
				} else {
515
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
519
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
516
						scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
520
						scope.problemReporter().reportNullComparedToNonNullProblem(local, reference);
517
					}
521
					}
518
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
522
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
519
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
523
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
520
					}
524
					}
521
				}
525
				}
522
			} else if (this.upstreamNullFlowInfo.isDefinitelyNonNull(local) && !flowInfo.isPotentiallyNull(local)) {    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291418
526
			} else if (this.upstreamNullFlowInfo.isDefinitelyNonNull(local) && !flowInfo.isPotentiallyNull(local)) {    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291418
523
				flowInfo.markAsDefinitelyNonNull(local);
527
				boolean isSynchronised = scope.isOuterMostMethodSynchronised();
528
				flowInfo.markAsDefinitelyNonNull(local, isSynchronised );
524
				if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
529
				if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
525
					recordNullReference(local, reference, checkType);
530
					recordNullReference(local, reference, checkType);
526
				}
531
				}
Lines 546-556 Link Here
546
				switch(checkType & CONTEXT_MASK) {
551
				switch(checkType & CONTEXT_MASK) {
547
					case FlowContext.IN_COMPARISON_NULL:
552
					case FlowContext.IN_COMPARISON_NULL:
548
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
553
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
549
							scope.problemReporter().localVariableNullReference(local, reference);
554
							scope.problemReporter().reportNullReferenceProblem(local, reference);
550
							return;
555
							return;
551
						}
556
						}
552
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
557
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
553
							scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
558
							scope.problemReporter().reportRedundantCheckOnNullProblem(local, reference);
554
						}
559
						}
555
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
560
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
556
							flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
561
							flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
Lines 558-591 Link Here
558
						return;
563
						return;
559
					case FlowContext.IN_COMPARISON_NON_NULL:
564
					case FlowContext.IN_COMPARISON_NON_NULL:
560
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
565
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
561
							scope.problemReporter().localVariableNullReference(local, reference);
566
							scope.problemReporter().reportNullReferenceProblem(local, reference);
562
							return;
567
							return;
563
						}
568
						}
564
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
569
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
565
							scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
570
							scope.problemReporter().reportNullComparedToNonNullProblem(local, reference);
566
						}
571
						}
567
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
572
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
568
							flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
573
							flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
569
						}
574
						}
570
						return;
575
						return;
571
					case FlowContext.IN_ASSIGNMENT:
576
					case FlowContext.IN_ASSIGNMENT:
572
						scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
577
						scope.problemReporter().reportRedundantNullAssignmentProblem(local, reference);
573
						return;
578
						return;
574
					case FlowContext.IN_INSTANCEOF:
579
					case FlowContext.IN_INSTANCEOF:
575
						scope.problemReporter().localVariableNullInstanceof(local, reference);
580
						scope.problemReporter().reportNullInstanceofProblem(local, reference);
576
						return;
581
						return;
577
				}
582
				}
578
			} else if (flowInfo.isPotentiallyNull(local)) {
583
			} else if (flowInfo.isPotentiallyNull(local)) {
579
				switch(checkType & CONTEXT_MASK) {
584
				switch(checkType & CONTEXT_MASK) {
580
					case FlowContext.IN_COMPARISON_NULL:
585
					case FlowContext.IN_COMPARISON_NULL:
581
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
586
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
582
							scope.problemReporter().localVariablePotentialNullReference(local, reference);
587
							scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
583
							return;
588
							return;
584
						}
589
						}
585
						break;
590
						break;
586
					case FlowContext.IN_COMPARISON_NON_NULL:
591
					case FlowContext.IN_COMPARISON_NON_NULL:
587
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
592
						if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning
588
							scope.problemReporter().localVariablePotentialNullReference(local, reference);
593
							scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
589
							return;
594
							return;
590
						}
595
						}
591
						break;
596
						break;
Lines 604-614 Link Here
604
				return;
609
				return;
605
			}
610
			}
606
			if (flowInfo.isDefinitelyNull(local)) {
611
			if (flowInfo.isDefinitelyNull(local)) {
607
				scope.problemReporter().localVariableNullReference(local, reference);
612
				scope.problemReporter().reportNullReferenceProblem(local, reference);
608
				return;
613
				return;
609
			}
614
			}
610
			if (flowInfo.isPotentiallyNull(local)) {
615
			if (flowInfo.isPotentiallyNull(local)) {
611
				scope.problemReporter().localVariablePotentialNullReference(local, reference);
616
				scope.problemReporter().reportPotentialNullReferenceProblem(local, reference);
612
				return;
617
				return;
613
			}
618
			}
614
			recordNullReference(local, reference, checkType);
619
			recordNullReference(local, reference, checkType);
(-)compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java (-23 / +59 lines)
Lines 11-17 Link Here
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.flow;
12
package org.eclipse.jdt.internal.compiler.flow;
13
13
14
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
14
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
15
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
15
16
16
/**
17
/**
17
 * A degenerate form of UnconditionalFlowInfo explicitly meant to capture
18
 * A degenerate form of UnconditionalFlowInfo explicitly meant to capture
Lines 53-60 Link Here
53
		}
54
		}
54
		if (upstream.extra != null) {
55
		if (upstream.extra != null) {
55
			this.extra = new long[extraLength][];
56
			this.extra = new long[extraLength][];
56
			int length = upstream.extra[2].length;
57
			int length = upstream.extra[0].length;
57
			for (int i = 2; i < extraLength; i++) {
58
			for (int i = 0; i < extraLength; i++) {
58
				this.extra[i] = new long[length];
59
				this.extra[i] = new long[length];
59
			}
60
			}
60
			for (int i = 0; i < length; i++) {
61
			for (int i = 0; i < length; i++) {
Lines 90-103 Link Here
90
	if (other.extra != null) {
91
	if (other.extra != null) {
91
		if (this.extra == null) {
92
		if (this.extra == null) {
92
			this.extra = new long[extraLength][];
93
			this.extra = new long[extraLength][];
93
			for (int i = 2, length = other.extra[2].length; i < extraLength; i++) {
94
			for (int i = 0, length = other.extra[0].length; i < extraLength; i++) {
94
				System.arraycopy(other.extra[i], 0,
95
				System.arraycopy(other.extra[i], 0,
95
					(this.extra[i] = new long[length]), 0, length);
96
					(this.extra[i] = new long[length]), 0, length);
96
			}
97
			}
97
		} else {
98
		} else {
98
			int length = this.extra[2].length, otherLength = other.extra[2].length;
99
			int length = this.extra[0].length, otherLength = other.extra[0].length;
99
			if (otherLength > length) {
100
			if (otherLength > length) {
100
				for (int i = 2; i < extraLength; i++) {
101
				for (int i = 0; i < extraLength; i++) {
101
					System.arraycopy(this.extra[i], 0,
102
					System.arraycopy(this.extra[i], 0,
102
						(this.extra[i] = new long[otherLength]), 0, length);
103
						(this.extra[i] = new long[otherLength]), 0, length);
103
					System.arraycopy(other.extra[i], length,
104
					System.arraycopy(other.extra[i], length,
Lines 106-112 Link Here
106
			} else if (otherLength < length) {
107
			} else if (otherLength < length) {
107
				length = otherLength;
108
				length = otherLength;
108
			}
109
			}
109
			for (int i = 2; i < extraLength; i++) {
110
			for (int i = 0; i < extraLength; i++) {
110
				for (int j = 0; j < length; j++) {
111
				for (int j = 0; j < length; j++) {
111
					this.extra[i][j] |= other.extra[i][j];
112
					this.extra[i][j] |= other.extra[i][j];
112
				}
113
				}
Lines 116-128 Link Here
116
	return this;
117
	return this;
117
}
118
}
118
119
119
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
120
public void markAsComparedEqualToNonNull(VariableBinding local, boolean isSynchronised) {
120
	// protected from non-object locals in calling methods
121
	// protected from non-object locals in calling methods
121
	if (this != DEAD_END) {
122
	if (this != DEAD_END) {
122
    	this.tagBits |= NULL_FLAG_MASK;
123
    	this.tagBits |= NULL_FLAG_MASK;
123
    	int position;
124
    	int position;
125
    	if (local instanceof FieldBinding) {
126
			if (isSynchronised) {
127
    			position = local.id;
128
    		} else {
129
				this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL, isSynchronised);
130
				return;
131
    		}
132
		} else {
133
			position = local.id + this.maxFieldCount;
134
		}
124
    	// position is zero-based
135
    	// position is zero-based
125
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
136
    	if (position < BitCacheSize) { // use bits
126
    		// set protected non null
137
    		// set protected non null
127
    		this.nullBit1 |= (1L << position);
138
    		this.nullBit1 |= (1L << position);
128
    		if (COVERAGE_TEST_FLAG) {
139
    		if (COVERAGE_TEST_FLAG) {
Lines 137-150 Link Here
137
			if (this.extra == null) {
148
			if (this.extra == null) {
138
				int length = vectorIndex + 1;
149
				int length = vectorIndex + 1;
139
				this.extra = new long[extraLength][];
150
				this.extra = new long[extraLength][];
140
				for (int j = 2; j < extraLength; j++) {
151
				for (int j = 0; j < extraLength; j++) {
141
					this.extra[j] = new long[length];
152
					this.extra[j] = new long[length];
142
				}
153
				}
143
			}
154
			}
144
			else {
155
			else {
145
				int oldLength; // might need to grow the arrays
156
				int oldLength; // might need to grow the arrays
146
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
157
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
147
					for (int j = 2; j < extraLength; j++) {
158
					for (int j = 0; j < extraLength; j++) {
148
						System.arraycopy(this.extra[j], 0,
159
						System.arraycopy(this.extra[j], 0,
149
							(this.extra[j] = new long[vectorIndex + 1]), 0,
160
							(this.extra[j] = new long[vectorIndex + 1]), 0,
150
							oldLength);
161
							oldLength);
Lines 161-173 Link Here
161
	}
172
	}
162
}
173
}
163
174
164
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
175
public void markAsDefinitelyNonNull(VariableBinding local, boolean isSynchronised) {
165
	// protected from non-object locals in calling methods
176
	// protected from non-object locals in calling methods
166
	if (this != DEAD_END) {
177
	if (this != DEAD_END) {
167
    	this.tagBits |= NULL_FLAG_MASK;
178
    	this.tagBits |= NULL_FLAG_MASK;
168
    	int position;
179
    	int position;
169
    	// position is zero-based
180
    	// position is zero-based
170
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
181
    	if (local instanceof FieldBinding) {
182
    		if (isSynchronised) {
183
    			position = local.id;
184
    		} else {
185
    			this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL, isSynchronised);
186
    			return;
187
    		}
188
    	} else {
189
    		position = local.id + this.maxFieldCount;
190
    	}
191
    	if (position < BitCacheSize) { // use bits
171
    		// set assigned non null
192
    		// set assigned non null
172
    		this.nullBit3 |= (1L << position);
193
    		this.nullBit3 |= (1L << position);
173
    		if (COVERAGE_TEST_FLAG) {
194
    		if (COVERAGE_TEST_FLAG) {
Lines 182-195 Link Here
182
			if (this.extra == null) {
203
			if (this.extra == null) {
183
				int length = vectorIndex + 1;
204
				int length = vectorIndex + 1;
184
				this.extra = new long[extraLength][];
205
				this.extra = new long[extraLength][];
185
				for (int j = 2; j < extraLength; j++) {
206
				for (int j = 0; j < extraLength; j++) {
186
					this.extra[j] = new long[length];
207
					this.extra[j] = new long[length];
187
				}
208
				}
188
			}
209
			}
189
			else {
210
			else {
190
				int oldLength; // might need to grow the arrays
211
				int oldLength; // might need to grow the arrays
191
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
212
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
192
					for (int j = 2; j < extraLength; j++) {
213
					for (int j = 0; j < extraLength; j++) {
193
						System.arraycopy(this.extra[j], 0,
214
						System.arraycopy(this.extra[j], 0,
194
							(this.extra[j] = new long[vectorIndex + 1]), 0,
215
							(this.extra[j] = new long[vectorIndex + 1]), 0,
195
							oldLength);
216
							oldLength);
Lines 207-219 Link Here
207
}
228
}
208
// PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either
229
// PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either
209
// PREMATURE project protected non null onto something else
230
// PREMATURE project protected non null onto something else
210
public void markAsDefinitelyNull(LocalVariableBinding local) {
231
public void markAsDefinitelyNull(VariableBinding local, boolean isSynchronised) {
211
	// protected from non-object locals in calling methods
232
	// protected from non-object locals in calling methods
212
	if (this != DEAD_END) {
233
	if (this != DEAD_END) {
213
    	this.tagBits |= NULL_FLAG_MASK;
234
    	this.tagBits |= NULL_FLAG_MASK;
214
    	int position;
235
    	int position;
236
    	if (local instanceof FieldBinding) {
237
    		if (isSynchronised) {
238
    			position = local.id;
239
    		} else {
240
	    		this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL, isSynchronised);
241
	    		return;
242
    		}
243
    	} else {
244
    		position = local.id + this.maxFieldCount;
245
    	}
215
    	// position is zero-based
246
    	// position is zero-based
216
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
247
    	if (position < BitCacheSize) { // use bits
217
    		// set assigned null
248
    		// set assigned null
218
    		this.nullBit2 |= (1L << position);
249
    		this.nullBit2 |= (1L << position);
219
    		if (COVERAGE_TEST_FLAG) {
250
    		if (COVERAGE_TEST_FLAG) {
Lines 228-241 Link Here
228
			if (this.extra == null) {
259
			if (this.extra == null) {
229
				int length = vectorIndex + 1;
260
				int length = vectorIndex + 1;
230
				this.extra = new long[extraLength][];
261
				this.extra = new long[extraLength][];
231
				for (int j = 2; j < extraLength; j++) {
262
				for (int j = 0; j < extraLength; j++) {
232
					this.extra[j] = new long[length];
263
					this.extra[j] = new long[length];
233
				}
264
				}
234
			}
265
			}
235
			else {
266
			else {
236
				int oldLength; // might need to grow the arrays
267
				int oldLength; // might need to grow the arrays
237
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
268
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
238
					for (int j = 2; j < extraLength; j++) {
269
					for (int j = 0; j < extraLength; j++) {
239
						System.arraycopy(this.extra[j], 0,
270
						System.arraycopy(this.extra[j], 0,
240
							(this.extra[j] = new long[vectorIndex + 1]), 0,
271
							(this.extra[j] = new long[vectorIndex + 1]), 0,
241
							oldLength);
272
							oldLength);
Lines 252-264 Link Here
252
	}
283
	}
253
}
284
}
254
285
255
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
286
public void markAsDefinitelyUnknown(VariableBinding local) {
256
	// protected from non-object locals in calling methods
287
	// protected from non-object locals in calling methods
257
	if (this != DEAD_END) {
288
	if (this != DEAD_END) {
258
    	this.tagBits |= NULL_FLAG_MASK;
289
    	this.tagBits |= NULL_FLAG_MASK;
259
    	int position;
290
    	int position;
291
    	if (local instanceof FieldBinding) {
292
    		position = local.id;
293
    	} else {
294
    		position = local.id + this.maxFieldCount;
295
    	}
260
    	// position is zero-based
296
    	// position is zero-based
261
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
297
    	if (position < BitCacheSize) { // use bits
262
    		// set assigned unknown
298
    		// set assigned unknown
263
    		this.nullBit4 |= (1L << position);
299
    		this.nullBit4 |= (1L << position);
264
    		if (COVERAGE_TEST_FLAG) {
300
    		if (COVERAGE_TEST_FLAG) {
Lines 273-286 Link Here
273
			if (this.extra == null) {
309
			if (this.extra == null) {
274
				int length = vectorIndex + 1;
310
				int length = vectorIndex + 1;
275
				this.extra = new long[extraLength][];
311
				this.extra = new long[extraLength][];
276
				for (int j = 2; j < extraLength; j++) {
312
				for (int j = 0; j < extraLength; j++) {
277
					this.extra[j] = new long[length];
313
					this.extra[j] = new long[length];
278
				}
314
				}
279
			}
315
			}
280
			else {
316
			else {
281
				int oldLength; // might need to grow the arrays
317
				int oldLength; // might need to grow the arrays
282
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
318
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
283
					for (int j = 2; j < extraLength; j++) {
319
					for (int j = 0; j < extraLength; j++) {
284
						System.arraycopy(this.extra[j], 0,
320
						System.arraycopy(this.extra[j], 0,
285
							(this.extra[j] = new long[vectorIndex + 1]), 0,
321
							(this.extra[j] = new long[vectorIndex + 1]), 0,
286
							oldLength);
322
							oldLength);
(-)compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java (-56 / +369 lines)
Lines 18-23 Link Here
18
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
20
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
21
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
21
22
22
/**
23
/**
23
 * Record initialization status during definite assignment analysis
24
 * Record initialization status during definite assignment analysis
Lines 82-88 Link Here
82
		// arrays which have the same size
83
		// arrays which have the same size
83
84
84
	public int maxFieldCount; // limit between fields and locals
85
	public int maxFieldCount; // limit between fields and locals
85
86
	// Constants
86
	// Constants
87
	public static final int BitCacheSize = 64; // 64 bits in a long.
87
	public static final int BitCacheSize = 64; // 64 bits in a long.
88
	public int[] nullStatusChangedInAssert; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
88
	public int[] nullStatusChangedInAssert; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
Lines 515-527 Link Here
515
	return this;
515
	return this;
516
}
516
}
517
517
518
final public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) {
518
final public boolean cannotBeDefinitelyNullOrNonNull(VariableBinding local) {
519
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
519
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
520
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
520
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
521
		return false;
521
		return false;
522
	}
522
	}
523
	int position;
523
	int position;
524
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
524
	if (local instanceof FieldBinding) {
525
		position = local.id;
526
	} else {
527
		position = local.id + this.maxFieldCount;
528
	}
529
	if (position < BitCacheSize) {
525
		// use bits
530
		// use bits
526
		return (
531
		return (
527
			(~this.nullBit1
532
			(~this.nullBit1
Lines 546-558 Link Here
546
		    & (1L << (position % BitCacheSize))) != 0;
551
		    & (1L << (position % BitCacheSize))) != 0;
547
}
552
}
548
553
549
final public boolean cannotBeNull(LocalVariableBinding local) {
554
final public boolean cannotBeNull(VariableBinding local) {
550
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
555
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
551
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
556
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
552
		return false;
557
		return false;
553
	}
558
	}
554
	int position;
559
	int position;
555
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
560
	if (local instanceof FieldBinding) {
561
		position = local.id;
562
	} else {
563
		position = local.id + this.maxFieldCount;
564
	}
565
	if (position < BitCacheSize) {
556
		// use bits
566
		// use bits
557
		return (this.nullBit1 & this.nullBit3
567
		return (this.nullBit1 & this.nullBit3
558
			& ((this.nullBit2 & this.nullBit4) | ~this.nullBit2)
568
			& ((this.nullBit2 & this.nullBit4) | ~this.nullBit2)
Lines 573-585 Link Here
573
		    & (1L << (position % BitCacheSize))) != 0;
583
		    & (1L << (position % BitCacheSize))) != 0;
574
}
584
}
575
585
576
final public boolean canOnlyBeNull(LocalVariableBinding local) {
586
final public boolean canOnlyBeNull(VariableBinding local) {
577
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
587
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
578
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
588
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
579
		return false;
589
		return false;
580
	}
590
	}
581
	int position;
591
	int position;
582
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
592
	if (local instanceof FieldBinding) {
593
		position = local.id;
594
	} else {
595
		position = local.id + this.maxFieldCount;
596
	}
597
	if (position < BitCacheSize) {
583
		// use bits
598
		// use bits
584
		return (this.nullBit1 & this.nullBit2
599
		return (this.nullBit1 & this.nullBit2
585
			& (~this.nullBit3 | ~this.nullBit4)
600
			& (~this.nullBit3 | ~this.nullBit4)
Lines 745-751 Link Here
745
	return isDefinitelyAssigned(local.id + this.maxFieldCount);
760
	return isDefinitelyAssigned(local.id + this.maxFieldCount);
746
}
761
}
747
762
748
final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
763
final public boolean isDefinitelyNonNull(VariableBinding local) {
764
	if (local instanceof FieldBinding && (this.tagBits & NULL_FLAG_MASK) == 0) {
765
		// no local yet in scope. Came here because of a field being queried for non null
766
		// will only happen for final fields, since they are assigned in a constructor or static block
767
		// and we may currently be in some other method
768
		this.tagBits |= NULL_FLAG_MASK;
769
	}
749
	// do not want to complain in unreachable code
770
	// do not want to complain in unreachable code
750
	if ((this.tagBits & UNREACHABLE) != 0 ||
771
	if ((this.tagBits & UNREACHABLE) != 0 ||
751
			(this.tagBits & NULL_FLAG_MASK) == 0) {
772
			(this.tagBits & NULL_FLAG_MASK) == 0) {
Lines 755-761 Link Here
755
			local.constant() != Constant.NotAConstant) { // String instances
776
			local.constant() != Constant.NotAConstant) { // String instances
756
		return true;
777
		return true;
757
	}
778
	}
758
	int position = local.id + this.maxFieldCount;
779
	int position;
780
	if (local instanceof FieldBinding) {
781
		if (local.isFinal() && ((FieldBinding)local).isStatic()) {
782
			// static final field's null status may not be in the flow info
783
			return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.NON_NULL);
784
		}
785
		position = local.id;
786
	} else {
787
		position = local.id + this.maxFieldCount;
788
	}
759
	if (position < BitCacheSize) { // use bits
789
	if (position < BitCacheSize) { // use bits
760
		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
790
		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
761
			    & (1L << position)) != 0;
791
			    & (1L << position)) != 0;
Lines 774-787 Link Here
774
		    & (1L << (position % BitCacheSize))) != 0;
804
		    & (1L << (position % BitCacheSize))) != 0;
775
}
805
}
776
806
777
final public boolean isDefinitelyNull(LocalVariableBinding local) {
807
final public boolean isDefinitelyNull(VariableBinding local) {
808
	if (local instanceof FieldBinding && (this.tagBits & NULL_FLAG_MASK) == 0) {
809
		// no local yet in scope. Came here because of a field being queried for non null
810
		// will only happen for final fields, since they are assigned in a constructor or static block
811
		// and we may currently be in some other method
812
		this.tagBits |= NULL_FLAG_MASK;
813
	}
778
	// do not want to complain in unreachable code
814
	// do not want to complain in unreachable code
779
	if ((this.tagBits & UNREACHABLE) != 0 ||
815
	if ((this.tagBits & UNREACHABLE) != 0 ||
780
			(this.tagBits & NULL_FLAG_MASK) == 0 ||
816
			(this.tagBits & NULL_FLAG_MASK) == 0 ||
781
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
817
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
782
		return false;
818
		return false;
783
	}
819
	}
784
	int position = local.id + this.maxFieldCount;
820
	int position;
821
	if (local instanceof FieldBinding) {
822
		if (local.isFinal() && ((FieldBinding)local).isStatic()) {
823
			// static final field's null status may not be in the flow info
824
			return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.NULL);
825
		}
826
		position = local.id;
827
	} else {
828
		position = local.id + this.maxFieldCount;
829
	}
785
	if (position < BitCacheSize) { // use bits
830
	if (position < BitCacheSize) { // use bits
786
		return ((this.nullBit1 & this.nullBit2
831
		return ((this.nullBit1 & this.nullBit2
787
			        & (~this.nullBit3 | ~this.nullBit4))
832
			        & (~this.nullBit3 | ~this.nullBit4))
Lines 801-813 Link Here
801
		    & (1L << (position % BitCacheSize))) != 0;
846
		    & (1L << (position % BitCacheSize))) != 0;
802
}
847
}
803
848
804
final public boolean isDefinitelyUnknown(LocalVariableBinding local) {
849
final public boolean isDefinitelyUnknown(VariableBinding local) {
805
	// do not want to complain in unreachable code
850
	// do not want to complain in unreachable code
806
	if ((this.tagBits & UNREACHABLE) != 0 ||
851
	if ((this.tagBits & UNREACHABLE) != 0 ||
807
			(this.tagBits & NULL_FLAG_MASK) == 0) {
852
			(this.tagBits & NULL_FLAG_MASK) == 0) {
808
		return false;
853
		return false;
809
	}
854
	}
810
	int position = local.id + this.maxFieldCount;
855
	int position;
856
	if (local instanceof FieldBinding) {
857
		position = local.id;
858
	} else {
859
		position = local.id + this.maxFieldCount;
860
	}
811
	if (position < BitCacheSize) { // use bits
861
	if (position < BitCacheSize) { // use bits
812
		return ((this.nullBit1 & this.nullBit4
862
		return ((this.nullBit1 & this.nullBit4
813
				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
863
				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
Lines 860-872 Link Here
860
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
910
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
861
}
911
}
862
912
863
final public boolean isPotentiallyNonNull(LocalVariableBinding local) {
913
final public boolean isPotentiallyNonNull(VariableBinding local) {
864
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
914
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
865
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
915
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
866
		return false;
916
		return false;
867
	}
917
	}
868
	int position;
918
	int position;
869
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
919
	if (local instanceof FieldBinding) {
920
		position = local.id;
921
	} else {
922
		position = local.id + this.maxFieldCount;
923
	}
924
	if (position < BitCacheSize) {
870
		// use bits
925
		// use bits
871
		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
926
		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
872
			    & (1L << position)) != 0;
927
			    & (1L << position)) != 0;
Lines 885-897 Link Here
885
		    & (1L << (position % BitCacheSize))) != 0;
940
		    & (1L << (position % BitCacheSize))) != 0;
886
}
941
}
887
942
888
final public boolean isPotentiallyNull(LocalVariableBinding local) {
943
final public boolean isPotentiallyNull(VariableBinding local) {
889
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
944
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
890
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
945
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
891
		return false;
946
		return false;
892
	}
947
	}
893
	int position;
948
	int position;
894
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
949
	if (local instanceof FieldBinding) {
950
		if (local.isFinal() && ((FieldBinding)local).isStatic()) {
951
			// static final field's null status may not be in the flow info
952
			return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.POTENTIALLY_NULL);
953
		}
954
		position = local.id;
955
	} else {
956
		position = local.id + this.maxFieldCount;
957
	}
958
	if (position < BitCacheSize) {
895
		// use bits
959
		// use bits
896
		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
960
		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
897
			    & (1L << position)) != 0;
961
			    & (1L << position)) != 0;
Lines 910-922 Link Here
910
		    & (1L << (position % BitCacheSize))) != 0;
974
		    & (1L << (position % BitCacheSize))) != 0;
911
}
975
}
912
976
913
final public boolean isPotentiallyUnknown(LocalVariableBinding local) {
977
final public boolean isPotentiallyUnknown(VariableBinding local) {
914
	// do not want to complain in unreachable code
978
	// do not want to complain in unreachable code
915
	if ((this.tagBits & UNREACHABLE) != 0 ||
979
	if ((this.tagBits & UNREACHABLE) != 0 ||
916
			(this.tagBits & NULL_FLAG_MASK) == 0) {
980
			(this.tagBits & NULL_FLAG_MASK) == 0) {
917
		return false;
981
		return false;
918
	}
982
	}
919
	int position = local.id + this.maxFieldCount;
983
	int position;
984
	if (local instanceof FieldBinding) {
985
		position = local.id;
986
	} else {
987
		position = local.id + this.maxFieldCount;
988
	}
920
	if (position < BitCacheSize) { // use bits
989
	if (position < BitCacheSize) { // use bits
921
		return (this.nullBit4
990
		return (this.nullBit4
922
			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
991
			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
Lines 937-949 Link Here
937
		    & (1L << (position % BitCacheSize))) != 0;
1006
		    & (1L << (position % BitCacheSize))) != 0;
938
}
1007
}
939
1008
940
final public boolean isProtectedNonNull(LocalVariableBinding local) {
1009
final public boolean isProtectedNonNull(VariableBinding local) {
941
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
1010
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
942
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
1011
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
943
		return false;
1012
		return false;
944
	}
1013
	}
945
	int position;
1014
	int position;
946
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1015
	if (local instanceof FieldBinding) {
1016
		position = local.id;
1017
	} else {
1018
		position = local.id + this.maxFieldCount;
1019
	}
1020
	if (position < BitCacheSize) {
947
		// use bits
1021
		// use bits
948
		return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0;
1022
		return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0;
949
	}
1023
	}
Lines 962-974 Link Here
962
		    & (1L << (position % BitCacheSize))) != 0;
1036
		    & (1L << (position % BitCacheSize))) != 0;
963
}
1037
}
964
1038
965
final public boolean isProtectedNull(LocalVariableBinding local) {
1039
final public boolean isProtectedNull(VariableBinding local) {
966
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
1040
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
967
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
1041
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
968
		return false;
1042
		return false;
969
	}
1043
	}
970
	int position;
1044
	int position;
971
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1045
	if (local instanceof FieldBinding) {
1046
		position = local.id;
1047
	} else {
1048
		position = local.id + this.maxFieldCount;
1049
	}
1050
	if (position < BitCacheSize) {
972
		// use bits
1051
		// use bits
973
		return (this.nullBit1 & this.nullBit2
1052
		return (this.nullBit1 & this.nullBit2
974
			& (this.nullBit3 ^ this.nullBit4)
1053
			& (this.nullBit3 ^ this.nullBit4)
Lines 1001-1015 Link Here
1001
		throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$
1080
		throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$
1002
	return expression;
1081
	return expression;
1003
}
1082
}
1004
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
1083
public void markAsComparedEqualToNonNull(VariableBinding local, boolean isSynchronised) {
1005
	// protected from non-object locals in calling methods
1084
	// protected from non-object locals in calling methods
1006
	if (this != DEAD_END) {
1085
	if (this != DEAD_END) {
1007
		this.tagBits |= NULL_FLAG_MASK;
1086
		this.tagBits |= NULL_FLAG_MASK;
1008
		int position;
1087
		int position;
1088
		if (local instanceof FieldBinding) {
1089
			if (isSynchronised) {
1090
    			position = local.id;
1091
    		} else {
1092
				this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL, isSynchronised);
1093
				return;
1094
    		}
1095
		} else {
1096
			position = local.id + this.maxFieldCount;
1097
		}
1009
		long mask;
1098
		long mask;
1010
		long a1, a2, a3, a4, na2;
1099
		long a1, a2, a3, a4, na2;
1011
		// position is zero-based
1100
		// position is zero-based
1012
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1101
		if (position < BitCacheSize) {
1013
			// use bits
1102
			// use bits
1014
			if (((mask = 1L << position)
1103
			if (((mask = 1L << position)
1015
				& (a1 = this.nullBit1)
1104
				& (a1 = this.nullBit1)
Lines 1098-1111 Link Here
1098
	}
1187
	}
1099
}
1188
}
1100
1189
1101
public void markAsComparedEqualToNull(LocalVariableBinding local) {
1190
public void markAsComparedEqualToNull(VariableBinding local, boolean isSynchronised) {
1102
	// protected from non-object locals in calling methods
1191
	// protected from non-object locals in calling methods
1103
	if (this != DEAD_END) {
1192
	if (this != DEAD_END) {
1104
		this.tagBits |= NULL_FLAG_MASK;
1193
		this.tagBits |= NULL_FLAG_MASK;
1105
		int position;
1194
		int position;
1106
		long mask;
1195
		long mask;
1107
		// position is zero-based
1196
		// position is zero-based
1108
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1197
		if (local instanceof FieldBinding) {
1198
			if (isSynchronised) {
1199
    			position = local.id;
1200
    		} else {
1201
				this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL, isSynchronised);
1202
				return;
1203
    		}
1204
		} else {
1205
			position = local.id + this.maxFieldCount;
1206
		}
1207
		if (position < BitCacheSize) {
1109
			// use bits
1208
			// use bits
1110
			if (((mask = 1L << position) & this.nullBit1) != 0) {
1209
			if (((mask = 1L << position) & this.nullBit1) != 0) {
1111
  			  	if ((mask
1210
  			  	if ((mask
Lines 1236-1249 Link Here
1236
		markAsDefinitelyAssigned(local.id + this.maxFieldCount);
1335
		markAsDefinitelyAssigned(local.id + this.maxFieldCount);
1237
}
1336
}
1238
1337
1239
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
1338
public void markAsDefinitelyNonNull(VariableBinding local, boolean isSynchronised) {
1240
	// protected from non-object locals in calling methods
1339
	// protected from non-object locals in calling methods
1241
	if (this != DEAD_END) {
1340
	if (this != DEAD_END) {
1242
    	this.tagBits |= NULL_FLAG_MASK;
1341
    	this.tagBits |= NULL_FLAG_MASK;
1243
    	long mask;
1342
    	long mask;
1244
    	int position;
1343
    	int position;
1344
    	if (local instanceof FieldBinding) {
1345
    		if (isSynchronised) {
1346
    			position = local.id;
1347
    		} else {
1348
    			this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL, isSynchronised);
1349
    			return;
1350
    		}
1351
    	} else {
1352
    		position = local.id + this.maxFieldCount;
1353
    	}
1245
    	// position is zero-based
1354
    	// position is zero-based
1246
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
1355
    	if (position < BitCacheSize) { // use bits
1247
    		// set assigned non null
1356
    		// set assigned non null
1248
    		this.nullBit1 |= (mask = 1L << position);
1357
    		this.nullBit1 |= (mask = 1L << position);
1249
    		this.nullBit3 |= mask;
1358
    		this.nullBit3 |= mask;
Lines 1258-1265 Link Here
1258
    	}
1367
    	}
1259
    	else {
1368
    	else {
1260
    		// use extra vector
1369
    		// use extra vector
1261
    		int vectorIndex ;
1370
    		int vectorIndex = (position / BitCacheSize) - 1;
1262
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1371
			if (this.extra == null) {
1372
				int length = vectorIndex + 1;
1373
				this.extra = new long[extraLength][];
1374
				for (int j = 0; j < extraLength; j++) {
1375
					this.extra[j] = new long[length];
1376
				}
1377
			}
1378
			else {
1379
				int oldLength; // might need to grow the arrays
1380
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1381
					for (int j = 0; j < extraLength; j++) {
1382
						System.arraycopy(this.extra[j], 0,
1383
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1384
							oldLength);
1385
					}
1386
				}
1387
			}
1388
    		this.extra[2][vectorIndex]
1263
    		    |= (mask = 1L << (position % BitCacheSize));
1389
    		    |= (mask = 1L << (position % BitCacheSize));
1264
    		this.extra[4][vectorIndex] |= mask;
1390
    		this.extra[4][vectorIndex] |= mask;
1265
    		this.extra[3][vectorIndex] &= (mask = ~mask);
1391
    		this.extra[3][vectorIndex] &= (mask = ~mask);
Lines 1273-1286 Link Here
1273
	}
1399
	}
1274
}
1400
}
1275
1401
1276
public void markAsDefinitelyNull(LocalVariableBinding local) {
1402
public void markAsDefinitelyNull(VariableBinding local, boolean isSynchronised) {
1277
	// protected from non-object locals in calling methods
1403
	// protected from non-object locals in calling methods
1278
	if (this != DEAD_END) {
1404
	if (this != DEAD_END) {
1279
    	this.tagBits |= NULL_FLAG_MASK;
1405
    	this.tagBits |= NULL_FLAG_MASK;
1280
    	long mask;
1406
    	long mask;
1281
    	int position;
1407
    	int position;
1408
    	if (local instanceof FieldBinding) {
1409
    		if (isSynchronised) {
1410
    			position = local.id;
1411
    		} else {
1412
	    		this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL, isSynchronised);
1413
	    		return;
1414
    		}
1415
    	} else {
1416
    		position = local.id + this.maxFieldCount;
1417
    	}
1282
    	// position is zero-based
1418
    	// position is zero-based
1283
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
1419
    	if (position < BitCacheSize) { // use bits
1284
    		// mark assigned null
1420
    		// mark assigned null
1285
    		this.nullBit1 |= (mask = 1L << position);
1421
    		this.nullBit1 |= (mask = 1L << position);
1286
    		this.nullBit2 |= mask;
1422
    		this.nullBit2 |= mask;
Lines 1295-1302 Link Here
1295
    	}
1431
    	}
1296
    	else {
1432
    	else {
1297
    		// use extra vector
1433
    		// use extra vector
1298
    		int vectorIndex ;
1434
    		int vectorIndex = (position / BitCacheSize) - 1;
1299
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1435
			if (this.extra == null) {
1436
				int length = vectorIndex + 1;
1437
				this.extra = new long[extraLength][];
1438
				for (int j = 0; j < extraLength; j++) {
1439
					this.extra[j] = new long[length];
1440
				}
1441
			}
1442
			else {
1443
				int oldLength; // might need to grow the arrays
1444
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1445
					for (int j = 0; j < extraLength; j++) {
1446
						System.arraycopy(this.extra[j], 0,
1447
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1448
							oldLength);
1449
					}
1450
				}
1451
			}
1452
    		this.extra[2][vectorIndex]
1300
    		    |= (mask = 1L << (position % BitCacheSize));
1453
    		    |= (mask = 1L << (position % BitCacheSize));
1301
    		this.extra[3][vectorIndex] |= mask;
1454
    		this.extra[3][vectorIndex] |= mask;
1302
    		this.extra[4][vectorIndex] &= (mask = ~mask);
1455
    		this.extra[4][vectorIndex] &= (mask = ~mask);
Lines 1316-1329 Link Here
1316
 */
1469
 */
1317
// PREMATURE may try to get closer to markAsDefinitelyAssigned, but not
1470
// PREMATURE may try to get closer to markAsDefinitelyAssigned, but not
1318
//			 obvious
1471
//			 obvious
1319
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
1472
public void markAsDefinitelyUnknown(VariableBinding local) {
1320
	// protected from non-object locals in calling methods
1473
	// protected from non-object locals in calling methods
1321
	if (this != DEAD_END) {
1474
	if (this != DEAD_END) {
1322
		this.tagBits |= NULL_FLAG_MASK;
1475
		this.tagBits |= NULL_FLAG_MASK;
1323
		long mask;
1476
		long mask;
1324
		int position;
1477
		int position;
1478
		if (local instanceof FieldBinding) {
1479
    		position = local.id;
1480
    	} else {
1481
    		position = local.id + this.maxFieldCount;
1482
    	}
1325
		// position is zero-based
1483
		// position is zero-based
1326
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1484
		if (position < BitCacheSize) {
1327
			// use bits
1485
			// use bits
1328
			// mark assigned null
1486
			// mark assigned null
1329
			this.nullBit1 |= (mask = 1L << position);
1487
			this.nullBit1 |= (mask = 1L << position);
Lines 1339-1346 Link Here
1339
		}
1497
		}
1340
		else {
1498
		else {
1341
			// use extra vector
1499
			// use extra vector
1342
			int vectorIndex ;
1500
			int vectorIndex = (position / BitCacheSize) - 1;
1343
			this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1501
			if (this.extra == null) {
1502
				int length = vectorIndex + 1;
1503
				this.extra = new long[extraLength][];
1504
				for (int j = 0; j < extraLength; j++) {
1505
					this.extra[j] = new long[length];
1506
				}
1507
			}
1508
			else {
1509
				int oldLength; // might need to grow the arrays
1510
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1511
					for (int j = 0; j < extraLength; j++) {
1512
						System.arraycopy(this.extra[j], 0,
1513
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1514
							oldLength);
1515
					}
1516
				}
1517
			}
1518
			this.extra[2][vectorIndex]
1344
			    |= (mask = 1L << (position % BitCacheSize));
1519
			    |= (mask = 1L << (position % BitCacheSize));
1345
			this.extra[5][vectorIndex] |= mask;
1520
			this.extra[5][vectorIndex] |= mask;
1346
			this.extra[3][vectorIndex] &= (mask = ~mask);
1521
			this.extra[3][vectorIndex] &= (mask = ~mask);
Lines 1354-1365 Link Here
1354
	}
1529
	}
1355
}
1530
}
1356
1531
1357
public void resetNullInfo(LocalVariableBinding local) {
1532
public void resetNullInfo(VariableBinding local) {
1358
	if (this != DEAD_END) {
1533
	if (this != DEAD_END) {
1359
		this.tagBits |= NULL_FLAG_MASK;
1534
		this.tagBits |= NULL_FLAG_MASK;
1360
        int position;
1535
        int position;
1361
        long mask;
1536
        long mask;
1362
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1537
        if (local instanceof FieldBinding) {
1538
    		position = local.id;
1539
    	} else {
1540
    		position = local.id + this.maxFieldCount;
1541
    	}
1542
        if (position < BitCacheSize) {
1363
            // use bits
1543
            // use bits
1364
            this.nullBit1 &= (mask = ~(1L << position));
1544
            this.nullBit1 &= (mask = ~(1L << position));
1365
            this.nullBit2 &= mask;
1545
            this.nullBit2 &= mask;
Lines 1367-1374 Link Here
1367
            this.nullBit4 &= mask;
1547
            this.nullBit4 &= mask;
1368
        } else {
1548
        } else {
1369
    		// use extra vector
1549
    		// use extra vector
1370
    		int vectorIndex ;
1550
        	int vectorIndex = (position / BitCacheSize) - 1;
1371
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1551
			if (this.extra == null) {
1552
				int length = vectorIndex + 1;
1553
				this.extra = new long[extraLength][];
1554
				for (int j = 0; j < extraLength; j++) {
1555
					this.extra[j] = new long[length];
1556
				}
1557
			}
1558
			else {
1559
				int oldLength; // might need to grow the arrays
1560
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1561
					for (int j = 0; j < extraLength; j++) {
1562
						System.arraycopy(this.extra[j], 0,
1563
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1564
							oldLength);
1565
					}
1566
				}
1567
			}
1568
    		this.extra[2][vectorIndex]
1372
    		    &= (mask = ~(1L << (position % BitCacheSize)));
1569
    		    &= (mask = ~(1L << (position % BitCacheSize)));
1373
    		this.extra[3][vectorIndex] &= mask;
1570
    		this.extra[3][vectorIndex] &= mask;
1374
    		this.extra[4][vectorIndex] &= mask;
1571
    		this.extra[4][vectorIndex] &= mask;
Lines 1377-1393 Link Here
1377
	}
1574
	}
1378
}
1575
}
1379
1576
1577
public void resetNullInfoForFields() {
1578
	if (this != DEAD_END) {
1579
		for (int position = 0; position < this.maxFieldCount; position++) {
1580
			long mask;
1581
	        if (position < BitCacheSize) {
1582
	            // use bits
1583
	            this.nullBit1 &= (mask = ~(1L << position));
1584
	            this.nullBit2 &= mask;
1585
	            this.nullBit3 &= mask;
1586
	            this.nullBit4 &= mask;
1587
	        } else {
1588
	    		// use extra vector
1589
	        	int vectorIndex = (position / BitCacheSize) - 1;
1590
				if (this.extra == null) {
1591
					int length = vectorIndex + 1;
1592
					this.extra = new long[extraLength][];
1593
					for (int j = 0; j < extraLength; j++) {
1594
						this.extra[j] = new long[length];
1595
					}
1596
				}
1597
				else {
1598
					int oldLength; // might need to grow the arrays
1599
					if (vectorIndex >= (oldLength = this.extra[0].length)) {
1600
						for (int j = 0; j < extraLength; j++) {
1601
							System.arraycopy(this.extra[j], 0,
1602
								(this.extra[j] = new long[vectorIndex + 1]), 0,
1603
								oldLength);
1604
						}
1605
					}
1606
				}
1607
	    		this.extra[2][vectorIndex]
1608
	    		    &= (mask = ~(1L << (position % BitCacheSize)));
1609
	    		this.extra[3][vectorIndex] &= mask;
1610
	    		this.extra[4][vectorIndex] &= mask;
1611
	    		this.extra[5][vectorIndex] &= mask;
1612
	    	}
1613
		}
1614
	}
1615
}
1616
1380
/**
1617
/**
1381
 * Mark a local as potentially having been assigned to an unknown value.
1618
 * Mark a local as potentially having been assigned to an unknown value.
1382
 * @param local the local to mark
1619
 * @param local the local to mark
1383
 */
1620
 */
1384
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
1621
public void markPotentiallyUnknownBit(VariableBinding local) {
1385
	// protected from non-object locals in calling methods
1622
	// protected from non-object locals in calling methods
1386
	if (this != DEAD_END) {
1623
	if (this != DEAD_END) {
1387
		this.tagBits |= NULL_FLAG_MASK;
1624
		this.tagBits |= NULL_FLAG_MASK;
1388
        int position;
1625
        int position;
1389
        long mask;
1626
        long mask;
1390
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1627
        if (local instanceof FieldBinding) {
1628
    		position = local.id;
1629
    	} else {
1630
    		position = local.id + this.maxFieldCount;
1631
    	}
1632
        if (position < BitCacheSize) {
1391
            // use bits
1633
            // use bits
1392
        	mask = 1L << position;
1634
        	mask = 1L << position;
1393
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
1635
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
Lines 1399-1405 Link Here
1399
			}
1641
			}
1400
        } else {
1642
        } else {
1401
    		// use extra vector
1643
    		// use extra vector
1402
    		int vectorIndex = (position / BitCacheSize) - 1;
1644
        	int vectorIndex = (position / BitCacheSize) - 1;
1645
			if (this.extra == null) {
1646
				int length = vectorIndex + 1;
1647
				this.extra = new long[extraLength][];
1648
				for (int j = 0; j < extraLength; j++) {
1649
					this.extra[j] = new long[length];
1650
				}
1651
			}
1652
			else {
1653
				int oldLength; // might need to grow the arrays
1654
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1655
					for (int j = 0; j < extraLength; j++) {
1656
						System.arraycopy(this.extra[j], 0,
1657
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1658
							oldLength);
1659
					}
1660
				}
1661
			}
1403
    		mask = 1L << (position % BitCacheSize);
1662
    		mask = 1L << (position % BitCacheSize);
1404
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
1663
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
1405
    		this.extra[5][vectorIndex] |= mask;
1664
    		this.extra[5][vectorIndex] |= mask;
Lines 1412-1423 Link Here
1412
	}
1671
	}
1413
}
1672
}
1414
1673
1415
public void markPotentiallyNullBit(LocalVariableBinding local) {
1674
public void markPotentiallyNullBit(VariableBinding local) {
1416
	if (this != DEAD_END) {
1675
	if (this != DEAD_END) {
1417
		this.tagBits |= NULL_FLAG_MASK;
1676
		this.tagBits |= NULL_FLAG_MASK;
1418
        int position;
1677
        int position;
1419
        long mask;
1678
        long mask;
1420
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1679
        if (local instanceof FieldBinding) {
1680
    		position = local.id;
1681
    	} else {
1682
    		position = local.id + this.maxFieldCount;
1683
    	}
1684
        if (position < BitCacheSize) {
1421
            // use bits
1685
            // use bits
1422
        	mask = 1L << position;
1686
        	mask = 1L << position;
1423
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
1687
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
Lines 1429-1435 Link Here
1429
			}
1693
			}
1430
        } else {
1694
        } else {
1431
    		// use extra vector
1695
    		// use extra vector
1432
    		int vectorIndex = (position / BitCacheSize) - 1;
1696
        	int vectorIndex = (position / BitCacheSize) - 1;
1697
			if (this.extra == null) {
1698
				int length = vectorIndex + 1;
1699
				this.extra = new long[extraLength][];
1700
				for (int j = 0; j < extraLength; j++) {
1701
					this.extra[j] = new long[length];
1702
				}
1703
			}
1704
			else {
1705
				int oldLength; // might need to grow the arrays
1706
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1707
					for (int j = 0; j < extraLength; j++) {
1708
						System.arraycopy(this.extra[j], 0,
1709
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1710
							oldLength);
1711
					}
1712
				}
1713
			}
1433
    		mask = 1L << (position % BitCacheSize);
1714
    		mask = 1L << (position % BitCacheSize);
1434
    		this.extra[3][vectorIndex] |= mask;
1715
    		this.extra[3][vectorIndex] |= mask;
1435
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
1716
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
Lines 1442-1453 Link Here
1442
	}
1723
	}
1443
}
1724
}
1444
1725
1445
public void markPotentiallyNonNullBit(LocalVariableBinding local) {
1726
public void markPotentiallyNonNullBit(VariableBinding local) {
1446
	if (this != DEAD_END) {
1727
	if (this != DEAD_END) {
1447
		this.tagBits |= NULL_FLAG_MASK;
1728
		this.tagBits |= NULL_FLAG_MASK;
1448
        int position;
1729
        int position;
1449
        long mask;
1730
        long mask;
1450
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1731
        if (local instanceof FieldBinding) {
1732
    		position = local.id;
1733
    	} else {
1734
    		position = local.id + this.maxFieldCount;
1735
    	}
1736
        if (position < BitCacheSize) {
1451
            // use bits
1737
            // use bits
1452
        	mask = 1L << position;
1738
        	mask = 1L << position;
1453
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
1739
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
Lines 1459-1465 Link Here
1459
			}
1745
			}
1460
        } else {
1746
        } else {
1461
    		// use extra vector
1747
    		// use extra vector
1462
    		int vectorIndex  = (position / BitCacheSize) - 1;
1748
        	int vectorIndex = (position / BitCacheSize) - 1;
1749
			if (this.extra == null) {
1750
				int length = vectorIndex + 1;
1751
				this.extra = new long[extraLength][];
1752
				for (int j = 0; j < extraLength; j++) {
1753
					this.extra[j] = new long[length];
1754
				}
1755
			}
1756
			else {
1757
				int oldLength; // might need to grow the arrays
1758
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1759
					for (int j = 0; j < extraLength; j++) {
1760
						System.arraycopy(this.extra[j], 0,
1761
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1762
							oldLength);
1763
					}
1764
				}
1765
			}
1463
    		mask = 1L << (position % BitCacheSize);
1766
    		mask = 1L << (position % BitCacheSize);
1464
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
1767
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
1465
    		this.extra[4][vectorIndex] |= mask;
1768
    		this.extra[4][vectorIndex] |= mask;
Lines 1951-1958 Link Here
1951
	return this;
2254
	return this;
1952
}
2255
}
1953
2256
1954
public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
2257
public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding) {
1955
	int position = local.id + this.maxFieldCount;
2258
	int position;
2259
	if (binding instanceof FieldBinding) {
2260
		position = binding.id;
2261
	} else {
2262
		position = binding.id + this.maxFieldCount;
2263
	}
1956
	int oldLength;
2264
	int oldLength;
1957
	if (this.nullStatusChangedInAssert == null) {
2265
	if (this.nullStatusChangedInAssert == null) {
1958
		this.nullStatusChangedInAssert = new int[position + 1];
2266
		this.nullStatusChangedInAssert = new int[position + 1];
Lines 1965-1972 Link Here
1965
	this.nullStatusChangedInAssert[position] = 1;
2273
	this.nullStatusChangedInAssert[position] = 1;
1966
}
2274
}
1967
2275
1968
public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
2276
public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding) {
1969
	int position = local.id + this.maxFieldCount;
2277
	int position;
2278
	if (binding instanceof FieldBinding) {
2279
		position = binding.id;
2280
	} else {
2281
		position = binding.id + this.maxFieldCount;
2282
	}
1970
	if(this.nullStatusChangedInAssert == null || position >= this.nullStatusChangedInAssert.length) {
2283
	if(this.nullStatusChangedInAssert == null || position >= this.nullStatusChangedInAssert.length) {
1971
		return false;
2284
		return false;
1972
	}
2285
	}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (+4 lines)
Lines 1220-1223 Link Here
1220
MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
1220
MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
1221
	return this.methods;
1221
	return this.methods;
1222
}
1222
}
1223
1224
public FieldBinding[] unResolvedFields() {
1225
	return this.fields;
1226
}
1223
}
1227
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java (+11 lines)
Lines 16-26 Link Here
16
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
16
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
17
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
17
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
19
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
21
21
public class FieldBinding extends VariableBinding {
22
public class FieldBinding extends VariableBinding {
22
	public ReferenceBinding declaringClass;
23
	public ReferenceBinding declaringClass;
23
	public int compoundUseFlag = 0; // number or accesses via postIncrement or compoundAssignment
24
	public int compoundUseFlag = 0; // number or accesses via postIncrement or compoundAssignment
25
	private int nullStatus;
24
	
26
	
25
protected FieldBinding() {
27
protected FieldBinding() {
26
	super(null, null, 0, null);
28
	super(null, null, 0, null);
Lines 29-34 Link Here
29
public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
31
public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
30
	super(name, type, modifiers, constant);
32
	super(name, type, modifiers, constant);
31
	this.declaringClass = declaringClass;
33
	this.declaringClass = declaringClass;
34
	this.nullStatus = FlowInfo.UNKNOWN;
32
}
35
}
33
// special API used to change field declaring class for runtime visibility check
36
// special API used to change field declaring class for runtime visibility check
34
public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
37
public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
Lines 386-389 Link Here
386
	}
389
	}
387
	return null;
390
	return null;
388
}
391
}
392
393
public int getNullStatusForStaticFinalField() {
394
	return this.nullStatus;
395
}
396
397
public void setNullStatusForStaticFinalField(int nullStatusToMark) {
398
	this.nullStatus = nullStatusToMark;
399
}
389
}
400
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java (+4 lines)
Lines 1115-1118 Link Here
1115
		}
1115
		}
1116
		return Binding.NO_TYPE_VARIABLES;
1116
		return Binding.NO_TYPE_VARIABLES;
1117
	}
1117
	}
1118
	
1119
	public FieldBinding[] unResolvedFields() {
1120
		return this.fields;
1121
	}
1118
}
1122
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (+4 lines)
Lines 1376-1379 Link Here
1376
MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
1376
MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
1377
	return methods();
1377
	return methods();
1378
}
1378
}
1379
1380
public FieldBinding[] unResolvedFields() {
1381
	return Binding.NO_FIELDS;
1382
}
1379
}
1383
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java (+12 lines)
Lines 3872-3877 Link Here
3872
		} while (scope != null);
3872
		} while (scope != null);
3873
		return lastMethodScope; // may answer null if no method around
3873
		return lastMethodScope; // may answer null if no method around
3874
	}
3874
	}
3875
	
3876
	public boolean isOuterMostMethodSynchronised() {
3877
		MethodScope outerMostMethodScope = this.outerMostMethodScope();
3878
		boolean isSynchronised = false;
3879
		if(outerMostMethodScope != null) {
3880
			AbstractMethodDeclaration referenceMethod = outerMostMethodScope.referenceMethod();
3881
			if(referenceMethod != null && referenceMethod.binding != null) {
3882
				isSynchronised = referenceMethod.binding.isSynchronized();
3883
			}
3884
		}
3885
		return isSynchronised;
3886
	}
3875
3887
3876
	public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
3888
	public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
3877
		TypeBinding[] parameters = method.parameters;
3889
		TypeBinding[] parameters = method.parameters;
(-)compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (+178 lines)
Lines 103-108 Link Here
103
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
103
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
104
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
104
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
105
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
105
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
106
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
106
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
107
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
107
import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants;
108
import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants;
108
import org.eclipse.jdt.internal.compiler.parser.Parser;
109
import org.eclipse.jdt.internal.compiler.parser.Parser;
Lines 280-296 Link Here
280
			return CompilerOptions.VarargsArgumentNeedCast;
281
			return CompilerOptions.VarargsArgumentNeedCast;
281
282
282
		case IProblem.NullLocalVariableReference:
283
		case IProblem.NullLocalVariableReference:
284
		case IProblem.NullFieldReference:
283
			return CompilerOptions.NullReference;
285
			return CompilerOptions.NullReference;
284
286
285
		case IProblem.PotentialNullLocalVariableReference:
287
		case IProblem.PotentialNullLocalVariableReference:
288
		case IProblem.PotentialNullFieldReference:
286
			return CompilerOptions.PotentialNullReference;
289
			return CompilerOptions.PotentialNullReference;
287
290
288
		case IProblem.RedundantLocalVariableNullAssignment:
291
		case IProblem.RedundantLocalVariableNullAssignment:
292
		case IProblem.RedundantFieldNullAssignment:
289
		case IProblem.RedundantNullCheckOnNonNullLocalVariable:
293
		case IProblem.RedundantNullCheckOnNonNullLocalVariable:
290
		case IProblem.RedundantNullCheckOnNullLocalVariable:
294
		case IProblem.RedundantNullCheckOnNullLocalVariable:
291
		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
295
		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
292
		case IProblem.NullLocalVariableComparisonYieldsFalse:
296
		case IProblem.NullLocalVariableComparisonYieldsFalse:
293
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
297
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
298
		case IProblem.NullFieldInstanceofYieldsFalse:
299
		case IProblem.RedundantNullCheckOnNonNullField:
300
		case IProblem.RedundantNullCheckOnNullField:
301
		case IProblem.NonNullFieldComparisonYieldsFalse:
302
		case IProblem.NullFieldComparisonYieldsFalse:
294
			return CompilerOptions.RedundantNullCheck;
303
			return CompilerOptions.RedundantNullCheck;
295
304
296
		case IProblem.BoxingConversion :
305
		case IProblem.BoxingConversion :
Lines 4866-4871 Link Here
4866
	}
4875
	}
4867
}
4876
}
4868
4877
4878
public void reportNonNullComparedToNullProblem(VariableBinding variable, ASTNode location) {
4879
	if (variable instanceof FieldBinding) {
4880
		this.fieldNonNullComparedToNull((FieldBinding)variable, location);
4881
	} else {
4882
		this.localVariableNonNullComparedToNull((LocalVariableBinding)variable, location);
4883
	}
4884
}
4885
4869
public void localVariableNonNullComparedToNull(LocalVariableBinding local, ASTNode location) {
4886
public void localVariableNonNullComparedToNull(LocalVariableBinding local, ASTNode location) {
4870
	int severity = computeSeverity(IProblem.NonNullLocalVariableComparisonYieldsFalse);
4887
	int severity = computeSeverity(IProblem.NonNullLocalVariableComparisonYieldsFalse);
4871
	if (severity == ProblemSeverities.Ignore) return;
4888
	if (severity == ProblemSeverities.Ignore) return;
Lines 4879-4884 Link Here
4879
		nodeSourceEnd(local, location));
4896
		nodeSourceEnd(local, location));
4880
}
4897
}
4881
4898
4899
public void fieldNonNullComparedToNull(FieldBinding field, ASTNode location) {
4900
	int severity = computeSeverity(IProblem.NonNullFieldComparisonYieldsFalse);
4901
	if (severity == ProblemSeverities.Ignore) return;
4902
	String[] arguments = new String[] {new String(field.name)  };
4903
	this.handle(
4904
		IProblem.NonNullFieldComparisonYieldsFalse,
4905
		arguments,
4906
		arguments,
4907
		severity,
4908
		nodeSourceStart(field, location),
4909
		nodeSourceEnd(field, location));
4910
}
4911
4912
public void reportNullComparedToNonNullProblem(VariableBinding variable, ASTNode location) {
4913
	if (variable instanceof FieldBinding) {
4914
		//if (variable.isFinal() && ((FieldBinding)variable).isStatic())
4915
			this.fieldNullComparedToNonNull((FieldBinding)variable, location);
4916
	} else {
4917
		this.localVariableNullComparedToNonNull((LocalVariableBinding)variable, location);
4918
	}
4919
}
4920
4882
public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNode location) {
4921
public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNode location) {
4883
	int severity = computeSeverity(IProblem.NullLocalVariableComparisonYieldsFalse);
4922
	int severity = computeSeverity(IProblem.NullLocalVariableComparisonYieldsFalse);
4884
	if (severity == ProblemSeverities.Ignore) return;
4923
	if (severity == ProblemSeverities.Ignore) return;
Lines 4892-4897 Link Here
4892
		nodeSourceEnd(local, location));
4931
		nodeSourceEnd(local, location));
4893
}
4932
}
4894
4933
4934
public void fieldNullComparedToNonNull(FieldBinding field, ASTNode location) {
4935
	int severity = computeSeverity(IProblem.NullFieldComparisonYieldsFalse);
4936
	if (severity == ProblemSeverities.Ignore) return;
4937
	String[] arguments = new String[] {new String(field.name)  };
4938
	this.handle(
4939
		IProblem.NullFieldComparisonYieldsFalse,
4940
		arguments,
4941
		arguments,
4942
		severity,
4943
		nodeSourceStart(field, location),
4944
		nodeSourceEnd(field, location));
4945
}
4946
4947
public void reportNullInstanceofProblem(VariableBinding variable, ASTNode location) {
4948
	if (variable instanceof FieldBinding) {
4949
		this.fieldNullInstanceof((FieldBinding) variable, location);
4950
	} else {
4951
		this.localVariableNullInstanceof((LocalVariableBinding) variable, location);
4952
	}
4953
}
4954
4895
public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) {
4955
public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) {
4896
	int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse);
4956
	int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse);
4897
	if (severity == ProblemSeverities.Ignore) return;
4957
	if (severity == ProblemSeverities.Ignore) return;
Lines 4905-4910 Link Here
4905
		nodeSourceEnd(local, location));
4965
		nodeSourceEnd(local, location));
4906
}
4966
}
4907
4967
4968
public void fieldNullInstanceof(FieldBinding field, ASTNode location) {
4969
	int severity = computeSeverity(IProblem.NullFieldInstanceofYieldsFalse);
4970
	if (severity == ProblemSeverities.Ignore) return;
4971
	String[] arguments = new String[] {new String(field.name)  };
4972
	this.handle(
4973
		IProblem.NullFieldInstanceofYieldsFalse,
4974
		arguments,
4975
		arguments,
4976
		severity,
4977
		nodeSourceStart(field, location),
4978
		nodeSourceEnd(field, location));
4979
}
4980
4981
public void reportNullReferenceProblem(VariableBinding variable, ASTNode location) {
4982
	if (variable instanceof FieldBinding) {
4983
		this.fieldNullReference((FieldBinding) variable, location);
4984
	} else {
4985
		this.localVariableNullReference((LocalVariableBinding) variable, location);
4986
	}
4987
}
4988
4908
public void localVariableNullReference(LocalVariableBinding local, ASTNode location) {
4989
public void localVariableNullReference(LocalVariableBinding local, ASTNode location) {
4909
	int severity = computeSeverity(IProblem.NullLocalVariableReference);
4990
	int severity = computeSeverity(IProblem.NullLocalVariableReference);
4910
	if (severity == ProblemSeverities.Ignore) return;
4991
	if (severity == ProblemSeverities.Ignore) return;
Lines 4918-4923 Link Here
4918
		nodeSourceEnd(local, location));
4999
		nodeSourceEnd(local, location));
4919
}
5000
}
4920
5001
5002
public void fieldNullReference(FieldBinding field, ASTNode location) {
5003
	int severity = computeSeverity(IProblem.NullFieldReference);
5004
	if (severity == ProblemSeverities.Ignore) return;
5005
	String[] arguments = new String[] {new String(field.name)  };
5006
	this.handle(
5007
		IProblem.NullFieldReference,
5008
		arguments,
5009
		arguments,
5010
		severity,
5011
		nodeSourceStart(field, location),
5012
		nodeSourceEnd(field, location));
5013
}
5014
5015
public void reportPotentialNullReferenceProblem(VariableBinding variable, ASTNode location) {
5016
	if (variable instanceof FieldBinding) {
5017
		this.fieldPotentialNullReference((FieldBinding) variable, location);
5018
	} else {
5019
		this.localVariablePotentialNullReference((LocalVariableBinding) variable, location);
5020
	}
5021
}
5022
4921
public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) {
5023
public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) {
4922
	int severity = computeSeverity(IProblem.PotentialNullLocalVariableReference);
5024
	int severity = computeSeverity(IProblem.PotentialNullLocalVariableReference);
4923
	if (severity == ProblemSeverities.Ignore) return;
5025
	if (severity == ProblemSeverities.Ignore) return;
Lines 4931-4936 Link Here
4931
		nodeSourceEnd(local, location));
5033
		nodeSourceEnd(local, location));
4932
}
5034
}
4933
5035
5036
public void fieldPotentialNullReference(FieldBinding field, ASTNode location) {
5037
	int severity = computeSeverity(IProblem.PotentialNullFieldReference);
5038
	if (severity == ProblemSeverities.Ignore) return;
5039
	String[] arguments = new String[] {new String(field.name)};
5040
	this.handle(
5041
		IProblem.PotentialNullFieldReference,
5042
		arguments,
5043
		arguments,
5044
		severity,
5045
		nodeSourceStart(field, location),
5046
		nodeSourceEnd(field, location));
5047
}
5048
5049
public void reportRedundantCheckOnNonNullProblem(VariableBinding variable, ASTNode location) {
5050
	if (variable instanceof FieldBinding) {
5051
		this.fieldRedundantCheckOnNonNull((FieldBinding) variable, location);
5052
	} else {
5053
		this.localVariableRedundantCheckOnNonNull((LocalVariableBinding) variable, location);
5054
	}
5055
}
5056
4934
public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) {
5057
public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) {
4935
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable);
5058
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable);
4936
	if (severity == ProblemSeverities.Ignore) return;
5059
	if (severity == ProblemSeverities.Ignore) return;
Lines 4944-4949 Link Here
4944
		nodeSourceEnd(local, location));
5067
		nodeSourceEnd(local, location));
4945
}
5068
}
4946
5069
5070
public void fieldRedundantCheckOnNonNull(FieldBinding local, ASTNode location) {
5071
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullField);
5072
	if (severity == ProblemSeverities.Ignore) return;
5073
	String[] arguments = new String[] {new String(local.name)  };
5074
	this.handle(
5075
		IProblem.RedundantNullCheckOnNonNullField,
5076
		arguments,
5077
		arguments,
5078
		severity,
5079
		nodeSourceStart(local, location),
5080
		nodeSourceEnd(local, location));
5081
}
5082
5083
public void reportRedundantCheckOnNullProblem (VariableBinding variable, ASTNode location) {
5084
	if (variable instanceof FieldBinding) {
5085
		this.fieldRedundantCheckOnNull((FieldBinding)variable, location);
5086
	} else {
5087
		this.localVariableRedundantCheckOnNull((LocalVariableBinding)variable, location);
5088
	}
5089
}
5090
4947
public void localVariableRedundantCheckOnNull(LocalVariableBinding local, ASTNode location) {
5091
public void localVariableRedundantCheckOnNull(LocalVariableBinding local, ASTNode location) {
4948
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNullLocalVariable);
5092
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNullLocalVariable);
4949
	if (severity == ProblemSeverities.Ignore) return;
5093
	if (severity == ProblemSeverities.Ignore) return;
Lines 4957-4962 Link Here
4957
		nodeSourceEnd(local, location));
5101
		nodeSourceEnd(local, location));
4958
}
5102
}
4959
5103
5104
public void fieldRedundantCheckOnNull(FieldBinding field, ASTNode location) {
5105
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNullField);
5106
	if (severity == ProblemSeverities.Ignore) return;
5107
	String[] arguments = new String[] {new String(field.name)  };
5108
	this.handle(
5109
		IProblem.RedundantNullCheckOnNullField,
5110
		arguments,
5111
		arguments,
5112
		severity,
5113
		nodeSourceStart(field, location),
5114
		nodeSourceEnd(field, location));
5115
}
5116
5117
public void reportRedundantNullAssignmentProblem (VariableBinding variable, ASTNode location) {
5118
	if (variable instanceof FieldBinding) {
5119
		this.fieldRedundantNullAssignment((FieldBinding)variable, location);
5120
	} else {
5121
		this.localVariableRedundantNullAssignment((LocalVariableBinding)variable, location);
5122
	}
5123
}
5124
4960
public void localVariableRedundantNullAssignment(LocalVariableBinding local, ASTNode location) {
5125
public void localVariableRedundantNullAssignment(LocalVariableBinding local, ASTNode location) {
4961
	int severity = computeSeverity(IProblem.RedundantLocalVariableNullAssignment);
5126
	int severity = computeSeverity(IProblem.RedundantLocalVariableNullAssignment);
4962
	if (severity == ProblemSeverities.Ignore) return;
5127
	if (severity == ProblemSeverities.Ignore) return;
Lines 4970-4975 Link Here
4970
		nodeSourceEnd(local, location));
5135
		nodeSourceEnd(local, location));
4971
}
5136
}
4972
5137
5138
public void fieldRedundantNullAssignment(FieldBinding field, ASTNode location) {
5139
	int severity = computeSeverity(IProblem.RedundantFieldNullAssignment);
5140
	if (severity == ProblemSeverities.Ignore) return;
5141
	String[] arguments = new String[] {new String(field.name)  };
5142
	this.handle(
5143
		IProblem.RedundantFieldNullAssignment,
5144
		arguments,
5145
		arguments,
5146
		severity,
5147
		nodeSourceStart(field, location),
5148
		nodeSourceEnd(field, location));
5149
}
5150
4973
public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) {
5151
public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) {
4974
	MethodBinding binding = method.binding;
5152
	MethodBinding binding = method.binding;
4975
	this.handle(
5153
	this.handle(
(-)compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+10 lines)
Lines 572-577 Link Here
572
### MORE GENERICS
572
### MORE GENERICS
573
660 = Unused type arguments for the non generic constructor {0}({1}) of type {2}; it should not be parameterized with arguments <{3}>
573
660 = Unused type arguments for the non generic constructor {0}({1}) of type {2}; it should not be parameterized with arguments <{3}>
574
574
575
### NULL ANALYSIS FOR FIELDS
576
670 = Null pointer access: The field {0} can only be null at this location
577
671 = Potential null pointer access: The field {0} may be null at this location
578
672 = Redundant null check: The field {0} can only be null at this location
579
673 = Null comparison always yields false: The field {0} can only be null at this location
580
674 = Redundant null check: The field {0} cannot be null at this location
581
675 = Null comparison always yields false: The field {0} cannot be null at this location
582
676 = Redundant assignment: The field {0} can only be null at this location
583
677 = instanceof always yields false: The field {0} can only be null at this location
584
575
### CORRUPTED BINARIES
585
### CORRUPTED BINARIES
576
700 = The class file {0} contains a signature ''{1}'' ill-formed at position {2}
586
700 = The class file {0} contains a signature ''{1}'' ill-formed at position {2}
577
587
(-)src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java (+16 lines)
Lines 696-701 Link Here
696
		expectedProblemAttributes.put("NonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
696
		expectedProblemAttributes.put("NonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
697
		expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
697
		expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
698
		expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
698
		expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
699
		expectedProblemAttributes.put("NonNullFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
699
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
700
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
700
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
701
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
701
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
702
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
Lines 708-713 Link Here
708
		expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
709
		expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
709
		expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
710
		expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
710
		expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
711
		expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
712
		expectedProblemAttributes.put("NullFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
713
		expectedProblemAttributes.put("NullFieldInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
714
		expectedProblemAttributes.put("NullFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
711
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
715
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
712
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
716
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
713
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
717
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
Lines 745-750 Link Here
745
		expectedProblemAttributes.put("ParsingErrorReplaceTokens", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
749
		expectedProblemAttributes.put("ParsingErrorReplaceTokens", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
746
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
750
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
747
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
751
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
752
		expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
748
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
753
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
749
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
754
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
750
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
755
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
Lines 752-759 Link Here
752
		expectedProblemAttributes.put("RecursiveConstructorInvocation", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
757
		expectedProblemAttributes.put("RecursiveConstructorInvocation", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
753
		expectedProblemAttributes.put("RedefinedArgument", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
758
		expectedProblemAttributes.put("RedefinedArgument", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
754
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
759
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
760
		expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
755
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
761
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
762
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
756
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
763
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
764
		expectedProblemAttributes.put("RedundantNullCheckOnNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
757
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
765
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
758
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
766
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
759
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
767
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
Lines 1333-1338 Link Here
1333
		expectedProblemAttributes.put("NonGenericConstructor", SKIP);
1341
		expectedProblemAttributes.put("NonGenericConstructor", SKIP);
1334
		expectedProblemAttributes.put("NonGenericMethod", SKIP);
1342
		expectedProblemAttributes.put("NonGenericMethod", SKIP);
1335
		expectedProblemAttributes.put("NonGenericType", SKIP);
1343
		expectedProblemAttributes.put("NonGenericType", SKIP);
1344
		expectedProblemAttributes.put("NonNullFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1336
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1345
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1337
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1346
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1338
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1347
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
Lines 1345-1350 Link Here
1345
		expectedProblemAttributes.put("NotVisibleField", SKIP);
1354
		expectedProblemAttributes.put("NotVisibleField", SKIP);
1346
		expectedProblemAttributes.put("NotVisibleMethod", SKIP);
1355
		expectedProblemAttributes.put("NotVisibleMethod", SKIP);
1347
		expectedProblemAttributes.put("NotVisibleType", SKIP);
1356
		expectedProblemAttributes.put("NotVisibleType", SKIP);
1357
		expectedProblemAttributes.put("NullFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1358
		expectedProblemAttributes.put("NullFieldInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1359
		expectedProblemAttributes.put("NullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
1348
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1360
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1349
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1361
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1350
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
1362
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
Lines 1382-1387 Link Here
1382
		expectedProblemAttributes.put("ParsingErrorReplaceTokens", SKIP);
1394
		expectedProblemAttributes.put("ParsingErrorReplaceTokens", SKIP);
1383
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", SKIP);
1395
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", SKIP);
1384
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
1396
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
1397
		expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1385
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1398
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1386
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1399
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1387
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1400
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
Lines 1389-1396 Link Here
1389
		expectedProblemAttributes.put("RecursiveConstructorInvocation", SKIP);
1402
		expectedProblemAttributes.put("RecursiveConstructorInvocation", SKIP);
1390
		expectedProblemAttributes.put("RedefinedArgument", SKIP);
1403
		expectedProblemAttributes.put("RedefinedArgument", SKIP);
1391
		expectedProblemAttributes.put("RedefinedLocal", SKIP);
1404
		expectedProblemAttributes.put("RedefinedLocal", SKIP);
1405
		expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1392
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1406
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1407
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1393
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1408
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1409
		expectedProblemAttributes.put("RedundantNullCheckOnNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1394
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1410
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1395
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
1411
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
1396
		expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
1412
		expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java (-13 / +33 lines)
Lines 34-42 Link Here
34
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
34
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
35
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException;
35
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException;
36
import org.eclipse.jdt.internal.compiler.impl.Constant;
36
import org.eclipse.jdt.internal.compiler.impl.Constant;
37
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
37
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
39
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
39
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
40
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
41
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
40
42
41
/**
43
/**
42
 * A tests series especially meant to validate the internals of our null
44
 * A tests series especially meant to validate the internals of our null
Lines 804-810 Link Here
804
					result2 = (UnconditionalFlowInfoTestHarness) source1.copy();
806
					result2 = (UnconditionalFlowInfoTestHarness) source1.copy();
805
					if (source2.isDefinitelyNonNull(TestLocalVariableBinding.local0)) {
807
					if (source2.isDefinitelyNonNull(TestLocalVariableBinding.local0)) {
806
						if (! source2.isProtectedNonNull(TestLocalVariableBinding.local0)) {
808
						if (! source2.isProtectedNonNull(TestLocalVariableBinding.local0)) {
807
							result1.markAsDefinitelyNonNull(TestLocalVariableBinding.local0);
809
							result1.markAsDefinitelyNonNull(TestLocalVariableBinding.local0, false);
808
						} else {
810
						} else {
809
							continue;
811
							continue;
810
						}
812
						}
Lines 1083-1100 Link Here
1083
	return copy;
1085
	return copy;
1084
}
1086
}
1085
1087
1086
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
1088
public void markAsDefinitelyNonNull(VariableBinding local, boolean isSynchronised) {
1087
	grow(local.id + this.maxFieldCount);
1089
	int position;
1088
	super.markAsDefinitelyNonNull(local);
1090
	if (local instanceof FieldBinding) {
1089
}
1091
		position = local.id;
1090
1092
	} else {
1091
public void markAsDefinitelyNull(LocalVariableBinding local) {
1093
		position = local.id + this.maxFieldCount;
1092
	grow(local.id + this.maxFieldCount);
1094
	}
1093
	super.markAsDefinitelyNull(local);
1095
	grow(position);
1094
}
1096
	super.markAsDefinitelyNonNull(local, isSynchronised);
1095
1097
}
1096
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
1098
1097
	grow(local.id + this.maxFieldCount);
1099
public void markAsDefinitelyNull(VariableBinding local) {
1100
	int position;
1101
	if (local instanceof FieldBinding) {
1102
		position = local.id;
1103
	} else {
1104
		position = local.id + this.maxFieldCount;
1105
	}
1106
	grow(position);
1107
	super.markAsDefinitelyNull(local, false);
1108
}
1109
1110
public void markAsDefinitelyUnknown(VariableBinding local) {
1111
	int position;
1112
	if (local instanceof FieldBinding) {
1113
		position = local.id;
1114
	} else {
1115
		position = local.id + this.maxFieldCount;
1116
	}
1117
	grow(position);
1098
	super.markAsDefinitelyUnknown(local);
1118
	super.markAsDefinitelyUnknown(local);
1099
}
1119
}
1100
1120
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java (-4 / +4 lines)
Lines 65-71 Link Here
65
				UnconditionalFlowInfo output(UnconditionalFlowInfo input,
65
				UnconditionalFlowInfo output(UnconditionalFlowInfo input,
66
						TestLocalVariableBinding local) {
66
						TestLocalVariableBinding local) {
67
					UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
67
					UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
68
					result.markAsComparedEqualToNonNull(local);
68
					result.markAsComparedEqualToNonNull(local, false);
69
					return result;
69
					return result;
70
				}
70
				}
71
			},
71
			},
Lines 108-114 Link Here
108
			UnconditionalFlowInfo output(UnconditionalFlowInfo input,
108
			UnconditionalFlowInfo output(UnconditionalFlowInfo input,
109
					TestLocalVariableBinding local) {
109
					TestLocalVariableBinding local) {
110
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
110
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
111
				result.markAsComparedEqualToNull(local);
111
				result.markAsComparedEqualToNull(local, false);
112
				return result;
112
				return result;
113
			}
113
			}
114
		},
114
		},
Lines 151-157 Link Here
151
			UnconditionalFlowInfo output(UnconditionalFlowInfo input,
151
			UnconditionalFlowInfo output(UnconditionalFlowInfo input,
152
					TestLocalVariableBinding local) {
152
					TestLocalVariableBinding local) {
153
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
153
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
154
				result.markAsDefinitelyNonNull(local);
154
				result.markAsDefinitelyNonNull(local, false);
155
				return result;
155
				return result;
156
			}
156
			}
157
		},
157
		},
Lines 195-201 Link Here
195
			UnconditionalFlowInfo output(UnconditionalFlowInfo input,
195
			UnconditionalFlowInfo output(UnconditionalFlowInfo input,
196
					TestLocalVariableBinding local) {
196
					TestLocalVariableBinding local) {
197
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
197
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
198
				result.markAsDefinitelyNull(local);
198
				result.markAsDefinitelyNull(local, false);
199
				return result;
199
				return result;
200
			}
200
			}
201
		},
201
		},
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-36 / +431 lines)
Lines 36-42 Link Here
36
// Only the highest compliance level is run; add the VM argument
36
// Only the highest compliance level is run; add the VM argument
37
// -Dcompliance=1.4 (for example) to lower it if needed
37
// -Dcompliance=1.4 (for example) to lower it if needed
38
static {
38
static {
39
//		TESTS_NAMES = new String[] { "testBug325229" };
39
//		TESTS_NAMES = new String[] { "test0002_simple_field" };
40
//		TESTS_NUMBERS = new int[] { 561 };
40
//		TESTS_NUMBERS = new int[] { 561 };
41
//		TESTS_RANGE = new int[] { 1, 2049 };
41
//		TESTS_RANGE = new int[] { 1, 2049 };
42
}
42
}
Lines 96-108 Link Here
96
			"    o.toString();\n" +
96
			"    o.toString();\n" +
97
			"  }\n" +
97
			"  }\n" +
98
			"}\n"},
98
			"}\n"},
99
	""
99
      "----------\n" +
100
//      "----------\n" +
100
      "1. ERROR in X.java (at line 5)\n" + 
101
//      "1. ERROR in X.java (at line 5)\n" +
101
      "	o.toString();\n" + 
102
//      "	o.toString();\n" +
102
      "	^\n" + 
103
//      "	^\n" +
103
      "Potential null pointer access: The field o may be null at this location\n" + 
104
//      "The field o is likely null; it was either set to null or checked for null when last used\n" +
104
      "----------\n"
105
//      "----------\n"
106
	);
105
	);
107
}
106
}
108
107
Lines 333-345 Link Here
333
			"    this.o.toString();\n" +
332
			"    this.o.toString();\n" +
334
			"  }\n" +
333
			"  }\n" +
335
			"}\n"},
334
			"}\n"},
336
		""
335
        "----------\n" + 
337
//      "----------\n" +
336
		"1. ERROR in X.java (at line 5)\n" + 
338
//      "1. ERROR in X.java (at line 5)\n" +
337
		"	this.o.toString();\n" + 
339
//      "	this.o.toString();\n" +
338
		"	     ^\n" + 
340
//      "	^^^^^^\n" +
339
		"Potential null pointer access: The field o may be null at this location\n" + 
341
//      "The field o is likely null; it was either set to null or checked for null when last used\n" +
340
		"----------\n"
342
//      "----------\n"
343
	);
341
	);
344
}
342
}
345
343
Lines 355-367 Link Here
355
			"    o.toString();\n" +
353
			"    o.toString();\n" +
356
			"  }\n" +
354
			"  }\n" +
357
			"}\n"},
355
			"}\n"},
358
		""
356
        "----------\n" + 
359
//      "----------\n" +
357
		"1. ERROR in X.java (at line 5)\n" + 
360
//      "1. ERROR in X.java (at line 5)\n" +
358
		"	o.toString();\n" + 
361
//      "	o.toString();\n" +
359
		"	^\n" + 
362
//      "	^\n" +
360
		"Potential null pointer access: The field o may be null at this location\n" + 
363
//      "The field o is likely null; it was either set to null or checked for null when last used\n" +
361
		"----------\n"
364
//      "----------\n"
365
	);
362
	);
366
}
363
}
367
364
Lines 411-423 Link Here
411
			"    }\n" +
408
			"    }\n" +
412
			"  }\n" +
409
			"  }\n" +
413
			"}\n"},
410
			"}\n"},
414
		""
411
        "----------\n" +
415
//      "----------\n" +
412
        "1. ERROR in X.java (at line 6)\n" + 
416
//      "1. ERROR in X.java (at line 6)\n" +
413
		"	X.this.o.toString();\n" + 
417
//      "	X.this.o.toString();\n" +
414
		"	       ^\n" + 
418
//      "	^^^^^^^^\n" +
415
		"Potential null pointer access: The field o may be null at this location\n" + 
419
//      "The field o is likely null; it was either set to null or checked for null when last used\n" +
416
		"----------\n"
420
//      "----------\n"
421
	);
417
	);
422
}
418
}
423
419
Lines 436-448 Link Here
436
			"  }\n" +
432
			"  }\n" +
437
			"  void bar() {/* */}\n" +
433
			"  void bar() {/* */}\n" +
438
			"}\n"},
434
			"}\n"},
439
		""
435
        "----------\n" +
440
//      "----------\n" +
436
        "1. ERROR in X.java (at line 5)\n" + 
441
//      "1. ERROR in X.java (at line 5)\n" +
437
		"	o.toString();\n" + 
442
//      "	o.toString();\n" +
438
		"	^\n" + 
443
//      "	^\n" +
439
		"Null pointer access: The field o can only be null at this location\n" + 
444
//      "The field o is likely null; it was either set to null or checked for null when last used\n" +
440
		"----------\n"
445
//      "----------\n"
446
	);
441
	);
447
}
442
}
448
443
Lines 13673-13678 Link Here
13673
			"}"},
13668
			"}"},
13674
		"null220");
13669
		"null220");
13675
}
13670
}
13671
13672
// null analysis -- simple case for field
13673
public void testBug247564a() {
13674
	this.runNegativeTest(
13675
		new String[] {
13676
			"X.java",
13677
			"public class X {\n" +
13678
			"  Object o;\n" +
13679
			"  void foo() {\n" +
13680
			"    if (o == null && o.toString() == \"\"){}\n" +
13681
			"    else {}\n" +
13682
			"    o.toString();\n" + // toString() call above defuses null info, so no warning here
13683
			"  }\n" +
13684
			"}\n"},
13685
		"----------\n" + 
13686
		"1. ERROR in X.java (at line 4)\n" + 
13687
		"	if (o == null && o.toString() == \"\"){}\n" + 
13688
		"	                 ^\n" + 
13689
		"Potential null pointer access: The field o may be null at this location\n" + 
13690
		"----------\n"
13691
	);
13692
}
13693
13694
// null analysis -- simple case for field
13695
// no redundant null check warnings should be obtained since value of field
13696
// may be changed in another thread.
13697
public void testBug247564a_1() {
13698
	this.runNegativeTest(
13699
		new String[] {
13700
			"X.java",
13701
			"public class X {\n" +
13702
			"  Object o;\n" +
13703
			"  void foo() {\n" +
13704
			"	 o = null;" +
13705
			"    if (o == null){}\n" +
13706
			"    if (o != null){}\n" +	
13707
			"    o.toString();\n" +	// warn here
13708
			"  }\n" +
13709
			"}\n"},
13710
		"----------\n" +  
13711
		"1. ERROR in X.java (at line 6)\n" + 
13712
		"	o.toString();\n" + 
13713
		"	^\n" + 
13714
		"Potential null pointer access: The field o may be null at this location\n" + 
13715
		"----------\n"
13716
	);
13717
}
13718
13719
// null analysis -- simple case for field
13720
public void testBug247564a_2() {
13721
	this.runNegativeTest(
13722
		new String[] {
13723
			"X.java",
13724
			"public class X {\n" +
13725
			"  Object o;\n" +
13726
			"  void foo() {\n" +
13727
			"    if (o == null){\n" +	// o is null inside the if block
13728
			"		o.toString();\n" +
13729
			"    }\n" +
13730
			"  }\n" +
13731
			"}\n"},
13732
		"----------\n" + 
13733
		"1. ERROR in X.java (at line 5)\n" + 
13734
		"	o.toString();\n" + 
13735
		"	^\n" + 
13736
		"Potential null pointer access: The field o may be null at this location\n" + 
13737
		"----------\n"
13738
	);
13739
}
13740
13741
// null analysis -- simple case for field
13742
// null info from one method should not be present in the other (for instance fields)
13743
public void testBug247564a_3() {
13744
	this.runNegativeTest(
13745
		new String[] {
13746
			"X.java",
13747
			"public class X {\n" +
13748
			"  Object o;\n" +
13749
			"  void foo() {\n" +
13750
			"  }\n" +
13751
			"  void foo1() {\n" + 
13752
			"	 o.toString();\n" +
13753
			"  }\n" +
13754
			"}\n"},
13755
		""
13756
	);
13757
}
13758
13759
// null analysis -- simple case for static final field
13760
public void testBug247564b() {
13761
	this.runNegativeTest(
13762
		new String[] {
13763
			"X.java",
13764
			"public class X {\n" +
13765
			"  static final Object o = null;\n" +
13766
			"  static final Object o1 = new Object();\n" +
13767
			"  void foo() {\n" +
13768
			"    if (o.toString() == \"\") {}\n" +
13769
			"    if (o == null) {}\n" +
13770
			"	 if (o != null) {}\n" +
13771
			"	 if (o1 == null) {}\n" +
13772
			"	 if (o1 != null) {}\n" +
13773
			"  }\n" +
13774
			"}\n"},
13775
		"----------\n" + 
13776
		"1. ERROR in X.java (at line 5)\n" + 
13777
		"	if (o.toString() == \"\") {}\n" + 
13778
		"	    ^\n" + 
13779
		"Null pointer access: The field o can only be null at this location\n" + 
13780
		"----------\n" + 
13781
		"2. ERROR in X.java (at line 6)\n" + 
13782
		"	if (o == null) {}\n" + 
13783
		"	    ^\n" + 
13784
		"Redundant null check: The field o can only be null at this location\n" + 
13785
		"----------\n" + 
13786
		"3. ERROR in X.java (at line 7)\n" + 
13787
		"	if (o != null) {}\n" + 
13788
		"	    ^\n" + 
13789
		"Null comparison always yields false: The field o can only be null at this location\n" + 
13790
		"----------\n" + 
13791
		"4. WARNING in X.java (at line 7)\n" + 
13792
		"	if (o != null) {}\n" + 
13793
		"	               ^^\n" + 
13794
		"Dead code\n" + 
13795
		"----------\n" + 
13796
		"5. ERROR in X.java (at line 8)\n" + 
13797
		"	if (o1 == null) {}\n" + 
13798
		"	    ^^\n" + 
13799
		"Null comparison always yields false: The field o1 cannot be null at this location\n" + 
13800
		"----------\n" + 
13801
		"6. WARNING in X.java (at line 8)\n" + 
13802
		"	if (o1 == null) {}\n" + 
13803
		"	                ^^\n" + 
13804
		"Dead code\n" + 
13805
		"----------\n" + 
13806
		"7. ERROR in X.java (at line 9)\n" + 
13807
		"	if (o1 != null) {}\n" + 
13808
		"	    ^^\n" + 
13809
		"Redundant null check: The field o1 cannot be null at this location\n" + 
13810
		"----------\n"
13811
	);
13812
}
13813
13814
// null analysis -- simple case for static final field
13815
public void testBug247564b_1() {
13816
	this.runNegativeTest(
13817
		new String[] {
13818
			"X.java",
13819
			"public class X {\n" +
13820
			"  static final Object o;\n" +
13821
			"  static final Object o1;\n" +
13822
			"  static {\n" +
13823
			"		o = null;\n" +
13824
			"		o1 = new Object();\n" +
13825
			"  }\n" +
13826
			"  void foo() {\n" +
13827
			"    if (o.toString() == \"\") {}\n" +
13828
			"    if (o == null) {}\n" +
13829
			"	 if (o != null) {}\n" +
13830
			"	 if (o1 == null) {}\n" +
13831
			"	 if (o1 != null) {}\n" +
13832
			"  }\n" +
13833
			"}\n"},
13834
		"----------\n" + 
13835
		"1. ERROR in X.java (at line 9)\n" + 
13836
		"	if (o.toString() == \"\") {}\n" + 
13837
		"	    ^\n" + 
13838
		"Null pointer access: The field o can only be null at this location\n" + 
13839
		"----------\n" + 
13840
		"2. ERROR in X.java (at line 10)\n" + 
13841
		"	if (o == null) {}\n" + 
13842
		"	    ^\n" + 
13843
		"Redundant null check: The field o can only be null at this location\n" + 
13844
		"----------\n" + 
13845
		"3. ERROR in X.java (at line 11)\n" + 
13846
		"	if (o != null) {}\n" + 
13847
		"	    ^\n" + 
13848
		"Null comparison always yields false: The field o can only be null at this location\n" + 
13849
		"----------\n" + 
13850
		"4. WARNING in X.java (at line 11)\n" + 
13851
		"	if (o != null) {}\n" + 
13852
		"	               ^^\n" + 
13853
		"Dead code\n" + 
13854
		"----------\n" + 
13855
		"5. ERROR in X.java (at line 12)\n" + 
13856
		"	if (o1 == null) {}\n" + 
13857
		"	    ^^\n" + 
13858
		"Null comparison always yields false: The field o1 cannot be null at this location\n" + 
13859
		"----------\n" + 
13860
		"6. WARNING in X.java (at line 12)\n" + 
13861
		"	if (o1 == null) {}\n" + 
13862
		"	                ^^\n" + 
13863
		"Dead code\n" + 
13864
		"----------\n" + 
13865
		"7. ERROR in X.java (at line 13)\n" + 
13866
		"	if (o1 != null) {}\n" + 
13867
		"	    ^^\n" + 
13868
		"Redundant null check: The field o1 cannot be null at this location\n" + 
13869
		"----------\n"
13870
	);
13871
}
13872
13873
// null analysis -- fields in synchronized methods
13874
// check that fields that are protected against concurrent access
13875
// behave as locals when no call to further methods can affect them
13876
public void testBug247564c() {
13877
	this.runNegativeTest(
13878
		new String[] {
13879
			"X.java",
13880
			"public class X {\n" +
13881
			"  Object o;\n" +
13882
			"  Object o1;\n" +
13883
			"  Object o2;\n" +
13884
			"  Object o3;\n" +
13885
			"  synchronized void foo() {\n" +
13886
			"		o = null;\n" +
13887
			"		if (o == null) {\n" +
13888
			"			o.toString();\n" +
13889
			"		}\n" +
13890
			"		o1 = new Object();\n" +
13891
			"		if (o1 == null) {\n" +
13892
			"			o1.toString();\n" +
13893
			"		}\n" +
13894
			"		o2 = null;\n" +
13895
			"		if (o2 != null) {\n" +
13896
			"		}\n" +
13897
			"		else {\n" +
13898
			"			o2.toString();\n" +
13899
			"		}\n" +
13900
			"		o3 = new Object();\n" +
13901
			"		if (o3 == null) {\n" +
13902
			"		}\n" +
13903
			"		else {\n" +
13904
			"			o3.toString();\n" +
13905
			"		}\n" +
13906
			"  }\n" +
13907
			"  void foo1() {\n" + 
13908
			"	 o.toString();\n" +
13909
			"  }\n" +
13910
			"}\n"},
13911
		"----------\n" + 
13912
		"1. ERROR in X.java (at line 8)\n" + 
13913
		"	if (o == null) {\n" + 
13914
		"	    ^\n" + 
13915
		"Redundant null check: The field o can only be null at this location\n" + 
13916
		"----------\n" + 
13917
		"2. ERROR in X.java (at line 9)\n" + 
13918
		"	o.toString();\n" + 
13919
		"	^\n" + 
13920
		"Null pointer access: The field o can only be null at this location\n" + 
13921
		"----------\n" + 
13922
		"3. ERROR in X.java (at line 12)\n" + 
13923
		"	if (o1 == null) {\n" + 
13924
		"	    ^^\n" + 
13925
		"Null comparison always yields false: The field o1 cannot be null at this location\n" + 
13926
		"----------\n" + 
13927
		"4. WARNING in X.java (at line 12)\n" + 
13928
		"	if (o1 == null) {\n" + 
13929
		"			o1.toString();\n" + 
13930
		"		}\n" + 
13931
		"	                ^^^^^^^^^^^^^^^^^^^^^^^\n" + 
13932
		"Dead code\n" + 
13933
		"----------\n" + 
13934
		"5. ERROR in X.java (at line 16)\n" + 
13935
		"	if (o2 != null) {\n" + 
13936
		"	    ^^\n" + 
13937
		"Null comparison always yields false: The field o2 can only be null at this location\n" + 
13938
		"----------\n" + 
13939
		"6. WARNING in X.java (at line 16)\n" + 
13940
		"	if (o2 != null) {\n" + 
13941
		"		}\n" + 
13942
		"	                ^^^^^\n" + 
13943
		"Dead code\n" + 
13944
		"----------\n" + 
13945
		"7. ERROR in X.java (at line 19)\n" + 
13946
		"	o2.toString();\n" + 
13947
		"	^^\n" + 
13948
		"Null pointer access: The field o2 can only be null at this location\n" + 
13949
		"----------\n" + 
13950
		"8. ERROR in X.java (at line 22)\n" + 
13951
		"	if (o3 == null) {\n" + 
13952
		"	    ^^\n" + 
13953
		"Null comparison always yields false: The field o3 cannot be null at this location\n" + 
13954
		"----------\n" + 
13955
		"9. WARNING in X.java (at line 22)\n" + 
13956
		"	if (o3 == null) {\n" + 
13957
		"		}\n" + 
13958
		"	                ^^^^^\n" + 
13959
		"Dead code\n" + 
13960
		"----------\n"
13961
	);
13962
}
13963
13964
// null analysis -- test redundant instanceof warning for static final field
13965
public void testBug247564d() {
13966
	this.runNegativeTest(
13967
		new String[] {
13968
			"X.java",
13969
			"public class X {\n" +
13970
			"  static final Object o = null;\n" +
13971
			"  static final Object o1 = new Object();\n" +
13972
			"  void foo() {\n" +
13973
			"    if (o instanceof String) {}\n" +
13974
			"    if (o1 instanceof String) {}\n" +
13975
			"  }\n" +
13976
			"}\n"},
13977
		"----------\n" + 
13978
		"1. ERROR in X.java (at line 5)\n" + 
13979
		"	if (o instanceof String) {}\n" + 
13980
		"	    ^\n" + 
13981
		"instanceof always yields false: The field o can only be null at this location\n" + 
13982
		"----------\n"
13983
	);
13984
}
13985
13986
// null analysis -- test redundant instanceof warning for fields in synchronised method
13987
public void testBug247564d_1() {
13988
	this.runNegativeTest(
13989
		new String[] {
13990
			"X.java",
13991
			"public class X {\n" +
13992
			"  Object o;\n" +
13993
			"  Object o1;\n" +
13994
			"  synchronized void foo() {\n" +
13995
			"    if (o == null && o instanceof String) {}\n" +
13996
			"	 o1 = null;\n" +
13997
			"    if (o1 instanceof String) {}\n" +
13998
			"  }\n" +
13999
			"  void foo1() {\n" +
14000
			"    if (o == null && o instanceof String) {}\n" +
14001
			"	 o1 = null;\n" +
14002
			"    if (o1 instanceof String) {}\n" +
14003
			"  }\n" +
14004
			"}\n"},
14005
		"----------\n" + 
14006
		"1. ERROR in X.java (at line 5)\n" + 
14007
		"	if (o == null && o instanceof String) {}\n" + 
14008
		"	                 ^\n" + 
14009
		"instanceof always yields false: The field o can only be null at this location\n" + 
14010
		"----------\n" + 
14011
		"2. ERROR in X.java (at line 7)\n" + 
14012
		"	if (o1 instanceof String) {}\n" + 
14013
		"	    ^^\n" + 
14014
		"instanceof always yields false: The field o1 can only be null at this location\n" + 
14015
		"----------\n"
14016
	);
14017
}
14018
14019
// null analysis -- test redundant instanceof warning for fields in synchronised method
14020
public void testBug247564e() {
14021
	this.runNegativeTest(
14022
		new String[] {
14023
			"X.java",
14024
			"public class X {\n" +
14025
			"  Object o;\n" +
14026
			"  synchronized void foo() {\n" +
14027
			"    if (o == null) { o = null;}\n" +
14028
			"  }\n" +
14029
			"  void foo1() {\n" +
14030
			"    if (o == null) { o = null;}\n" +
14031
			"  }\n" +
14032
			"}\n"},
14033
		"----------\n" + 
14034
		"1. ERROR in X.java (at line 4)\n" + 
14035
		"	if (o == null) { o = null;}\n" + 
14036
		"	                 ^\n" + 
14037
		"Redundant assignment: The field o can only be null at this location\n" + 
14038
		"----------\n"
14039
	);
14040
}
14041
14042
// null analysis -- test redundant instanceof warning for fields in synchronised method
14043
public void testBug247564e_1() {
14044
	this.runNegativeTest(
14045
		new String[] {
14046
			"X.java",
14047
			"public class X {\n" +
14048
			"  Object o;\n" +
14049
			"  synchronized void foo() {\n" +
14050
			"    o = null;" +
14051
			"    do {\n" +
14052
			"      if (o != null) return;\n" +
14053
			"      o = null;\n" +
14054
			"    } while (true);\n" +
14055
			"  }\n" +
14056
			"}"},
14057
		"----------\n" +
14058
		"1. ERROR in X.java (at line 5)\n" + 
14059
		"	if (o != null) return;\n" + 
14060
		"	    ^\n" + 
14061
		"Null comparison always yields false: The field o can only be null at this location\n" + 
14062
		"----------\n" + 
14063
		"2. ERROR in X.java (at line 6)\n" + 
14064
		"	o = null;\n" + 
14065
		"	^\n" + 
14066
		"Redundant assignment: The field o can only be null at this location\n" + 
14067
		"----------\n",
14068
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
14069
}
14070
13676
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 
14071
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 
13677
// Dead Code detection removing code that isn't dead
14072
// Dead Code detection removing code that isn't dead
13678
public void testBug332637() {
14073
public void testBug332637() {

Return to bug 247564