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 (+20 lines)
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 (-1 / +10 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 56-61 Link Here
56
		flowInfo.markNullStatus(local, nullStatus);
56
		flowInfo.markNullStatus(local, nullStatus);
57
		if (flowContext.initsOnFinally != null)
57
		if (flowContext.initsOnFinally != null)
58
			flowContext.initsOnFinally.markNullStatus(local, nullStatus);
58
			flowContext.initsOnFinally.markNullStatus(local, nullStatus);
59
		if (local instanceof FieldBinding && local.isFinal() && ((FieldBinding) local).isStatic()) {
60
			// static final field being assigned. Record its null status for future reference
61
			// since the flowInfo from a constructor or static block wont be available in a method
62
			FieldBinding fieldBinding = (FieldBinding) local;
63
			fieldBinding.setNullStatusForStaticFinalField(nullStatus);
64
		}
59
	}
65
	}
60
	return flowInfo;
66
	return flowInfo;
61
}
67
}
Lines 205-208 Link Here
205
public LocalVariableBinding localVariableBinding() {
211
public LocalVariableBinding localVariableBinding() {
206
	return this.lhs.localVariableBinding();
212
	return this.lhs.localVariableBinding();
207
}
213
}
214
public VariableBinding variableBinding() {
215
	return this.lhs.variableBinding();
216
}
208
}
217
}
(-)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 (-4 / +4 lines)
Lines 24-46 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
		switch (nullStatus) {
37
		switch (nullStatus) {
38
			case FlowInfo.NULL :
38
			case FlowInfo.NULL :
39
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
39
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
40
					flowContext.recordUsingNullReference(scope, local, reference,
40
					flowContext.recordUsingNullReference(scope, local, reference,
41
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo);
41
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo);
42
					initsWhenTrue.markAsComparedEqualToNull(local); // from thereon it is set
42
					initsWhenTrue.markAsComparedEqualToNull(local); // from thereon it is set
43
					initsWhenFalse.markAsComparedEqualToNonNull(local); // from thereon it is set
43
					initsWhenFalse.markAsComparedEqualToNonNull(local ); // from thereon it is set
44
				} else {
44
				} else {
45
					flowContext.recordUsingNullReference(scope, local, reference,
45
					flowContext.recordUsingNullReference(scope, local, reference,
46
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
46
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java (-3 / +12 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 506-519 Link Here
506
 * @param flowInfo the upstream flow info; caveat: may get modified
507
 * @param flowInfo the upstream flow info; caveat: may get modified
507
 */
508
 */
508
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
509
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
509
	LocalVariableBinding local = localVariableBinding();
510
	VariableBinding local = variableBinding();
510
	if (local != null &&
511
	if (local != null &&
511
			(local.type.tagBits & TagBits.IsBaseType) == 0) {
512
			(local.type.tagBits & TagBits.IsBaseType) == 0) {
512
		if ((this.bits & ASTNode.IsNonNull) == 0) {
513
		if ((this.bits & ASTNode.IsNonNull) == 0) {
513
			flowContext.recordUsingNullReference(scope, local, this,
514
			flowContext.recordUsingNullReference(scope, local, this,
514
					FlowContext.MAY_NULL, flowInfo);
515
					FlowContext.MAY_NULL, flowInfo);
515
		}
516
		}
516
		flowInfo.markAsComparedEqualToNonNull(local);
517
		flowInfo.markAsComparedEqualToNonNull(local );
517
			// from thereon it is set
518
			// from thereon it is set
518
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
519
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
519
			flowInfo.markedAsNullOrNonNullInAssertExpression(local);
520
			flowInfo.markedAsNullOrNonNullInAssertExpression(local);
Lines 849-855 Link Here
849
		this.constant != null && this.constant != Constant.NotAConstant)
850
		this.constant != null && this.constant != Constant.NotAConstant)
850
	return FlowInfo.NON_NULL; // constant expression cannot be null
851
	return FlowInfo.NON_NULL; // constant expression cannot be null
851
852
852
	LocalVariableBinding local = localVariableBinding();
853
	VariableBinding local = variableBinding();
853
	if (local != null)
854
	if (local != null)
854
		return flowInfo.nullStatus(local);
855
		return flowInfo.nullStatus(local);
855
	return FlowInfo.NON_NULL;
856
	return FlowInfo.NON_NULL;
Lines 1055-1058 Link Here
1055
public void traverse(ASTVisitor visitor, ClassScope scope) {
1056
public void traverse(ASTVisitor visitor, ClassScope scope) {
1056
	// nothing to do
1057
	// nothing to do
1057
}
1058
}
1059
1060
/**
1061
 * Returns the field or local variable referenced by this node. Can be a direct reference (SingleNameReference)
1062
 * or thru a cast expression etc...
1063
 */
1064
public VariableBinding variableBinding() {
1065
	return null;
1066
}
1058
}
1067
}
(-)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 (-1 / +16 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 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
	if (this.receiver.isThis() || this.binding.isStatic()) {
675
		if (this.receiver instanceof MessageSend) {
676
			if (((MessageSend) this.receiver).actualReceiverType == this.receiver.resolvedType) {
677
				return this.binding;
678
			}
679
		} else {
680
			return this.binding;
681
		}
682
	}
683
	return super.variableBinding();
684
}
685
671
}
686
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java (-5 / +5 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
		initsWhenTrue.markAsComparedEqualToNonNull(variable );
40
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
40
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
41
			initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local);
41
			initsWhenTrue.markedAsNullOrNonNullInAssertExpression(variable);
42
		}
42
		}
43
		flowContext.recordUsingNullReference(currentScope, local,
43
		flowContext.recordUsingNullReference(currentScope, variable,
44
				this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo);
44
				this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo);
45
		// no impact upon enclosing try context
45
		// no impact upon enclosing try context
46
		return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
46
		return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
(-)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/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/TypeDeclaration.java (-4 / +84 lines)
Lines 43-48 Link Here
43
	public MethodScope staticInitializerScope;
43
	public MethodScope staticInitializerScope;
44
	public boolean ignoreFurtherInvestigation = false;
44
	public boolean ignoreFurtherInvestigation = false;
45
	public int maxFieldCount;
45
	public int maxFieldCount;
46
	public int maxFieldCountForFlowInfo;	// cumulative count of fields in this type and enclosing types
46
	public int declarationSourceStart;
47
	public int declarationSourceStart;
47
	public int declarationSourceEnd;
48
	public int declarationSourceEnd;
48
	public int bodyStart;
49
	public int bodyStart;
Lines 198-204 Link Here
198
			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
199
			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
199
		}
200
		}
200
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
201
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
202
		
203
		ClassScope enclosingClass = currentScope.classScope();
204
		if (enclosingClass.referenceContext != null) {
205
			this.maxFieldCountForFlowInfo = enclosingClass.referenceContext.maxFieldCountForFlowInfo + this.maxFieldCount;
206
		} else {
207
			this.maxFieldCountForFlowInfo = this.maxFieldCount;
208
		}
201
		updateMaxFieldCount(); // propagate down the max field count
209
		updateMaxFieldCount(); // propagate down the max field count
210
		flowInfo.unconditionalInits().maxFieldCount = this.maxFieldCountForFlowInfo;
202
		internalAnalyseCode(flowContext, flowInfo);
211
		internalAnalyseCode(flowContext, flowInfo);
203
	} catch (AbortType e) {
212
	} catch (AbortType e) {
204
		this.ignoreFurtherInvestigation = true;
213
		this.ignoreFurtherInvestigation = true;
Lines 214-222 Link Here
214
	if (this.ignoreFurtherInvestigation)
223
	if (this.ignoreFurtherInvestigation)
215
		return;
224
		return;
216
	try {
225
	try {
226
		if (this.enclosingType == null) {
227
			this.maxFieldCountForFlowInfo = this.maxFieldCount;
228
		} else {
229
			this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount;
230
		}
217
		// propagate down the max field count
231
		// propagate down the max field count
218
		updateMaxFieldCount();
232
		updateMaxFieldCount();
219
		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount));
233
		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCountForFlowInfo));
220
	} catch (AbortType e) {
234
	} catch (AbortType e) {
221
		this.ignoreFurtherInvestigation = true;
235
		this.ignoreFurtherInvestigation = true;
222
	}
236
	}
Lines 236-242 Link Here
236
			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
250
			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
237
		}
251
		}
238
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
252
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
253
		
254
		if (this.enclosingType == null) {
255
			this.maxFieldCountForFlowInfo = this.maxFieldCount;
256
		} else {
257
			this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount;
258
		}
239
		updateMaxFieldCount(); // propagate down the max field count
259
		updateMaxFieldCount(); // propagate down the max field count
260
		flowInfo.unconditionalInits().maxFieldCount = this.maxFieldCountForFlowInfo;
240
		internalAnalyseCode(flowContext, flowInfo);
261
		internalAnalyseCode(flowContext, flowInfo);
241
	} catch (AbortType e) {
262
	} catch (AbortType e) {
242
		this.ignoreFurtherInvestigation = true;
263
		this.ignoreFurtherInvestigation = true;
Lines 251-257 Link Here
251
	if (this.ignoreFurtherInvestigation)
272
	if (this.ignoreFurtherInvestigation)
252
		return;
273
		return;
253
	try {
274
	try {
254
		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount));
275
		if (this.enclosingType == null) {
276
			this.maxFieldCountForFlowInfo = this.maxFieldCount;
277
		} else {
278
			this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount;
279
		}
280
		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCountForFlowInfo));
255
	} catch (AbortType e) {
281
	} catch (AbortType e) {
256
		this.ignoreFurtherInvestigation = true;
282
		this.ignoreFurtherInvestigation = true;
257
	}
283
	}
Lines 646-652 Link Here
646
				// branch, since the previous initializer already got the blame.
672
				// branch, since the previous initializer already got the blame.
647
				if (staticFieldInfo == FlowInfo.DEAD_END) {
673
				if (staticFieldInfo == FlowInfo.DEAD_END) {
648
					this.staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
674
					this.staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
649
					staticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
675
					staticFieldInfo = FlowInfo.initial(this.maxFieldCountForFlowInfo).setReachMode(FlowInfo.UNREACHABLE);
650
				}
676
				}
651
			} else {
677
			} else {
652
				if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
678
				if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
Lines 662-668 Link Here
662
				// branch, since the previous initializer already got the blame.
688
				// branch, since the previous initializer already got the blame.
663
				if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
689
				if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
664
					this.initializerScope.problemReporter().initializerMustCompleteNormally(field);
690
					this.initializerScope.problemReporter().initializerMustCompleteNormally(field);
665
					nonStaticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
691
					nonStaticFieldInfo = FlowInfo.initial(this.maxFieldCountForFlowInfo).setReachMode(FlowInfo.UNREACHABLE);
666
				}
692
				}
667
			}
693
			}
668
		}
694
		}
Lines 1087-1092 Link Here
1087
		if (this.maxFieldCount < localMaxFieldCount) {
1113
		if (this.maxFieldCount < localMaxFieldCount) {
1088
			this.maxFieldCount = localMaxFieldCount;
1114
			this.maxFieldCount = localMaxFieldCount;
1089
		}
1115
		}
1116
//		if (this.memberTypes != null) {
1117
//			for (int i = 0, count = this.memberTypes.length; i < count; i++) {
1118
//				this.memberTypes[i].maxFieldCount += this.maxFieldCount;
1119
//			}
1120
//		}
1121
        // field count from supertypes should be included in maxFieldCount,
1122
		// so that a field from supertype doesn't end up with same id as a local variable
1123
		// in a method being analyzed.
1124
		ReferenceBinding superClassBinding = sourceType.superclass;
1125
		while (superClassBinding != null) {
1126
			FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields();
1127
			if (unResolvedFields != null) {
1128
				this.maxFieldCount += unResolvedFields.length;
1129
			}
1130
			superClassBinding = superClassBinding.superclass();
1131
		}
1132
		ReferenceBinding[] superInterfacesBinding = this.binding.superInterfaces;
1133
		this.maxFieldCount += findFieldCountFromSuperInterfaces(superInterfacesBinding);
1134
//		if (this.enclosingType != null)
1135
//			this.maxFieldCount += this.enclosingType.maxFieldCount;
1136
		
1090
		if (needSerialVersion) {
1137
		if (needSerialVersion) {
1091
			//check that the current type doesn't extend javax.rmi.CORBA.Stub
1138
			//check that the current type doesn't extend javax.rmi.CORBA.Stub
1092
			TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4);
1139
			TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4);
Lines 1173-1178 Link Here
1173
	}
1220
	}
1174
}
1221
}
1175
1222
1223
private int findFieldCountFromSuperInterfaces(ReferenceBinding[] superinterfaces) {
1224
	int numOfFields = 0;
1225
	if (superinterfaces == null)
1226
		return numOfFields ;
1227
	for (int i = 0; i < superinterfaces.length; i++) {
1228
		numOfFields += superinterfaces[i].fieldCount();
1229
		numOfFields += findFieldCountFromSuperInterfaces(superinterfaces[i].superInterfaces());		
1230
	}
1231
	return numOfFields;
1232
}
1233
1176
/**
1234
/**
1177
 * Resolve a local type declaration
1235
 * Resolve a local type declaration
1178
 */
1236
 */
Lines 1449-1456 Link Here
1449
	} else {
1507
	} else {
1450
		this.maxFieldCount = outerMostType.maxFieldCount; // down
1508
		this.maxFieldCount = outerMostType.maxFieldCount; // down
1451
	}
1509
	}
1510
	
1452
}
1511
}
1453
1512
1513
//int getMaxFieldCountForFlowInfo() {
1514
//	int maxFieldCountForFlowInfo = 0;
1515
//	if (this.binding == null)
1516
//		return maxFieldCountForFlowInfo; // error scenario
1517
//	ReferenceBinding superClassBinding = this.binding.superclass;
1518
//	while (superClassBinding != null) {
1519
//		FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields();
1520
//		if (unResolvedFields != null) {
1521
//			this.maxFieldCount += unResolvedFields.length;
1522
//		}
1523
//		superClassBinding = superClassBinding.superclass();
1524
//	}
1525
//	ReferenceBinding[] superInterfacesBinding = this.binding.superInterfaces;
1526
//	maxFieldCountForFlowInfo += findFieldCountFromSuperInterfaces(superInterfacesBinding);
1527
//	if (this.enclosingType != null) {
1528
//		maxFieldCountForFlowInfo += this.enclosingType.maxFieldCount;
1529
//	}
1530
//	return maxFieldCountForFlowInfo;
1531
//	
1532
//}
1533
1454
/**
1534
/**
1455
 * Returns whether the type is a secondary one or not.
1535
 * Returns whether the type is a secondary one or not.
1456
 */
1536
 */
(-)compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java (-19 / +25 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-146 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) {
139
	this.initsWhenTrue.markAsComparedEqualToNonNull(local);
140
	this.initsWhenTrue.markAsComparedEqualToNonNull(local);
140
	this.initsWhenFalse.markAsComparedEqualToNonNull(local);
141
	this.initsWhenFalse.markAsComparedEqualToNonNull(local);
141
}
142
}
142
143
143
public void markAsComparedEqualToNull(LocalVariableBinding local) {
144
public void markAsComparedEqualToNull(VariableBinding local) {
144
	this.initsWhenTrue.markAsComparedEqualToNull(local);
145
	this.initsWhenTrue.markAsComparedEqualToNull(local);
145
    this.initsWhenFalse.markAsComparedEqualToNull(local);
146
    this.initsWhenFalse.markAsComparedEqualToNull(local);
146
}
147
}
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) {
159
	this.initsWhenTrue.markAsDefinitelyNonNull(local);
160
	this.initsWhenTrue.markAsDefinitelyNonNull(local);
160
	this.initsWhenFalse.markAsDefinitelyNonNull(local);
161
	this.initsWhenFalse.markAsDefinitelyNonNull(local);
161
}
162
}
162
163
163
public void markAsDefinitelyNull(LocalVariableBinding local) {
164
public void markAsDefinitelyNull(VariableBinding local) {
164
	this.initsWhenTrue.markAsDefinitelyNull(local);
165
	this.initsWhenTrue.markAsDefinitelyNull(local);
165
	this.initsWhenFalse.markAsDefinitelyNull(local);
166
	this.initsWhenFalse.markAsDefinitelyNull(local);
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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableNullReference(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().variableRedundantCheckOnNull(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().variableNullReference(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().variableNullComparedToNonNull(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().variableRedundantNullAssignment(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().variableNullInstanceof(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().variablePotentialNullReference(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().variablePotentialNullReference(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().variableNullReference(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().variablePotentialNullReference(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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableNullReference(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().variableRedundantCheckOnNull(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().variableNullReference(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().variableNullComparedToNonNull(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().variableRedundantNullAssignment(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().variableNullInstanceof(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().variablePotentialNullReference(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().variablePotentialNullReference(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().variableNullReference(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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableNullReference(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().variableRedundantCheckOnNull(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().variableNullReference(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().variableNullComparedToNonNull(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().variableRedundantNullAssignment(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().variableNullInstanceof(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().variablePotentialNullReference(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().variablePotentialNullReference(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().variableNullReference(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().variablePotentialNullReference(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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableNullReference(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().variableRedundantCheckOnNull(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().variableNullReference(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().variableNullComparedToNonNull(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().variableRedundantNullAssignment(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().variableNullInstanceof(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().variablePotentialNullReference(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().variablePotentialNullReference(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().variableNullReference(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().variablePotentialNullReference(local, reference);
660
				return;
659
				return;
661
			}
660
			}
662
			break;
661
			break;
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java (-91 / +103 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
239
 */
247
 */
240
abstract public void markAsComparedEqualToNonNull(LocalVariableBinding local);
248
abstract public void markAsComparedEqualToNonNull(VariableBinding binding);
241
249
242
/**
250
/**
243
 * Record that a local variable got checked to be null.
251
 * Record that a field or local variable got checked to be null.
244
 * @param local the checked local variable
252
 * @param binding the checked field or local variable
245
 */
253
 */
246
abstract public void markAsComparedEqualToNull(LocalVariableBinding local);
254
abstract public void markAsComparedEqualToNull(VariableBinding binding);
247
255
248
	/**
256
	/**
249
	 * Record a field got definitely assigned.
257
	 * Record a field got definitely assigned.
Lines 251-284 Link Here
251
	abstract public void markAsDefinitelyAssigned(FieldBinding field);
259
	abstract public void markAsDefinitelyAssigned(FieldBinding field);
252
260
253
	/**
261
	/**
254
	 * Record a local got definitely assigned to a non-null value.
262
	 * Record a field or local got definitely assigned to a non-null value.
255
	 */
263
	 */
256
	abstract public void markAsDefinitelyNonNull(LocalVariableBinding local);
264
	abstract public void markAsDefinitelyNonNull(VariableBinding binding);
257
265
258
	/**
266
	/**
259
	 * Record a local got definitely assigned to null.
267
	 * Record a field or local got definitely assigned to null.
260
	 */
268
	 */
261
	abstract public void markAsDefinitelyNull(LocalVariableBinding local);
269
	abstract public void markAsDefinitelyNull(VariableBinding binding);
262
270
263
	/**
271
	/**
264
	 * Reset all null-information about a given local.
272
	 * Reset all null-information about a given field or local.
265
	 */
273
	 */
266
	abstract public void resetNullInfo(LocalVariableBinding local);
274
	abstract public void resetNullInfo(VariableBinding binding);
267
275
268
	/**
276
	/**
269
	 * Record a local may have got assigned to unknown (set the bit on existing info).
277
	 *  variant of {@link #resetNullInfo(VariableBinding)} for resetting null info for all fields
270
	 */
278
	 */
271
	abstract public void markPotentiallyUnknownBit(LocalVariableBinding local);
279
	abstract public void resetNullInfoForFields();
280
	/**
281
	 * Record a field or local may have got assigned to unknown (set the bit on existing info).
282
	 */
283
	abstract public void markPotentiallyUnknownBit(VariableBinding binding);
272
284
273
	/**
285
	/**
274
	 * Record a local may have got assigned to null (set the bit on existing info).
286
	 * Record a field or local may have got assigned to null (set the bit on existing info).
275
	 */
287
	 */
276
	abstract public void markPotentiallyNullBit(LocalVariableBinding local);
288
	abstract public void markPotentiallyNullBit(VariableBinding binding);
277
289
278
	/**
290
	/**
279
	 * Record a local may have got assigned to non-null (set the bit on existing info).
291
	 * Record a field or local may have got assigned to non-null (set the bit on existing info).
280
	 */
292
	 */
281
	abstract public void markPotentiallyNonNullBit(LocalVariableBinding local);
293
	abstract public void markPotentiallyNonNullBit(VariableBinding binding);
282
294
283
	/**
295
	/**
284
	 * Record a local got definitely assigned.
296
	 * Record a local got definitely assigned.
Lines 286-344 Link Here
286
	abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
298
	abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
287
299
288
/**
300
/**
289
 * Record a local got definitely assigned to an unknown value.
301
 * Record a field or local got definitely assigned to an unknown value.
290
 */
302
 */
291
abstract public void markAsDefinitelyUnknown(LocalVariableBinding local);
303
abstract public void markAsDefinitelyUnknown(VariableBinding binding);
292
304
293
/**
305
/**
294
 * Mark the null status of the given local according to the given status
306
 * Mark the null status of the given field or local according to the given status
295
 * @param local
307
 * @param binding
296
 * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
308
 * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
297
 */
309
 */
298
public void markNullStatus(LocalVariableBinding local, int nullStatus) {
310
public void markNullStatus(VariableBinding binding, int nullStatus) {
299
	switch(nullStatus) {
311
	switch(nullStatus) {
300
		// definite status?
312
		// definite status?
301
		case FlowInfo.UNKNOWN :
313
		case FlowInfo.UNKNOWN :
302
			markAsDefinitelyUnknown(local);
314
			markAsDefinitelyUnknown(binding);
303
			break;
315
			break;
304
		case FlowInfo.NULL :
316
		case FlowInfo.NULL :
305
			markAsDefinitelyNull(local);
317
			markAsDefinitelyNull(binding);
306
			break;
318
			break;
307
		case FlowInfo.NON_NULL :
319
		case FlowInfo.NON_NULL :
308
			markAsDefinitelyNonNull(local);
320
			markAsDefinitelyNonNull(binding);
309
			break;
321
			break;
310
		default:
322
		default:
311
			// collect potential status:
323
			// collect potential status:
312
			resetNullInfo(local);
324
			resetNullInfo(binding);
313
			if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0)
325
			if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0)
314
				markPotentiallyUnknownBit(local);
326
				markPotentiallyUnknownBit(binding);
315
			if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
327
			if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
316
				markPotentiallyNullBit(local);
328
				markPotentiallyNullBit(binding);
317
			if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0)
329
			if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0)
318
				markPotentiallyNonNullBit(local);
330
				markPotentiallyNonNullBit(binding);
319
			if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0)
331
			if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0)
320
				markAsDefinitelyUnknown(local);
332
				markAsDefinitelyUnknown(binding);
321
	}
333
	}
322
}
334
}
323
335
324
/**
336
/**
325
 * Answer the null status of the given local
337
 * Answer the null status of the given field or local
326
 * @param local
338
 * @param binding
327
 * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
339
 * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
328
 */
340
 */
329
public int nullStatus(LocalVariableBinding local) {
341
public int nullStatus(VariableBinding binding) {
330
	if (isDefinitelyUnknown(local))
342
	if (isDefinitelyUnknown(binding))
331
		return FlowInfo.UNKNOWN;
343
		return FlowInfo.UNKNOWN;
332
	if (isDefinitelyNull(local))
344
	if (isDefinitelyNull(binding))
333
		return FlowInfo.NULL;
345
		return FlowInfo.NULL;
334
	if (isDefinitelyNonNull(local))
346
	if (isDefinitelyNonNull(binding))
335
		return FlowInfo.NON_NULL;
347
		return FlowInfo.NON_NULL;
336
	int status = 0;
348
	int status = 0;
337
	if (isPotentiallyUnknown(local))
349
	if (isPotentiallyUnknown(binding))
338
		status |= FlowInfo.POTENTIALLY_UNKNOWN;
350
		status |= FlowInfo.POTENTIALLY_UNKNOWN;
339
	if (isPotentiallyNull(local))
351
	if (isPotentiallyNull(binding))
340
		status |= FlowInfo.POTENTIALLY_NULL;
352
		status |= FlowInfo.POTENTIALLY_NULL;
341
	if (isPotentiallyNonNull(local))
353
	if (isPotentiallyNonNull(binding))
342
		status |= FlowInfo.POTENTIALLY_NON_NULL;
354
		status |= FlowInfo.POTENTIALLY_NON_NULL;
343
	if (status > 0)
355
	if (status > 0)
344
		return status;
356
		return status;
Lines 555-566 Link Here
555
 * where this variable is being checked against null
567
 * where this variable is being checked against null
556
 */
568
 */
557
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
569
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
558
abstract public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local);
570
abstract public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding);
559
571
560
/** 
572
/** 
561
 * Returns true if the local variable being checked for was marked as null or not null
573
 * 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.
574
 * inside an assert expression due to comparison against null.
563
 */
575
 */
564
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
576
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
565
abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local);
577
abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding);
566
}
578
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (-52 / +52 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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableRedundantCheckOnNull(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().variableNullComparedToNonNull(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().variableNullReference(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().variableRedundantCheckOnNull(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().variableNullReference(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().variableNullComparedToNonNull(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().variableRedundantNullAssignment(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().variableNullInstanceof(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().variablePotentialNullReference(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().variablePotentialNullReference(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().variableNullReference(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().variableRedundantCheckOnNonNull(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().variableNonNullComparedToNull(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().variableNullReference(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().variableRedundantCheckOnNull(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().variableNullReference(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().variableNullComparedToNonNull(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
								scope.problemReporter().variableRedundantNullAssignment(local, expression);
305
								continue;
305
								continue;
306
							case FlowContext.IN_INSTANCEOF:
306
							case FlowContext.IN_INSTANCEOF:
307
								scope.problemReporter().localVariableNullInstanceof(local, expression);
307
								scope.problemReporter().variableNullInstanceof(local, expression);
308
								continue;
308
								continue;
309
						}
309
						}
310
					} else if (flowInfo.isPotentiallyNull(local)) {
310
					} else if (flowInfo.isPotentiallyNull(local)) {
Lines 312-325 Link Here
312
							case FlowContext.IN_COMPARISON_NULL:
312
							case FlowContext.IN_COMPARISON_NULL:
313
								this.nullReferences[i] = null;
313
								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
314
								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);
315
									scope.problemReporter().variablePotentialNullReference(local, expression);
316
									continue;
316
									continue;
317
								}
317
								}
318
								break;
318
								break;
319
							case FlowContext.IN_COMPARISON_NON_NULL:
319
							case FlowContext.IN_COMPARISON_NON_NULL:
320
								this.nullReferences[i] = null;
320
								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
321
								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);
322
									scope.problemReporter().variablePotentialNullReference(local, expression);
323
									continue;
323
									continue;
324
								}
324
								}
325
								break;
325
								break;
Lines 329-340 Link Here
329
				case MAY_NULL:
329
				case MAY_NULL:
330
					if (flowInfo.isDefinitelyNull(local)) {
330
					if (flowInfo.isDefinitelyNull(local)) {
331
						this.nullReferences[i] = null;
331
						this.nullReferences[i] = null;
332
						scope.problemReporter().localVariableNullReference(local, expression);
332
						scope.problemReporter().variableNullReference(local, expression);
333
						continue;
333
						continue;
334
					}
334
					}
335
					if (flowInfo.isPotentiallyNull(local)) {
335
					if (flowInfo.isPotentiallyNull(local)) {
336
						this.nullReferences[i] = null;
336
						this.nullReferences[i] = null;
337
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
337
						scope.problemReporter().variablePotentialNullReference(local, expression);
338
						continue;
338
						continue;
339
					}
339
					}
340
					break;
340
					break;
Lines 458-484 Link Here
458
		return true;
458
		return true;
459
	}
459
	}
460
460
461
protected void recordNullReference(LocalVariableBinding local,
461
protected void recordNullReference(VariableBinding local,
462
	Expression expression, int status) {
462
	Expression expression, int status) {
463
	if (this.nullCount == 0) {
463
	if (this.nullCount == 0) {
464
		this.nullLocals = new LocalVariableBinding[5];
464
		this.nullVariables = new VariableBinding[5];
465
		this.nullReferences = new Expression[5];
465
		this.nullReferences = new Expression[5];
466
		this.nullCheckTypes = new int[5];
466
		this.nullCheckTypes = new int[5];
467
	}
467
	}
468
	else if (this.nullCount == this.nullLocals.length) {
468
	else if (this.nullCount == this.nullVariables.length) {
469
		System.arraycopy(this.nullLocals, 0,
469
		System.arraycopy(this.nullVariables, 0,
470
			this.nullLocals = new LocalVariableBinding[this.nullCount * 2], 0, this.nullCount);
470
			this.nullVariables = new VariableBinding[this.nullCount * 2], 0, this.nullCount);
471
		System.arraycopy(this.nullReferences, 0,
471
		System.arraycopy(this.nullReferences, 0,
472
			this.nullReferences = new Expression[this.nullCount * 2], 0, this.nullCount);
472
			this.nullReferences = new Expression[this.nullCount * 2], 0, this.nullCount);
473
		System.arraycopy(this.nullCheckTypes, 0,
473
		System.arraycopy(this.nullCheckTypes, 0,
474
			this.nullCheckTypes = new int[this.nullCount * 2], 0, this.nullCount);
474
			this.nullCheckTypes = new int[this.nullCount * 2], 0, this.nullCount);
475
	}
475
	}
476
	this.nullLocals[this.nullCount] = local;
476
	this.nullVariables[this.nullCount] = local;
477
	this.nullReferences[this.nullCount] = expression;
477
	this.nullReferences[this.nullCount] = expression;
478
	this.nullCheckTypes[this.nullCount++] = status;
478
	this.nullCheckTypes[this.nullCount++] = status;
479
}
479
}
480
480
481
public void recordUsingNullReference(Scope scope, LocalVariableBinding local,
481
public void recordUsingNullReference(Scope scope, VariableBinding local,
482
		Expression reference, int checkType, FlowInfo flowInfo) {
482
		Expression reference, int checkType, FlowInfo flowInfo) {
483
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 ||
483
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 ||
484
			flowInfo.isDefinitelyUnknown(local)) {
484
			flowInfo.isDefinitelyUnknown(local)) {
Lines 490-503 Link Here
490
			if (flowInfo.isDefinitelyNonNull(local)) {
490
			if (flowInfo.isDefinitelyNonNull(local)) {
491
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
491
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
492
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
492
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
493
						scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
493
						scope.problemReporter().variableRedundantCheckOnNonNull(local, reference);
494
					}
494
					}
495
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
495
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
496
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
496
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
497
					}
497
					}
498
				} else {
498
				} else {
499
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
499
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
500
						scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
500
						scope.problemReporter().variableNonNullComparedToNull(local, reference);
501
					}
501
					}
502
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
502
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
503
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
503
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
Lines 506-526 Link Here
506
			} else if (flowInfo.isDefinitelyNull(local)) {
506
			} else if (flowInfo.isDefinitelyNull(local)) {
507
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
507
				if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) {
508
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
508
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
509
						scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
509
						scope.problemReporter().variableRedundantCheckOnNull(local, reference);
510
					}
510
					}
511
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
511
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
512
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
512
						flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
513
					}
513
					}
514
				} else {
514
				} else {
515
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
515
					if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
516
						scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
516
						scope.problemReporter().variableNullComparedToNonNull(local, reference);
517
					}
517
					}
518
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
518
					if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
519
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
519
						flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
520
					}
520
					}
521
				}
521
				}
522
			} else if (this.upstreamNullFlowInfo.isDefinitelyNonNull(local) && !flowInfo.isPotentiallyNull(local)) {    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291418
522
			} else if (this.upstreamNullFlowInfo.isDefinitelyNonNull(local) && !flowInfo.isPotentiallyNull(local)) {    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291418
523
				flowInfo.markAsDefinitelyNonNull(local);
523
				flowInfo.markAsDefinitelyNonNull(local );
524
				if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
524
				if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
525
					recordNullReference(local, reference, checkType);
525
					recordNullReference(local, reference, checkType);
526
				}
526
				}
Lines 546-556 Link Here
546
				switch(checkType & CONTEXT_MASK) {
546
				switch(checkType & CONTEXT_MASK) {
547
					case FlowContext.IN_COMPARISON_NULL:
547
					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
548
						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);
549
							scope.problemReporter().variableNullReference(local, reference);
550
							return;
550
							return;
551
						}
551
						}
552
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
552
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
553
							scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
553
							scope.problemReporter().variableRedundantCheckOnNull(local, reference);
554
						}
554
						}
555
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
555
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
556
							flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
556
							flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE);
Lines 558-591 Link Here
558
						return;
558
						return;
559
					case FlowContext.IN_COMPARISON_NON_NULL:
559
					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
560
						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);
561
							scope.problemReporter().variableNullReference(local, reference);
562
							return;
562
							return;
563
						}
563
						}
564
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
564
						if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) {
565
							scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
565
							scope.problemReporter().variableNullComparedToNonNull(local, reference);
566
						}
566
						}
567
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
567
						if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) {
568
							flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
568
							flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE);
569
						}
569
						}
570
						return;
570
						return;
571
					case FlowContext.IN_ASSIGNMENT:
571
					case FlowContext.IN_ASSIGNMENT:
572
						scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
572
						scope.problemReporter().variableRedundantNullAssignment(local, reference);
573
						return;
573
						return;
574
					case FlowContext.IN_INSTANCEOF:
574
					case FlowContext.IN_INSTANCEOF:
575
						scope.problemReporter().localVariableNullInstanceof(local, reference);
575
						scope.problemReporter().variableNullInstanceof(local, reference);
576
						return;
576
						return;
577
				}
577
				}
578
			} else if (flowInfo.isPotentiallyNull(local)) {
578
			} else if (flowInfo.isPotentiallyNull(local)) {
579
				switch(checkType & CONTEXT_MASK) {
579
				switch(checkType & CONTEXT_MASK) {
580
					case FlowContext.IN_COMPARISON_NULL:
580
					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
581
						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);
582
							scope.problemReporter().variablePotentialNullReference(local, reference);
583
							return;
583
							return;
584
						}
584
						}
585
						break;
585
						break;
586
					case FlowContext.IN_COMPARISON_NON_NULL:
586
					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
587
						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);
588
							scope.problemReporter().variablePotentialNullReference(local, reference);
589
							return;
589
							return;
590
						}
590
						}
591
						break;
591
						break;
Lines 604-614 Link Here
604
				return;
604
				return;
605
			}
605
			}
606
			if (flowInfo.isDefinitelyNull(local)) {
606
			if (flowInfo.isDefinitelyNull(local)) {
607
				scope.problemReporter().localVariableNullReference(local, reference);
607
				scope.problemReporter().variableNullReference(local, reference);
608
				return;
608
				return;
609
			}
609
			}
610
			if (flowInfo.isPotentiallyNull(local)) {
610
			if (flowInfo.isPotentiallyNull(local)) {
611
				scope.problemReporter().localVariablePotentialNullReference(local, reference);
611
				scope.problemReporter().variablePotentialNullReference(local, reference);
612
				return;
612
				return;
613
			}
613
			}
614
			recordNullReference(local, reference, checkType);
614
			recordNullReference(local, reference, checkType);
(-)compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java (-12 / +33 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 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) {
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
			position = local.id;
127
		} else {
128
			position = local.id + this.maxFieldCount;
129
		}
124
    	// position is zero-based
130
    	// position is zero-based
125
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
131
    	if (position < BitCacheSize) { // use bits
126
    		// set protected non null
132
    		// set protected non null
127
    		this.nullBit1 |= (1L << position);
133
    		this.nullBit1 |= (1L << position);
128
    		if (COVERAGE_TEST_FLAG) {
134
    		if (COVERAGE_TEST_FLAG) {
Lines 161-173 Link Here
161
	}
167
	}
162
}
168
}
163
169
164
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
170
public void markAsDefinitelyNonNull(VariableBinding local) {
165
	// protected from non-object locals in calling methods
171
	// protected from non-object locals in calling methods
166
	if (this != DEAD_END) {
172
	if (this != DEAD_END) {
167
    	this.tagBits |= NULL_FLAG_MASK;
173
    	this.tagBits |= NULL_FLAG_MASK;
168
    	int position;
174
    	int position;
169
    	// position is zero-based
175
    	// position is zero-based
170
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
176
    	if (local instanceof FieldBinding) {
177
    		position = local.id;
178
    	} else {
179
    		position = local.id + this.maxFieldCount;
180
    	}
181
    	if (position < BitCacheSize) { // use bits
171
    		// set assigned non null
182
    		// set assigned non null
172
    		this.nullBit3 |= (1L << position);
183
    		this.nullBit3 |= (1L << position);
173
    		if (COVERAGE_TEST_FLAG) {
184
    		if (COVERAGE_TEST_FLAG) {
Lines 207-219 Link Here
207
}
218
}
208
// PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either
219
// PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either
209
// PREMATURE project protected non null onto something else
220
// PREMATURE project protected non null onto something else
210
public void markAsDefinitelyNull(LocalVariableBinding local) {
221
public void markAsDefinitelyNull(VariableBinding local) {
211
	// protected from non-object locals in calling methods
222
	// protected from non-object locals in calling methods
212
	if (this != DEAD_END) {
223
	if (this != DEAD_END) {
213
    	this.tagBits |= NULL_FLAG_MASK;
224
    	this.tagBits |= NULL_FLAG_MASK;
214
    	int position;
225
    	int position;
226
    	if (local instanceof FieldBinding) {
227
    		position = local.id;
228
    	} else {
229
    		position = local.id + this.maxFieldCount;
230
    	}
215
    	// position is zero-based
231
    	// position is zero-based
216
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
232
    	if (position < BitCacheSize) { // use bits
217
    		// set assigned null
233
    		// set assigned null
218
    		this.nullBit2 |= (1L << position);
234
    		this.nullBit2 |= (1L << position);
219
    		if (COVERAGE_TEST_FLAG) {
235
    		if (COVERAGE_TEST_FLAG) {
Lines 252-264 Link Here
252
	}
268
	}
253
}
269
}
254
270
255
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
271
public void markAsDefinitelyUnknown(VariableBinding local) {
256
	// protected from non-object locals in calling methods
272
	// protected from non-object locals in calling methods
257
	if (this != DEAD_END) {
273
	if (this != DEAD_END) {
258
    	this.tagBits |= NULL_FLAG_MASK;
274
    	this.tagBits |= NULL_FLAG_MASK;
259
    	int position;
275
    	int position;
276
    	if (local instanceof FieldBinding) {
277
    		position = local.id;
278
    	} else {
279
    		position = local.id + this.maxFieldCount;
280
    	}
260
    	// position is zero-based
281
    	// position is zero-based
261
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
282
    	if (position < BitCacheSize) { // use bits
262
    		// set assigned unknown
283
    		// set assigned unknown
263
    		this.nullBit4 |= (1L << position);
284
    		this.nullBit4 |= (1L << position);
264
    		if (COVERAGE_TEST_FLAG) {
285
    		if (COVERAGE_TEST_FLAG) {
Lines 407-413 Link Here
407
 * Mark a local as potentially having been assigned to an unknown value.
428
 * Mark a local as potentially having been assigned to an unknown value.
408
 * @param local the local to mark
429
 * @param local the local to mark
409
 */
430
 */
410
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
431
public void markPotentiallyUnknownBit(VariableBinding local) {
411
	// protected from non-object locals in calling methods
432
	// protected from non-object locals in calling methods
412
	if (this != DEAD_END) {
433
	if (this != DEAD_END) {
413
		this.tagBits |= NULL_FLAG_MASK;
434
		this.tagBits |= NULL_FLAG_MASK;
Lines 454-460 Link Here
454
	}
475
	}
455
}
476
}
456
477
457
public void markPotentiallyNullBit(LocalVariableBinding local) {
478
public void markPotentiallyNullBit(VariableBinding local) {
458
	if (this != DEAD_END) {
479
	if (this != DEAD_END) {
459
		this.tagBits |= NULL_FLAG_MASK;
480
		this.tagBits |= NULL_FLAG_MASK;
460
        int position;
481
        int position;
Lines 500-506 Link Here
500
	}
521
	}
501
}
522
}
502
523
503
public void markPotentiallyNonNullBit(LocalVariableBinding local) {
524
public void markPotentiallyNonNullBit(VariableBinding local) {
504
	if (this != DEAD_END) {
525
	if (this != DEAD_END) {
505
		this.tagBits |= NULL_FLAG_MASK;
526
		this.tagBits |= NULL_FLAG_MASK;
506
        int position;
527
        int position;
(-)compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java (-51 / +271 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 515-527 Link Here
515
	return this;
516
	return this;
516
}
517
}
517
518
518
final public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) {
519
final public boolean cannotBeDefinitelyNullOrNonNull(VariableBinding local) {
519
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
520
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
520
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
521
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
521
		return false;
522
		return false;
522
	}
523
	}
523
	int position;
524
	int position;
524
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
525
	if (local instanceof FieldBinding) {
526
		position = local.id;
527
	} else {
528
		position = local.id + this.maxFieldCount;
529
	}
530
	if (position < BitCacheSize) {
525
		// use bits
531
		// use bits
526
		return (
532
		return (
527
			(~this.nullBit1
533
			(~this.nullBit1
Lines 546-558 Link Here
546
		    & (1L << (position % BitCacheSize))) != 0;
552
		    & (1L << (position % BitCacheSize))) != 0;
547
}
553
}
548
554
549
final public boolean cannotBeNull(LocalVariableBinding local) {
555
final public boolean cannotBeNull(VariableBinding local) {
550
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
556
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
551
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
557
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
552
		return false;
558
		return false;
553
	}
559
	}
554
	int position;
560
	int position;
555
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
561
	if (local instanceof FieldBinding) {
562
		position = local.id;
563
	} else {
564
		position = local.id + this.maxFieldCount;
565
	}
566
	if (position < BitCacheSize) {
556
		// use bits
567
		// use bits
557
		return (this.nullBit1 & this.nullBit3
568
		return (this.nullBit1 & this.nullBit3
558
			& ((this.nullBit2 & this.nullBit4) | ~this.nullBit2)
569
			& ((this.nullBit2 & this.nullBit4) | ~this.nullBit2)
Lines 573-585 Link Here
573
		    & (1L << (position % BitCacheSize))) != 0;
584
		    & (1L << (position % BitCacheSize))) != 0;
574
}
585
}
575
586
576
final public boolean canOnlyBeNull(LocalVariableBinding local) {
587
final public boolean canOnlyBeNull(VariableBinding local) {
577
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
588
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
578
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
589
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
579
		return false;
590
		return false;
580
	}
591
	}
581
	int position;
592
	int position;
582
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
593
	if (local instanceof FieldBinding) {
594
		position = local.id;
595
	} else {
596
		position = local.id + this.maxFieldCount;
597
	}
598
	if (position < BitCacheSize) {
583
		// use bits
599
		// use bits
584
		return (this.nullBit1 & this.nullBit2
600
		return (this.nullBit1 & this.nullBit2
585
			& (~this.nullBit3 | ~this.nullBit4)
601
			& (~this.nullBit3 | ~this.nullBit4)
Lines 745-751 Link Here
745
	return isDefinitelyAssigned(local.id + this.maxFieldCount);
761
	return isDefinitelyAssigned(local.id + this.maxFieldCount);
746
}
762
}
747
763
748
final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
764
final public boolean isDefinitelyNonNull(VariableBinding local) {
765
	if (local instanceof FieldBinding && (this.tagBits & NULL_FLAG_MASK) == 0) {
766
		// no local yet in scope. Came here because of a field being queried for non null
767
		// will only happen for final fields, since they are assigned in a constructor or static block
768
		// and we may currently be in some other method
769
		this.tagBits |= NULL_FLAG_MASK;
770
	}
749
	// do not want to complain in unreachable code
771
	// do not want to complain in unreachable code
750
	if ((this.tagBits & UNREACHABLE) != 0 ||
772
	if ((this.tagBits & UNREACHABLE) != 0 ||
751
			(this.tagBits & NULL_FLAG_MASK) == 0) {
773
			(this.tagBits & NULL_FLAG_MASK) == 0) {
Lines 755-761 Link Here
755
			local.constant() != Constant.NotAConstant) { // String instances
777
			local.constant() != Constant.NotAConstant) { // String instances
756
		return true;
778
		return true;
757
	}
779
	}
758
	int position = local.id + this.maxFieldCount;
780
	int position;
781
	if (local instanceof FieldBinding) {
782
		if (local.isFinal() && ((FieldBinding)local).isStatic()) {
783
			// static final field's null status may not be in the flow info
784
			return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.NON_NULL);
785
		}
786
		position = local.id;
787
	} else {
788
		position = local.id + this.maxFieldCount;
789
	}
759
	if (position < BitCacheSize) { // use bits
790
	if (position < BitCacheSize) { // use bits
760
		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
791
		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
761
			    & (1L << position)) != 0;
792
			    & (1L << position)) != 0;
Lines 774-787 Link Here
774
		    & (1L << (position % BitCacheSize))) != 0;
805
		    & (1L << (position % BitCacheSize))) != 0;
775
}
806
}
776
807
777
final public boolean isDefinitelyNull(LocalVariableBinding local) {
808
final public boolean isDefinitelyNull(VariableBinding local) {
809
	if (local instanceof FieldBinding && (this.tagBits & NULL_FLAG_MASK) == 0) {
810
		// no local yet in scope. Came here because of a field being queried for non null
811
		// will only happen for final fields, since they are assigned in a constructor or static block
812
		// and we may currently be in some other method
813
		this.tagBits |= NULL_FLAG_MASK;
814
	}
778
	// do not want to complain in unreachable code
815
	// do not want to complain in unreachable code
779
	if ((this.tagBits & UNREACHABLE) != 0 ||
816
	if ((this.tagBits & UNREACHABLE) != 0 ||
780
			(this.tagBits & NULL_FLAG_MASK) == 0 ||
817
			(this.tagBits & NULL_FLAG_MASK) == 0 ||
781
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
818
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
782
		return false;
819
		return false;
783
	}
820
	}
784
	int position = local.id + this.maxFieldCount;
821
	int position;
822
	if (local instanceof FieldBinding) {
823
		if (local.isFinal() && ((FieldBinding)local).isStatic()) {
824
			// static final field's null status may not be in the flow info
825
			return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.NULL);
826
		}
827
		position = local.id;
828
	} else {
829
		position = local.id + this.maxFieldCount;
830
	}
785
	if (position < BitCacheSize) { // use bits
831
	if (position < BitCacheSize) { // use bits
786
		return ((this.nullBit1 & this.nullBit2
832
		return ((this.nullBit1 & this.nullBit2
787
			        & (~this.nullBit3 | ~this.nullBit4))
833
			        & (~this.nullBit3 | ~this.nullBit4))
Lines 801-813 Link Here
801
		    & (1L << (position % BitCacheSize))) != 0;
847
		    & (1L << (position % BitCacheSize))) != 0;
802
}
848
}
803
849
804
final public boolean isDefinitelyUnknown(LocalVariableBinding local) {
850
final public boolean isDefinitelyUnknown(VariableBinding local) {
805
	// do not want to complain in unreachable code
851
	// do not want to complain in unreachable code
806
	if ((this.tagBits & UNREACHABLE) != 0 ||
852
	if ((this.tagBits & UNREACHABLE) != 0 ||
807
			(this.tagBits & NULL_FLAG_MASK) == 0) {
853
			(this.tagBits & NULL_FLAG_MASK) == 0) {
808
		return false;
854
		return false;
809
	}
855
	}
810
	int position = local.id + this.maxFieldCount;
856
	int position;
857
	if (local instanceof FieldBinding) {
858
		position = local.id;
859
	} else {
860
		position = local.id + this.maxFieldCount;
861
	}
811
	if (position < BitCacheSize) { // use bits
862
	if (position < BitCacheSize) { // use bits
812
		return ((this.nullBit1 & this.nullBit4
863
		return ((this.nullBit1 & this.nullBit4
813
				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
864
				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
Lines 860-872 Link Here
860
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
911
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
861
}
912
}
862
913
863
final public boolean isPotentiallyNonNull(LocalVariableBinding local) {
914
final public boolean isPotentiallyNonNull(VariableBinding local) {
864
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
915
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
865
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
916
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
866
		return false;
917
		return false;
867
	}
918
	}
868
	int position;
919
	int position;
869
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
920
	if (local instanceof FieldBinding) {
921
		position = local.id;
922
	} else {
923
		position = local.id + this.maxFieldCount;
924
	}
925
	if (position < BitCacheSize) { // use bits
870
		// use bits
926
		// use bits
871
		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
927
		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
872
			    & (1L << position)) != 0;
928
			    & (1L << position)) != 0;
Lines 885-897 Link Here
885
		    & (1L << (position % BitCacheSize))) != 0;
941
		    & (1L << (position % BitCacheSize))) != 0;
886
}
942
}
887
943
888
final public boolean isPotentiallyNull(LocalVariableBinding local) {
944
final public boolean isPotentiallyNull(VariableBinding local) {
889
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
945
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
890
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
946
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
891
		return false;
947
		return false;
892
	}
948
	}
893
	int position;
949
	int position;
894
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
950
	if (local instanceof FieldBinding) {
951
		if (local.isFinal() && ((FieldBinding)local).isStatic()) {
952
			// static final field's null status may not be in the flow info
953
			return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.POTENTIALLY_NULL);
954
		}
955
		position = local.id;
956
	} else {
957
		position = local.id + this.maxFieldCount;
958
	}
959
	if (position < BitCacheSize) {
895
		// use bits
960
		// use bits
896
		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
961
		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
897
			    & (1L << position)) != 0;
962
			    & (1L << position)) != 0;
Lines 910-922 Link Here
910
		    & (1L << (position % BitCacheSize))) != 0;
975
		    & (1L << (position % BitCacheSize))) != 0;
911
}
976
}
912
977
913
final public boolean isPotentiallyUnknown(LocalVariableBinding local) {
978
final public boolean isPotentiallyUnknown(VariableBinding local) {
914
	// do not want to complain in unreachable code
979
	// do not want to complain in unreachable code
915
	if ((this.tagBits & UNREACHABLE) != 0 ||
980
	if ((this.tagBits & UNREACHABLE) != 0 ||
916
			(this.tagBits & NULL_FLAG_MASK) == 0) {
981
			(this.tagBits & NULL_FLAG_MASK) == 0) {
917
		return false;
982
		return false;
918
	}
983
	}
919
	int position = local.id + this.maxFieldCount;
984
	int position;
985
	if (local instanceof FieldBinding) {
986
		position = local.id;
987
	} else {
988
		position = local.id + this.maxFieldCount;
989
	}
920
	if (position < BitCacheSize) { // use bits
990
	if (position < BitCacheSize) { // use bits
921
		return (this.nullBit4
991
		return (this.nullBit4
922
			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
992
			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
Lines 937-950 Link Here
937
		    & (1L << (position % BitCacheSize))) != 0;
1007
		    & (1L << (position % BitCacheSize))) != 0;
938
}
1008
}
939
1009
940
final public boolean isProtectedNonNull(LocalVariableBinding local) {
1010
final public boolean isProtectedNonNull(VariableBinding local) {
941
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
1011
	if ((this.tagBits & NULL_FLAG_MASK) == 0 ||
942
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
1012
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
943
		return false;
1013
		return false;
944
	}
1014
	}
945
	int position;
1015
	int position;
946
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1016
	if (local instanceof FieldBinding) {
947
		// use bits
1017
		position = local.id;
1018
	} else {
1019
		position = local.id + this.maxFieldCount;
1020
	}
1021
	if (position < BitCacheSize) { // 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
	}
950
	// use extra vector
1024
	// use extra vector
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) {
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
			this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL);
1090
			return;
1091
		} else {
1092
			position = local.id + this.maxFieldCount;
1093
		}
1009
		long mask;
1094
		long mask;
1010
		long a1, a2, a3, a4, na2;
1095
		long a1, a2, a3, a4, na2;
1011
		// position is zero-based
1096
		// position is zero-based
1012
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1097
		if (position < BitCacheSize) {
1013
			// use bits
1098
			// use bits
1014
			if (((mask = 1L << position)
1099
			if (((mask = 1L << position)
1015
				& (a1 = this.nullBit1)
1100
				& (a1 = this.nullBit1)
Lines 1098-1111 Link Here
1098
	}
1183
	}
1099
}
1184
}
1100
1185
1101
public void markAsComparedEqualToNull(LocalVariableBinding local) {
1186
public void markAsComparedEqualToNull(VariableBinding local) {
1102
	// protected from non-object locals in calling methods
1187
	// protected from non-object locals in calling methods
1103
	if (this != DEAD_END) {
1188
	if (this != DEAD_END) {
1104
		this.tagBits |= NULL_FLAG_MASK;
1189
		this.tagBits |= NULL_FLAG_MASK;
1105
		int position;
1190
		int position;
1106
		long mask;
1191
		long mask;
1107
		// position is zero-based
1192
		// position is zero-based
1108
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1193
		if (local instanceof FieldBinding) {
1194
			this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL);
1195
			return;
1196
		} else {
1197
			position = local.id + this.maxFieldCount;
1198
		}
1199
		if (position < BitCacheSize) {
1109
			// use bits
1200
			// use bits
1110
			if (((mask = 1L << position) & this.nullBit1) != 0) {
1201
			if (((mask = 1L << position) & this.nullBit1) != 0) {
1111
  			  	if ((mask
1202
  			  	if ((mask
Lines 1236-1249 Link Here
1236
		markAsDefinitelyAssigned(local.id + this.maxFieldCount);
1327
		markAsDefinitelyAssigned(local.id + this.maxFieldCount);
1237
}
1328
}
1238
1329
1239
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
1330
public void markAsDefinitelyNonNull(VariableBinding local) {
1240
	// protected from non-object locals in calling methods
1331
	// protected from non-object locals in calling methods
1241
	if (this != DEAD_END) {
1332
	if (this != DEAD_END) {
1242
    	this.tagBits |= NULL_FLAG_MASK;
1333
    	this.tagBits |= NULL_FLAG_MASK;
1243
    	long mask;
1334
    	long mask;
1244
    	int position;
1335
    	int position;
1336
    	if (local instanceof FieldBinding) {
1337
    		this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL);
1338
    		return;
1339
    	} else {
1340
    		position = local.id + this.maxFieldCount;
1341
    	}
1245
    	// position is zero-based
1342
    	// position is zero-based
1246
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
1343
    	if (position < BitCacheSize) { // use bits
1247
    		// set assigned non null
1344
    		// set assigned non null
1248
    		this.nullBit1 |= (mask = 1L << position);
1345
    		this.nullBit1 |= (mask = 1L << position);
1249
    		this.nullBit3 |= mask;
1346
    		this.nullBit3 |= mask;
Lines 1258-1265 Link Here
1258
    	}
1355
    	}
1259
    	else {
1356
    	else {
1260
    		// use extra vector
1357
    		// use extra vector
1261
    		int vectorIndex ;
1358
    		int vectorIndex = (position / BitCacheSize) - 1;
1262
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1359
    		if (this.extra == null) {
1360
    			int length = vectorIndex + 1;
1361
    			this.extra = new long[extraLength][];
1362
    			for (int j = 0; j < extraLength; j++) {
1363
    				this.extra[j] = new long[length];
1364
    			}
1365
    		}
1366
    		else {
1367
    			int oldLength; // might need to grow the arrays
1368
    			if (vectorIndex >= (oldLength = this.extra[0].length)) {
1369
    				for (int j = 0; j < extraLength; j++) {
1370
    					System.arraycopy(this.extra[j], 0,
1371
    						(this.extra[j] = new long[vectorIndex + 1]), 0,
1372
    						oldLength);
1373
    				}
1374
    			}
1375
    		}
1376
    		this.extra[2][vectorIndex]
1263
    		    |= (mask = 1L << (position % BitCacheSize));
1377
    		    |= (mask = 1L << (position % BitCacheSize));
1264
    		this.extra[4][vectorIndex] |= mask;
1378
    		this.extra[4][vectorIndex] |= mask;
1265
    		this.extra[3][vectorIndex] &= (mask = ~mask);
1379
    		this.extra[3][vectorIndex] &= (mask = ~mask);
Lines 1273-1286 Link Here
1273
	}
1387
	}
1274
}
1388
}
1275
1389
1276
public void markAsDefinitelyNull(LocalVariableBinding local) {
1390
public void markAsDefinitelyNull(VariableBinding local) {
1277
	// protected from non-object locals in calling methods
1391
	// protected from non-object locals in calling methods
1278
	if (this != DEAD_END) {
1392
	if (this != DEAD_END) {
1279
    	this.tagBits |= NULL_FLAG_MASK;
1393
    	this.tagBits |= NULL_FLAG_MASK;
1280
    	long mask;
1394
    	long mask;
1281
    	int position;
1395
    	int position;
1396
    	if (local instanceof FieldBinding) {
1397
    		this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL);
1398
    		return;
1399
    	} else {
1400
    		position = local.id + this.maxFieldCount;
1401
    	}
1282
    	// position is zero-based
1402
    	// position is zero-based
1283
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
1403
    	if (position < BitCacheSize) { // use bits
1284
    		// mark assigned null
1404
    		// mark assigned null
1285
    		this.nullBit1 |= (mask = 1L << position);
1405
    		this.nullBit1 |= (mask = 1L << position);
1286
    		this.nullBit2 |= mask;
1406
    		this.nullBit2 |= mask;
Lines 1295-1302 Link Here
1295
    	}
1415
    	}
1296
    	else {
1416
    	else {
1297
    		// use extra vector
1417
    		// use extra vector
1298
    		int vectorIndex ;
1418
    		int vectorIndex = (position / BitCacheSize) - 1;
1299
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1419
    		if (this.extra == null) {
1420
    			int length = vectorIndex + 1;
1421
    			this.extra = new long[extraLength][];
1422
    			for (int j = 0; j < extraLength; j++) {
1423
    				this.extra[j] = new long[length];
1424
    			}
1425
    		}
1426
    		else {
1427
    			int oldLength; // might need to grow the arrays
1428
    			if (vectorIndex >= (oldLength = this.extra[0].length)) {
1429
    				for (int j = 0; j < extraLength; j++) {
1430
    					System.arraycopy(this.extra[j], 0,
1431
    						(this.extra[j] = new long[vectorIndex + 1]), 0,
1432
    						oldLength);
1433
    				}
1434
    			}
1435
    		}
1436
    		this.extra[2][vectorIndex]
1300
    		    |= (mask = 1L << (position % BitCacheSize));
1437
    		    |= (mask = 1L << (position % BitCacheSize));
1301
    		this.extra[3][vectorIndex] |= mask;
1438
    		this.extra[3][vectorIndex] |= mask;
1302
    		this.extra[4][vectorIndex] &= (mask = ~mask);
1439
    		this.extra[4][vectorIndex] &= (mask = ~mask);
Lines 1316-1329 Link Here
1316
 */
1453
 */
1317
// PREMATURE may try to get closer to markAsDefinitelyAssigned, but not
1454
// PREMATURE may try to get closer to markAsDefinitelyAssigned, but not
1318
//			 obvious
1455
//			 obvious
1319
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
1456
public void markAsDefinitelyUnknown(VariableBinding local) {
1320
	// protected from non-object locals in calling methods
1457
	// protected from non-object locals in calling methods
1321
	if (this != DEAD_END) {
1458
	if (this != DEAD_END) {
1322
		this.tagBits |= NULL_FLAG_MASK;
1459
		this.tagBits |= NULL_FLAG_MASK;
1323
		long mask;
1460
		long mask;
1324
		int position;
1461
		int position;
1462
		if (local instanceof FieldBinding) {
1463
			position = local.id;
1464
		} else {
1465
			position = local.id + this.maxFieldCount;
1466
		}
1325
		// position is zero-based
1467
		// position is zero-based
1326
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1468
		if (position < BitCacheSize) {
1327
			// use bits
1469
			// use bits
1328
			// mark assigned null
1470
			// mark assigned null
1329
			this.nullBit1 |= (mask = 1L << position);
1471
			this.nullBit1 |= (mask = 1L << position);
Lines 1339-1346 Link Here
1339
		}
1481
		}
1340
		else {
1482
		else {
1341
			// use extra vector
1483
			// use extra vector
1342
			int vectorIndex ;
1484
			int vectorIndex = (position / BitCacheSize) - 1;
1343
			this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1485
			if (this.extra == null) {
1486
				int length = vectorIndex + 1;
1487
				this.extra = new long[extraLength][];
1488
				for (int j = 0; j < extraLength; j++) {
1489
					this.extra[j] = new long[length];
1490
				}
1491
			}
1492
			else {
1493
				int oldLength; // might need to grow the arrays
1494
				if (vectorIndex >= (oldLength = this.extra[0].length)) {
1495
					for (int j = 0; j < extraLength; j++) {
1496
						System.arraycopy(this.extra[j], 0,
1497
							(this.extra[j] = new long[vectorIndex + 1]), 0,
1498
							oldLength);
1499
					}
1500
				}
1501
			}
1502
			this.extra[2][vectorIndex]
1344
			    |= (mask = 1L << (position % BitCacheSize));
1503
			    |= (mask = 1L << (position % BitCacheSize));
1345
			this.extra[5][vectorIndex] |= mask;
1504
			this.extra[5][vectorIndex] |= mask;
1346
			this.extra[3][vectorIndex] &= (mask = ~mask);
1505
			this.extra[3][vectorIndex] &= (mask = ~mask);
Lines 1354-1365 Link Here
1354
	}
1513
	}
1355
}
1514
}
1356
1515
1357
public void resetNullInfo(LocalVariableBinding local) {
1516
public void resetNullInfo(VariableBinding local) {
1358
	if (this != DEAD_END) {
1517
	if (this != DEAD_END) {
1359
		this.tagBits |= NULL_FLAG_MASK;
1518
		this.tagBits |= NULL_FLAG_MASK;
1360
        int position;
1519
        int position;
1361
        long mask;
1520
        long mask;
1362
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1521
        if (local instanceof FieldBinding) {
1522
        	position = local.id;
1523
        } else {
1524
        	position = local.id + this.maxFieldCount;
1525
        }
1526
        if (position < BitCacheSize) {
1363
            // use bits
1527
            // use bits
1364
            this.nullBit1 &= (mask = ~(1L << position));
1528
            this.nullBit1 &= (mask = ~(1L << position));
1365
            this.nullBit2 &= mask;
1529
            this.nullBit2 &= mask;
Lines 1381-1398 Link Here
1381
    	}
1545
    	}
1382
	}
1546
	}
1383
}
1547
}
1548
public void resetNullInfoForFields() {
1549
	if (this != DEAD_END) {
1550
		long mask;
1551
		if (this.maxFieldCount < BitCacheSize) {
1552
			 // use bits
1553
	        this.nullBit1 &= (mask = -1L << this.maxFieldCount);
1554
	        this.nullBit2 &= mask;
1555
	        this.nullBit3 &= mask;
1556
	        this.nullBit4 &= mask;
1557
		}
1558
		else {
1559
			 this.nullBit1 &= (mask = 0L);
1560
		     this.nullBit2 &= mask;
1561
		     this.nullBit3 &= mask;
1562
		     this.nullBit4 &= mask;
1563
			if (this.extra != null){
1564
				for (int position = BitCacheSize; position < this.maxFieldCount; position++) {
1565
					// use extra vector
1566
				    int vectorIndex = (position / BitCacheSize) - 1;
1567
				    if (vectorIndex >= this.extra[2].length)
1568
						break;   // No null info about fields beyond this point in the extra vector
1569
					this.extra[2][vectorIndex]
1570
					    &= (mask = ~(1L << (position % BitCacheSize)));
1571
					this.extra[3][vectorIndex] &= mask;
1572
					this.extra[4][vectorIndex] &= mask;
1573
					this.extra[5][vectorIndex] &= mask;
1574
				}
1575
			}
1576
		}
1577
	}
1578
}
1384
1579
1385
/**
1580
/**
1386
 * Mark a local as potentially having been assigned to an unknown value.
1581
 * Mark a local as potentially having been assigned to an unknown value.
1387
 * @param local the local to mark
1582
 * @param local the local to mark
1388
 */
1583
 */
1389
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
1584
public void markPotentiallyUnknownBit(VariableBinding local) {
1390
	// protected from non-object locals in calling methods
1585
	// protected from non-object locals in calling methods
1391
	if (this != DEAD_END) {
1586
	if (this != DEAD_END) {
1392
		this.tagBits |= NULL_FLAG_MASK;
1587
		this.tagBits |= NULL_FLAG_MASK;
1393
        int position;
1588
        int position;
1394
        long mask;
1589
        long mask;
1395
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1590
        if (local instanceof FieldBinding) {
1591
        	position = local.id;
1592
        } else {
1593
        	position = local.id + this.maxFieldCount;
1594
        }
1595
        if (position < BitCacheSize) {
1396
            // use bits
1596
            // use bits
1397
        	mask = 1L << position;
1597
        	mask = 1L << position;
1398
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
1598
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
Lines 1434-1445 Link Here
1434
	}
1634
	}
1435
}
1635
}
1436
1636
1437
public void markPotentiallyNullBit(LocalVariableBinding local) {
1637
public void markPotentiallyNullBit(VariableBinding local) {
1438
	if (this != DEAD_END) {
1638
	if (this != DEAD_END) {
1439
		this.tagBits |= NULL_FLAG_MASK;
1639
		this.tagBits |= NULL_FLAG_MASK;
1440
        int position;
1640
        int position;
1441
        long mask;
1641
        long mask;
1442
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1642
        if (local instanceof FieldBinding) {
1643
        	position = local.id;
1644
        } else {
1645
        	position = local.id + this.maxFieldCount;
1646
        }
1647
        if (position < BitCacheSize) {
1443
            // use bits
1648
            // use bits
1444
        	mask = 1L << position;
1649
        	mask = 1L << position;
1445
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
1650
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
Lines 1481-1492 Link Here
1481
	}
1686
	}
1482
}
1687
}
1483
1688
1484
public void markPotentiallyNonNullBit(LocalVariableBinding local) {
1689
public void markPotentiallyNonNullBit(VariableBinding local) {
1485
	if (this != DEAD_END) {
1690
	if (this != DEAD_END) {
1486
		this.tagBits |= NULL_FLAG_MASK;
1691
		this.tagBits |= NULL_FLAG_MASK;
1487
        int position;
1692
        int position;
1488
        long mask;
1693
        long mask;
1489
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1694
        if (local instanceof FieldBinding) {
1695
        	position = local.id;
1696
        } else {
1697
        	position = local.id + this.maxFieldCount;
1698
        }
1699
        if (position < BitCacheSize) {
1490
            // use bits
1700
            // use bits
1491
        	mask = 1L << position;
1701
        	mask = 1L << position;
1492
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
1702
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
Lines 2007-2014 Link Here
2007
	return this;
2217
	return this;
2008
}
2218
}
2009
2219
2010
public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
2220
public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding) {
2011
	int position = local.id + this.maxFieldCount;
2221
	int position;
2222
	if (binding instanceof FieldBinding) {
2223
		position = binding.id;
2224
	} else {
2225
		position = binding.id + this.maxFieldCount;
2226
	}
2012
	int oldLength;
2227
	int oldLength;
2013
	if (this.nullStatusChangedInAssert == null) {
2228
	if (this.nullStatusChangedInAssert == null) {
2014
		this.nullStatusChangedInAssert = new int[position + 1];
2229
		this.nullStatusChangedInAssert = new int[position + 1];
Lines 2021-2028 Link Here
2021
	this.nullStatusChangedInAssert[position] = 1;
2236
	this.nullStatusChangedInAssert[position] = 1;
2022
}
2237
}
2023
2238
2024
public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
2239
public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding) {
2025
	int position = local.id + this.maxFieldCount;
2240
	int position;
2241
	if (binding instanceof FieldBinding) {
2242
		position = binding.id;
2243
	} else {
2244
		position = binding.id + this.maxFieldCount;
2245
	}
2026
	if(this.nullStatusChangedInAssert == null || position >= this.nullStatusChangedInAssert.length) {
2246
	if(this.nullStatusChangedInAssert == null || position >= this.nullStatusChangedInAssert.length) {
2027
		return false;
2247
		return false;
2028
	}
2248
	}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java (-2 / +9 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 34-44 Link Here
34
	public TypeDeclaration referenceContext;
34
	public TypeDeclaration referenceContext;
35
	public TypeReference superTypeReference;
35
	public TypeReference superTypeReference;
36
	java.util.ArrayList deferredBoundChecks;
36
	java.util.ArrayList deferredBoundChecks;
37
	public int cumulativeFieldCount;   // cumulative field count from all enclosing types, used to build unique field id's for member types.
37
38
38
	public ClassScope(Scope parent, TypeDeclaration context) {
39
	public ClassScope(Scope parent, TypeDeclaration context) {
39
		super(Scope.CLASS_SCOPE, parent);
40
		super(Scope.CLASS_SCOPE, parent);
40
		this.referenceContext = context;
41
		this.referenceContext = context;
41
		this.deferredBoundChecks = null; // initialized if required
42
		this.deferredBoundChecks = null; // initialized if required
43
		this.cumulativeFieldCount = 0;
42
	}
44
	}
43
45
44
	void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
46
	void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
Lines 104-109 Link Here
104
		FieldBinding[] fieldBindings = new FieldBinding[count];
106
		FieldBinding[] fieldBindings = new FieldBinding[count];
105
		HashtableOfObject knownFieldNames = new HashtableOfObject(count);
107
		HashtableOfObject knownFieldNames = new HashtableOfObject(count);
106
		count = 0;
108
		count = 0;
109
		ClassScope enclosingClass = this.enclosingClassScope();
110
		if (enclosingClass != null) {
111
			this.cumulativeFieldCount += enclosingClass.cumulativeFieldCount;
112
		}
107
		for (int i = 0; i < size; i++) {
113
		for (int i = 0; i < size; i++) {
108
			FieldDeclaration field = fields[i];
114
			FieldDeclaration field = fields[i];
109
			if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
115
			if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
Lines 111-117 Link Here
111
				// now this error reporting is moved into the parser itself. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=212713
117
				// now this error reporting is moved into the parser itself. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=212713
112
			} else {
118
			} else {
113
				FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | ExtraCompilerModifiers.AccUnresolved, sourceType);
119
				FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | ExtraCompilerModifiers.AccUnresolved, sourceType);
114
				fieldBinding.id = count;
120
				fieldBinding.id = count + this.cumulativeFieldCount;
115
				// field's type will be resolved when needed for top level types
121
				// field's type will be resolved when needed for top level types
116
				checkAndSetModifiersForField(fieldBinding, field);
122
				checkAndSetModifiersForField(fieldBinding, field);
117
123
Lines 139-144 Link Here
139
		// remove duplicate fields
145
		// remove duplicate fields
140
		if (count != fieldBindings.length)
146
		if (count != fieldBindings.length)
141
			System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
147
			System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
148
		this.cumulativeFieldCount += count;
142
		sourceType.tagBits &= ~(TagBits.AreFieldsSorted|TagBits.AreFieldsComplete); // in case some static imports reached already into this type
149
		sourceType.tagBits &= ~(TagBits.AreFieldsSorted|TagBits.AreFieldsComplete); // in case some static imports reached already into this type
143
		sourceType.setFields(fieldBindings);
150
		sourceType.setFields(fieldBindings);
144
	}
151
	}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java (+12 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-40 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) {
35
	super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
38
	super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
36
	this.declaringClass = declaringClass;
39
	this.declaringClass = declaringClass;
37
	this.id = initialFieldBinding.id;
40
	this.id = initialFieldBinding.id;
41
	this.nullStatus = FlowInfo.UNKNOWN;
38
	setAnnotations(initialFieldBinding.getAnnotations());
42
	setAnnotations(initialFieldBinding.getAnnotations());
39
}
43
}
40
/* API
44
/* API
Lines 386-389 Link Here
386
	}
390
	}
387
	return null;
391
	return null;
388
}
392
}
393
394
public int getNullStatusForStaticFinalField() {
395
	return this.nullStatus;
396
}
397
398
public void setNullStatusForStaticFinalField(int nullStatusToMark) {
399
	this.nullStatus = nullStatusToMark;
400
}
389
}
401
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (-1 / +15 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 38-43 Link Here
38
	char[] fileName;
38
	char[] fileName;
39
	char[] constantPoolName;
39
	char[] constantPoolName;
40
	char[] signature;
40
	char[] signature;
41
//	int cumulativeFieldCount;
41
42
42
	private SimpleLookupTable compatibleCache;
43
	private SimpleLookupTable compatibleCache;
43
44
Lines 1380-1383 Link Here
1380
public FieldBinding[] unResolvedFields() {
1381
public FieldBinding[] unResolvedFields() {
1381
	return Binding.NO_FIELDS;
1382
	return Binding.NO_FIELDS;
1382
}
1383
}
1384
1385
//public int findCumulativeFieldCount() {
1386
//	FieldBinding[] unResolvedFields = this.unResolvedFields();
1387
//	if (unResolvedFields != null) {
1388
//		this.cumulativeFieldCount += unResolvedFields.length;
1389
//	}
1390
//	ReferenceBinding superClassBinding = this.superclass();
1391
//	if (superClassBinding != null) {
1392
//		this.cumulativeFieldCount += superClassBinding.cumulativeFieldCount;
1393
//	}
1394
//	ReferenceBinding[] superInterfacesBinding = this.superInterfaces;
1395
//	return this.cumulativeFieldCount;
1396
//}
1383
}
1397
}
(-)compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (-48 / +105 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-4973 Link Here
4866
	}
4875
	}
4867
}
4876
}
4868
4877
4869
public void localVariableNonNullComparedToNull(LocalVariableBinding local, ASTNode location) {
4878
public void variableNonNullComparedToNull(VariableBinding variable, ASTNode location) {
4870
	int severity = computeSeverity(IProblem.NonNullLocalVariableComparisonYieldsFalse);
4879
	int problem;
4880
	if (variable instanceof FieldBinding) {
4881
		problem = IProblem.NonNullFieldComparisonYieldsFalse;
4882
	} else {
4883
		problem = IProblem.NonNullLocalVariableComparisonYieldsFalse;
4884
	}
4885
	int severity = computeSeverity(problem);
4871
	if (severity == ProblemSeverities.Ignore) return;
4886
	if (severity == ProblemSeverities.Ignore) return;
4872
	String[] arguments = new String[] {new String(local.name)  };
4887
	String[] arguments = new String[] {new String(variable.name)  };
4873
	this.handle(
4888
	this.handle(
4874
		IProblem.NonNullLocalVariableComparisonYieldsFalse,
4889
		problem,
4875
		arguments,
4890
		arguments,
4876
		arguments,
4891
		arguments,
4877
		severity,
4892
		severity,
4878
		nodeSourceStart(local, location),
4893
		nodeSourceStart(variable, location),
4879
		nodeSourceEnd(local, location));
4894
		nodeSourceEnd(variable, location));
4880
}
4895
}
4881
4896
4882
public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNode location) {
4897
public void variableNullComparedToNonNull(VariableBinding variable, ASTNode location) {
4883
	int severity = computeSeverity(IProblem.NullLocalVariableComparisonYieldsFalse);
4898
	int problem;
4899
	if (variable instanceof FieldBinding) {
4900
		problem = IProblem.NullFieldComparisonYieldsFalse;
4901
	} else {
4902
		problem = IProblem.NullLocalVariableComparisonYieldsFalse;
4903
	}
4904
	int severity = computeSeverity(problem);
4884
	if (severity == ProblemSeverities.Ignore) return;
4905
	if (severity == ProblemSeverities.Ignore) return;
4885
	String[] arguments = new String[] {new String(local.name)  };
4906
	String[] arguments = new String[] {new String(variable.name)  };
4886
	this.handle(
4907
	this.handle(
4887
		IProblem.NullLocalVariableComparisonYieldsFalse,
4908
		problem,
4888
		arguments,
4909
		arguments,
4889
		arguments,
4910
		arguments,
4890
		severity,
4911
		severity,
4891
		nodeSourceStart(local, location),
4912
		nodeSourceStart(variable, location),
4892
		nodeSourceEnd(local, location));
4913
		nodeSourceEnd(variable, location));
4893
}
4914
}
4894
4915
4895
public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) {
4916
public void variableNullInstanceof(VariableBinding variable, ASTNode location) {
4896
	int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse);
4917
	int problem;
4918
	if (variable instanceof FieldBinding) {
4919
		problem = IProblem.NullFieldInstanceofYieldsFalse;
4920
	} else {
4921
		problem = IProblem.NullLocalVariableInstanceofYieldsFalse;
4922
	}
4923
	int severity = computeSeverity(problem);
4897
	if (severity == ProblemSeverities.Ignore) return;
4924
	if (severity == ProblemSeverities.Ignore) return;
4898
	String[] arguments = new String[] {new String(local.name)  };
4925
	String[] arguments = new String[] {new String(variable.name)  };
4899
	this.handle(
4926
	this.handle(
4900
		IProblem.NullLocalVariableInstanceofYieldsFalse,
4927
		problem,
4901
		arguments,
4928
		arguments,
4902
		arguments,
4929
		arguments,
4903
		severity,
4930
		severity,
4904
		nodeSourceStart(local, location),
4931
		nodeSourceStart(variable, location),
4905
		nodeSourceEnd(local, location));
4932
		nodeSourceEnd(variable, location));
4906
}
4933
}
4907
4934
4908
public void localVariableNullReference(LocalVariableBinding local, ASTNode location) {
4935
public void variableNullReference(VariableBinding variable, ASTNode location) {
4909
	int severity = computeSeverity(IProblem.NullLocalVariableReference);
4936
	int problem;
4937
	if (variable instanceof FieldBinding) {
4938
		problem = IProblem.NullFieldReference;
4939
	} else {
4940
		problem = IProblem.NullLocalVariableReference;
4941
	}
4942
	int severity = computeSeverity(problem);
4910
	if (severity == ProblemSeverities.Ignore) return;
4943
	if (severity == ProblemSeverities.Ignore) return;
4911
	String[] arguments = new String[] {new String(local.name)  };
4944
	String[] arguments = new String[] {new String(variable.name)  };
4912
	this.handle(
4945
	this.handle(
4913
		IProblem.NullLocalVariableReference,
4946
		problem,
4914
		arguments,
4947
		arguments,
4915
		arguments,
4948
		arguments,
4916
		severity,
4949
		severity,
4917
		nodeSourceStart(local, location),
4950
		nodeSourceStart(variable, location),
4918
		nodeSourceEnd(local, location));
4951
		nodeSourceEnd(variable, location));
4919
}
4952
}
4920
4953
4921
public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) {
4954
public void variablePotentialNullReference(VariableBinding variable, ASTNode location) {
4922
	int severity = computeSeverity(IProblem.PotentialNullLocalVariableReference);
4955
	int problem;
4956
	if (variable instanceof FieldBinding) {
4957
		problem = IProblem.PotentialNullFieldReference;
4958
	} else {
4959
		problem = IProblem.PotentialNullLocalVariableReference;
4960
	}
4961
	int severity = computeSeverity(problem);
4923
	if (severity == ProblemSeverities.Ignore) return;
4962
	if (severity == ProblemSeverities.Ignore) return;
4924
	String[] arguments = new String[] {new String(local.name)};
4963
	String[] arguments = new String[] {new String(variable.name)  };
4925
	this.handle(
4964
	this.handle(
4926
		IProblem.PotentialNullLocalVariableReference,
4965
		problem,
4927
		arguments,
4966
		arguments,
4928
		arguments,
4967
		arguments,
4929
		severity,
4968
		severity,
4930
		nodeSourceStart(local, location),
4969
		nodeSourceStart(variable, location),
4931
		nodeSourceEnd(local, location));
4970
		nodeSourceEnd(variable, location));
4932
}
4971
}
4933
4972
4934
public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) {
4973
public void variableRedundantCheckOnNonNull(VariableBinding variable, ASTNode location) {
4935
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable);
4974
	int problem;
4975
	if (variable instanceof FieldBinding) {
4976
		problem = IProblem.RedundantNullCheckOnNonNullField;
4977
	} else {
4978
		problem = IProblem.RedundantNullCheckOnNonNullLocalVariable;
4979
	}
4980
	int severity = computeSeverity(problem);
4936
	if (severity == ProblemSeverities.Ignore) return;
4981
	if (severity == ProblemSeverities.Ignore) return;
4937
	String[] arguments = new String[] {new String(local.name)  };
4982
	String[] arguments = new String[] {new String(variable.name)  };
4938
	this.handle(
4983
	this.handle(
4939
		IProblem.RedundantNullCheckOnNonNullLocalVariable,
4984
		problem,
4940
		arguments,
4985
		arguments,
4941
		arguments,
4986
		arguments,
4942
		severity,
4987
		severity,
4943
		nodeSourceStart(local, location),
4988
		nodeSourceStart(variable, location),
4944
		nodeSourceEnd(local, location));
4989
		nodeSourceEnd(variable, location));
4945
}
4990
}
4946
4991
4947
public void localVariableRedundantCheckOnNull(LocalVariableBinding local, ASTNode location) {
4992
public void variableRedundantCheckOnNull (VariableBinding variable, ASTNode location) {
4948
	int severity = computeSeverity(IProblem.RedundantNullCheckOnNullLocalVariable);
4993
	int problem;
4994
	if (variable instanceof FieldBinding) {
4995
		problem = IProblem.RedundantNullCheckOnNullField;
4996
	} else {
4997
		problem = IProblem.RedundantNullCheckOnNullLocalVariable;
4998
	}
4999
	int severity = computeSeverity(problem);
4949
	if (severity == ProblemSeverities.Ignore) return;
5000
	if (severity == ProblemSeverities.Ignore) return;
4950
	String[] arguments = new String[] {new String(local.name)  };
5001
	String[] arguments = new String[] {new String(variable.name)  };
4951
	this.handle(
5002
	this.handle(
4952
		IProblem.RedundantNullCheckOnNullLocalVariable,
5003
		problem,
4953
		arguments,
5004
		arguments,
4954
		arguments,
5005
		arguments,
4955
		severity,
5006
		severity,
4956
		nodeSourceStart(local, location),
5007
		nodeSourceStart(variable, location),
4957
		nodeSourceEnd(local, location));
5008
		nodeSourceEnd(variable, location));
4958
}
5009
}
4959
5010
4960
public void localVariableRedundantNullAssignment(LocalVariableBinding local, ASTNode location) {
5011
public void variableRedundantNullAssignment (VariableBinding variable, ASTNode location) {
4961
	int severity = computeSeverity(IProblem.RedundantLocalVariableNullAssignment);
5012
	int problem;
5013
	if (variable instanceof FieldBinding) {
5014
		problem = IProblem.RedundantFieldNullAssignment;
5015
	} else {
5016
		problem = IProblem.RedundantLocalVariableNullAssignment;
5017
	}
5018
	int severity = computeSeverity(problem);
4962
	if (severity == ProblemSeverities.Ignore) return;
5019
	if (severity == ProblemSeverities.Ignore) return;
4963
	String[] arguments = new String[] {new String(local.name)  };
5020
	String[] arguments = new String[] {new String(variable.name)  };
4964
	this.handle(
5021
	this.handle(
4965
		IProblem.RedundantLocalVariableNullAssignment,
5022
		problem,
4966
		arguments,
5023
		arguments,
4967
		arguments,
5024
		arguments,
4968
		severity,
5025
		severity,
4969
		nodeSourceStart(local, location),
5026
		nodeSourceStart(variable, location),
4970
		nodeSourceEnd(local, location));
5027
		nodeSourceEnd(variable, location));
4971
}
5028
}
4972
5029
4973
public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) {
5030
public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) {
(-)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
(-)Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java (-1 / +1 lines)
Lines 32-38 Link Here
32
	// Only the highest compliance level is run; add the VM argument
32
	// Only the highest compliance level is run; add the VM argument
33
	// -Dcompliance=1.4 (for example) to lower it if needed
33
	// -Dcompliance=1.4 (for example) to lower it if needed
34
	static {
34
	static {
35
//		TESTS_NAMES = new String[] { "test011" };
35
		TESTS_NAMES = new String[] { "test001" };
36
//	 	TESTS_NUMBERS = new int[] { 204 };
36
//	 	TESTS_NUMBERS = new int[] { 204 };
37
//		TESTS_RANGE = new int[] { 231, 240 };
37
//		TESTS_RANGE = new int[] { 231, 240 };
38
	}
38
	}
(-)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 (-6 / +26 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 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) {
1087
	grow(local.id + this.maxFieldCount);
1089
	int position;
1090
	if (local instanceof FieldBinding) {
1091
		position = local.id;
1092
	} else {
1093
		position = local.id + this.maxFieldCount;
1094
	}
1095
	grow(position);
1088
	super.markAsDefinitelyNonNull(local);
1096
	super.markAsDefinitelyNonNull(local);
1089
}
1097
}
1090
1098
1091
public void markAsDefinitelyNull(LocalVariableBinding local) {
1099
public void markAsDefinitelyNull(VariableBinding local) {
1092
	grow(local.id + this.maxFieldCount);
1100
	int position;
1101
	if (local instanceof FieldBinding) {
1102
		position = local.id;
1103
	} else {
1104
		position = local.id + this.maxFieldCount;
1105
	}
1106
	grow(position);
1093
	super.markAsDefinitelyNull(local);
1107
	super.markAsDefinitelyNull(local);
1094
}
1108
}
1095
1109
1096
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
1110
public void markAsDefinitelyUnknown(VariableBinding local) {
1097
	grow(local.id + this.maxFieldCount);
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/NullReferenceTest.java (-36 / +569 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[] { "testBug247564h_1" };
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
		"Potential null pointer access: The field o may 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 null analysis for fields in synchronized methods
13875
// behave as it does in ordinary methods.
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
			"  static final Object o2 = null;\n" +
13884
			"  static final Object o3 = new Object();\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
			"		if (o2 != null) {\n" +
13895
			"		}\n" +
13896
			"		else {\n" +
13897
			"			o2.toString();\n" +
13898
			"		}\n" +
13899
			"		if (o3 == null) {\n" +
13900
			"		}\n" +
13901
			"		else {\n" +
13902
			"			o3.toString();\n" +
13903
			"		}\n" +
13904
			"  }\n" +
13905
			"  void foo1() {\n" + 
13906
			"	 o.toString();\n" +
13907
			"  }\n" +
13908
			"}\n"},
13909
		"----------\n" + 
13910
		"1. ERROR in X.java (at line 9)\n" + 
13911
		"	o.toString();\n" + 
13912
		"	^\n" + 
13913
		"Potential null pointer access: The field o may be null at this location\n" + 
13914
		"----------\n" + 
13915
		"2. ERROR in X.java (at line 13)\n" + 
13916
		"	o1.toString();\n" + 
13917
		"	^^\n" + 
13918
		"Potential null pointer access: The field o1 may be null at this location\n" + 
13919
		"----------\n" + 
13920
		"3. ERROR in X.java (at line 15)\n" + 
13921
		"	if (o2 != null) {\n" + 
13922
		"	    ^^\n" + 
13923
		"Null comparison always yields false: The field o2 can only be null at this location\n" + 
13924
		"----------\n" + 
13925
		"4. WARNING in X.java (at line 15)\n" + 
13926
		"	if (o2 != null) {\n" + 
13927
		"		}\n" + 
13928
		"	                ^^^^^\n" + 
13929
		"Dead code\n" + 
13930
		"----------\n" + 
13931
		"5. ERROR in X.java (at line 18)\n" + 
13932
		"	o2.toString();\n" + 
13933
		"	^^\n" + 
13934
		"Null pointer access: The field o2 can only be null at this location\n" + 
13935
		"----------\n" + 
13936
		"6. ERROR in X.java (at line 20)\n" + 
13937
		"	if (o3 == null) {\n" + 
13938
		"	    ^^\n" + 
13939
		"Null comparison always yields false: The field o3 cannot be null at this location\n" + 
13940
		"----------\n" + 
13941
		"7. WARNING in X.java (at line 20)\n" + 
13942
		"	if (o3 == null) {\n" + 
13943
		"		}\n" + 
13944
		"	                ^^^^^\n" + 
13945
		"Dead code\n" + 
13946
		"----------\n"
13947
	);
13948
}
13949
13950
// null analysis -- test redundant instanceof warning for static final field
13951
public void testBug247564d() {
13952
	this.runNegativeTest(
13953
		new String[] {
13954
			"X.java",
13955
			"public class X {\n" +
13956
			"  static final Object o = null;\n" +
13957
			"  static final Object o1 = new Object();\n" +
13958
			"  void foo() {\n" +
13959
			"    if (o instanceof String) {}\n" +
13960
			"    if (o1 instanceof String) {}\n" +
13961
			"  }\n" +
13962
			"}\n"},
13963
		"----------\n" + 
13964
		"1. ERROR in X.java (at line 5)\n" + 
13965
		"	if (o instanceof String) {}\n" + 
13966
		"	    ^\n" + 
13967
		"instanceof always yields false: The field o can only be null at this location\n" + 
13968
		"----------\n"
13969
	);
13970
}
13971
13972
// null analysis -- test redundant instanceof warning for static final fields
13973
public void testBug247564e_1() {
13974
	this.runNegativeTest(
13975
		new String[] {
13976
			"X.java",
13977
			"public class X {\n" +
13978
			"  static final Object o = null;\n" +
13979
			"  void foo() {\n" +
13980
			"      if (o instanceof X) return;\n" +
13981
			"  }\n" +
13982
			"}"},
13983
		"----------\n" + 
13984
		"1. ERROR in X.java (at line 4)\n" + 
13985
		"	if (o instanceof X) return;\n" + 
13986
		"	    ^\n" + 
13987
		"instanceof always yields false: The field o can only be null at this location\n" + 
13988
		"----------\n",
13989
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
13990
}
13991
13992
// null analysis -- test potential null ptr access warning because of static field access through object returned by method call
13993
public void testBug247564f() {
13994
	Map compilerOptions = getCompilerOptions();
13995
	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
13996
	this.runNegativeTest(
13997
		false,
13998
		new String[] {
13999
			"X.java",
14000
			"public class X {\n" +
14001
			"  static Object o;\n" +
14002
			"  static Object o1;\n" +
14003
			"  Object o2;\n" +
14004
			"  X getX() { return new X();\n}\n" +
14005
			"  void foo() {\n" +
14006
			"      if (getX().o == null && this.o.hashCode() == 0) return;\n" +
14007
			"      if (getX().o2 == null && this.o2.hashCode() == 0) return;\n" +
14008
			"  }\n" +
14009
			"}"},
14010
		null,
14011
		compilerOptions,
14012
		"----------\n" +
14013
		"1. ERROR in X.java (at line 8)\n" + 
14014
		"	if (getX().o == null && this.o.hashCode() == 0) return;\n" + 
14015
		"	                             ^\n" + 
14016
		"Potential null pointer access: The field o may be null at this location\n" + 
14017
		"----------\n",
14018
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
14019
}
14020
14021
// null analysis -- test potential null ptr access warning because of static field access through object returned by method call
14022
public void testBug247564f_1() {
14023
	Map compilerOptions = getCompilerOptions();
14024
	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
14025
	this.runNegativeTest(
14026
		false,
14027
		new String[] {
14028
			"X.java",
14029
			"public class X {\n" +
14030
			"  static Object o;\n" +
14031
			"  X getX() { return new X();\n}\n" +
14032
			"  Y getY() { return new Y();\n}\n" +
14033
			"  void foo() {\n" +
14034
			"      if (getY().o == null && this.o.hashCode() == 0) return;\n" +
14035
			"      if (getX().o == null && this.o.hashCode() == 0) return;\n" +
14036
			"  }\n" +
14037
			"}\n" +
14038
			"class Y{\n" +
14039
			"	static Object o;\n" +
14040
			"}\n"},
14041
		null,
14042
		compilerOptions,
14043
		"----------\n" +
14044
		"1. ERROR in X.java (at line 9)\n" + 
14045
		"	if (getX().o == null && this.o.hashCode() == 0) return;\n" + 
14046
		"	                             ^\n" + 
14047
		"Potential null pointer access: The field o may be null at this location\n" + 
14048
		"----------\n",
14049
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
14050
}
14051
14052
// null analysis -- test field analysis in case of more than 64 fields
14053
public void testBug247564g() {
14054
	Map compilerOptions = getCompilerOptions();
14055
	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
14056
	this.runNegativeTest(
14057
		false,
14058
		new String[] {
14059
			"X.java",
14060
			"public class X {\n" +
14061
			"Object field0, \n" +
14062
			"field1, field2, field3, field4, \n" +
14063
			"field5, field6, field7, field8, \n" +
14064
			"field9, field10, field11, field12, \n" +
14065
			"field13, field14, field15, field16, \n" +
14066
			"field17, field18, field19, field20, \n" +
14067
			"field21, field22, field23, field24, \n" +
14068
			"field25, field26, field27, field28, \n" +
14069
			"field29, field30, field31, field32, \n" +
14070
			"field33, field34, field35, field36, \n" +
14071
			"field37, field38, field39, field40, \n" +
14072
			"field41, field42, field43, field44, \n" +
14073
			"field45, field46, field47, field48, \n" +
14074
			"field49, field50, field51, field52, \n" +
14075
			"field53, field54, field55, field56, \n" +
14076
			"field57, field58, field59, field60, \n" +
14077
			"field61, field62, field63, field64, \n" +
14078
			"field65, field66, field67, field68, \n" +
14079
			"field69, field70, field71, field72, \n" +
14080
			"field73, field74, field75, field76, \n" +
14081
			"field77, field78, field79, field80, \n" +
14082
			"field81, field82, field83, field84, \n" +
14083
			"field85, field86, field87, field88, \n" +
14084
			"field89, field90, field91, field92, \n" +
14085
			"field93, field94, field95, field96, \n" +
14086
			"field97, field98, field99;\n" +
14087
			"static final Object field100 = null;\n" +
14088
			"  void foo() {\n" +
14089
			"	int i = 0;" +
14090
			"   while (i<10){\n" +
14091
			"      i++;\n" +
14092
			"      if (this.field99 == null && this.field99.hashCode() == 0){}\n" +
14093
			"	   this.field98 = null;\n" +
14094
			"	}\n" +
14095
			"	if (this.field98.hashCode() == 0) {}\n" +	// should not complain
14096
			"	this.field97 = null;\n" +
14097
			"	if (this.field97.hashCode() == 0) {}\n" +
14098
			"	if (this.field100.hashCode() == 0) {}\n" +
14099
			"  }\n" +
14100
			"}"},
14101
		null,
14102
		compilerOptions,
14103
		"----------\n" +
14104
		"1. ERROR in X.java (at line 32)\n" + 
14105
		"	if (this.field99 == null && this.field99.hashCode() == 0){}\n" + 
14106
		"	                                 ^^^^^^^\n" + 
14107
		"Potential null pointer access: The field field99 may be null at this location\n" + 
14108
		"----------\n" + 
14109
		"2. ERROR in X.java (at line 37)\n" + 
14110
		"	if (this.field97.hashCode() == 0) {}\n" + 
14111
		"	         ^^^^^^^\n" + 
14112
		"Potential null pointer access: The field field97 may be null at this location\n" + 
14113
		"----------\n" + 
14114
		"3. ERROR in X.java (at line 38)\n" + 
14115
		"	if (this.field100.hashCode() == 0) {}\n" + 
14116
		"	         ^^^^^^^^\n" + 
14117
		"Null pointer access: The field field100 can only be null at this location\n" + 
14118
		"----------\n",
14119
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
14120
}
14121
14122
// null analysis -- simple case for field for inner class
14123
// to make sure field id's of inner and outer classes are not same for flow analysis
14124
public void testBug247564h() {
14125
	this.runNegativeTest(
14126
		new String[] {
14127
			"X.java",
14128
			"public class X {\n" +
14129
			"  Object o;\n" +
14130
			"  class X1 {\n" +
14131
			"	 Object x;" +
14132
			"	 Object x1;" +
14133
			"	 Object x2;" +
14134
			"	 void goo() {\n" +
14135
			"    	if (o == null && x.toString() == \"\"){}\n" +
14136
			"	 	if (o2 == null && o2.toString() == \"\"){}\n" +
14137
			"	 	if (o2 == null && x2.toString() == \"\"){}\n" +
14138
			"    }\n" +
14139
			
14140
			"  }\n" +
14141
			"  Object o1;\n" +
14142
			"  static Object o2;\n" +
14143
			"}\n"},
14144
		"----------\n" + 
14145
		"1. ERROR in X.java (at line 6)\n" + 
14146
		"	if (o2 == null && o2.toString() == \"\"){}\n" + 
14147
		"	                  ^^\n" + 
14148
		"Potential null pointer access: The field o2 may be null at this location\n" + 
14149
		"----------\n"
14150
	);
14151
}
14152
14153
// null analysis -- simple case for field for inner class
14154
// to make sure that id's of local variables in inner classes dotn conflict with those of fields.
14155
public void testBug247564h_1() {
14156
	this.runNegativeTest(
14157
		new String[] {
14158
			"X.java",
14159
			"public class X {\n" +
14160
			"  Object field0;\n" +
14161
			"  Object field1;\n" +
14162
			"  class X1 {\n" +
14163
			"	 Object field2;" +
14164
			"	 Object field3;" +
14165
			"	 void goo(Object var) {\n" +
14166
			"    	if (var == null && field3.toString() == \"\"){}\n" +
14167
			"    	if (field3 == null && field3.toString() == \"\"){}\n" +
14168
			"    }\n" +
14169
			"  }\n" +
14170
			"}\n"},
14171
		"----------\n" + 
14172
		"1. ERROR in X.java (at line 7)\n" + 
14173
		"	if (field3 == null && field3.toString() == \"\"){}\n" + 
14174
		"	                      ^^^^^^\n" + 
14175
		"Potential null pointer access: The field field3 may be null at this location\n" + 
14176
		"----------\n"
14177
	);
14178
}
14179
14180
// null analysis -- simple case for field for inner class
14181
// to make sure that id's of local variables in inner classes dotn conflict with those of fields.
14182
public void testBug247564h_2() {
14183
	this.runNegativeTest(
14184
		new String[] {
14185
			"X.java",
14186
			"public class X {\n" +
14187
			"  Object field0;\n" +
14188
			"  Object field1;\n" +
14189
			"  class X1 {\n" +
14190
			"	 class X2 {\n" +
14191
			"	 Object field3;\n" +
14192
			"	 void goo(Object var) {\n" +
14193
			"    	if (var == null && field3.toString() == \"\"){}\n" +
14194
			"    	if (field3 == null && field3.toString() == \"\"){}\n" +
14195
			"    	if (field3 == null && field1.toString() == \"\"){}\n" +
14196
			"    }\n" +
14197
			"    }\n" +
14198
			"  Object field2;\n" +
14199
			"  }\n" +
14200
			"}\n"},
14201
		"----------\n" + 
14202
		"1. ERROR in X.java (at line 9)\n" + 
14203
		"	if (field3 == null && field3.toString() == \"\"){}\n" + 
14204
		"	                      ^^^^^^\n" + 
14205
		"Potential null pointer access: The field field3 may be null at this location\n" + 
14206
		"----------\n"
14207
	);
14208
}
13676
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 
14209
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 
13677
// Dead Code detection removing code that isn't dead
14210
// Dead Code detection removing code that isn't dead
13678
public void testBug332637() {
14211
public void testBug332637() {

Return to bug 247564