Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 188023 Details for
Bug 247564
[compiler][null] Detecting null field reference
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
proposed fix v1.2.1 + regression tests
patch1feb.txt (text/plain), 178.10 KB, created by
Ayushman Jain
on 2011-02-01 01:17:09 EST
(
hide
)
Description:
proposed fix v1.2.1 + regression tests
Filename:
MIME Type:
Creator:
Ayushman Jain
Created:
2011-02-01 01:17:09 EST
Size:
178.10 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jdt.core >Index: compiler/org/eclipse/jdt/core/compiler/IProblem.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java,v >retrieving revision 1.225 >diff -u -r1.225 IProblem.java >--- compiler/org/eclipse/jdt/core/compiler/IProblem.java 16 Jan 2011 22:43:21 -0000 1.225 >+++ compiler/org/eclipse/jdt/core/compiler/IProblem.java 1 Feb 2011 05:32:30 -0000 >@@ -1245,6 +1245,26 @@ > /** @since 3.4 */ > int UnusedTypeArgumentsForConstructorInvocation = MethodRelated + 660; > >+ /** >+ * Null analysis for fields >+ */ >+ /** @since 3.7 */ >+ int NullFieldReference = Internal + FieldRelated + 670; >+ /** @since 3.7 */ >+ int PotentialNullFieldReference = Internal + FieldRelated + 671; >+ /** @since 3.7 */ >+ int RedundantNullCheckOnNullField = Internal + FieldRelated + 672; >+ /** @since 3.7 */ >+ int NullFieldComparisonYieldsFalse = Internal + FieldRelated + 673; >+ /** @since 3.7 */ >+ int RedundantNullCheckOnNonNullField = Internal + FieldRelated + 674; >+ /** @since 3.7 */ >+ int NonNullFieldComparisonYieldsFalse = Internal + FieldRelated + 675; >+ /** @since 3.7 */ >+ int RedundantFieldNullAssignment = Internal + FieldRelated + 676; >+ /** @since 3.7 */ >+ int NullFieldInstanceofYieldsFalse = Internal + FieldRelated + 677; >+ > /** > * Corrupted binaries > */ >Index: compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java,v >retrieving revision 1.95 >diff -u -r1.95 Assignment.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 22 Jan 2011 23:39:25 -0000 1.95 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 1 Feb 2011 05:32:30 -0000 >@@ -40,7 +40,7 @@ > // record setting a variable: various scenarii are possible, setting an array reference, > // a field reference, a blank final field reference, a field of an enclosing instance or > // just a local variable. >- LocalVariableBinding local = this.lhs.localVariableBinding(); >+ VariableBinding local = this.lhs.variableBinding(); > if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) { > this.expression.checkNPE(currentScope, flowContext, flowInfo); > } >@@ -59,6 +59,12 @@ > flowInfo.markNullStatus(local, nullStatus); > if (flowContext.initsOnFinally != null) > flowContext.initsOnFinally.markNullStatus(local, nullStatus); >+ if (local instanceof FieldBinding && local.isFinal() && ((FieldBinding) local).isStatic()) { >+ // static final field being assigned. Record its null status for future reference >+ // since the flowInfo from a constructor or static block wont be available in a method >+ FieldBinding fieldBinding = (FieldBinding) local; >+ fieldBinding.setNullStatusForStaticFinalField(nullStatus); >+ } > } > return flowInfo; > } >@@ -208,4 +214,7 @@ > public LocalVariableBinding localVariableBinding() { > return this.lhs.localVariableBinding(); > } >+public VariableBinding variableBinding() { >+ return this.lhs.variableBinding(); >+} > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/Block.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java,v >retrieving revision 1.43 >diff -u -r1.43 Block.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/Block.java 14 Oct 2009 18:08:37 -0000 1.43 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/Block.java 1 Feb 2011 05:32:30 -0000 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2009 IBM Corporation and others. >+ * Copyright (c) 2000, 2010 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -36,6 +36,8 @@ > flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo); > } > } >+ // don't let the flow info collected for fields from this block persist. >+ flowInfo.resetNullInfoForFields(); > return flowInfo; > } > /** >Index: compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java,v >retrieving revision 1.137 >diff -u -r1.137 CastExpression.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java 17 Dec 2010 06:40:12 -0000 1.137 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java 1 Feb 2011 05:32:30 -0000 >@@ -32,6 +32,7 @@ > import org.eclipse.jdt.internal.compiler.lookup.TagBits; > import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; > import org.eclipse.jdt.internal.compiler.lookup.TypeIds; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; > > public class CastExpression extends Expression { >@@ -444,6 +445,13 @@ > return this.expression.localVariableBinding(); > } > >+/** >+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#variableBinding() >+ */ >+public VariableBinding variableBinding() { >+ return this.expression.variableBinding(); >+} >+ > public int nullStatus(FlowInfo flowInfo) { > return this.expression.nullStatus(flowInfo); > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java,v >retrieving revision 1.81 >diff -u -r1.81 EqualExpression.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java 15 Sep 2010 16:10:50 -0000 1.81 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java 1 Feb 2011 05:32:30 -0000 >@@ -24,23 +24,23 @@ > } > private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) { > >- LocalVariableBinding local = this.left.localVariableBinding(); >+ VariableBinding local = this.left.variableBinding(); > if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { > checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, this.right.nullStatus(flowInfo), this.left); > } >- local = this.right.localVariableBinding(); >+ local = this.right.variableBinding(); > if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { > checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, this.left.nullStatus(flowInfo), this.right); > } > } >- private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) { >+ private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, VariableBinding local, int nullStatus, Expression reference) { > switch (nullStatus) { > case FlowInfo.NULL : > if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { > flowContext.recordUsingNullReference(scope, local, reference, > FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo); > initsWhenTrue.markAsComparedEqualToNull(local); // from thereon it is set >- initsWhenFalse.markAsComparedEqualToNonNull(local); // from thereon it is set >+ initsWhenFalse.markAsComparedEqualToNonNull(local ); // from thereon it is set > } else { > flowContext.recordUsingNullReference(scope, local, reference, > FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo); >Index: compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java,v >retrieving revision 1.133 >diff -u -r1.133 Expression.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 17 Jan 2011 08:05:01 -0000 1.133 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 1 Feb 2011 05:32:30 -0000 >@@ -35,6 +35,7 @@ > import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; > import org.eclipse.jdt.internal.compiler.lookup.TypeIds; > import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; > import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement; > import org.eclipse.jdt.internal.compiler.util.Messages; >@@ -506,14 +507,14 @@ > * @param flowInfo the upstream flow info; caveat: may get modified > */ > public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) { >- LocalVariableBinding local = localVariableBinding(); >+ VariableBinding local = variableBinding(); > if (local != null && > (local.type.tagBits & TagBits.IsBaseType) == 0) { > if ((this.bits & ASTNode.IsNonNull) == 0) { > flowContext.recordUsingNullReference(scope, local, this, > FlowContext.MAY_NULL, flowInfo); > } >- flowInfo.markAsComparedEqualToNonNull(local); >+ flowInfo.markAsComparedEqualToNonNull(local ); > // from thereon it is set > if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) { > flowInfo.markedAsNullOrNonNullInAssertExpression(local); >@@ -849,7 +850,7 @@ > this.constant != null && this.constant != Constant.NotAConstant) > return FlowInfo.NON_NULL; // constant expression cannot be null > >- LocalVariableBinding local = localVariableBinding(); >+ VariableBinding local = variableBinding(); > if (local != null) > return flowInfo.nullStatus(local); > return FlowInfo.NON_NULL; >@@ -1055,4 +1056,12 @@ > public void traverse(ASTVisitor visitor, ClassScope scope) { > // nothing to do > } >+ >+/** >+ * Returns the field or local variable referenced by this node. Can be a direct reference (SingleNameReference) >+ * or thru a cast expression etc... >+ */ >+public VariableBinding variableBinding() { >+ return null; >+} > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java,v >retrieving revision 1.102 >diff -u -r1.102 FieldDeclaration.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java 5 Jan 2011 19:57:26 -0000 1.102 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java 1 Feb 2011 05:32:30 -0000 >@@ -74,6 +74,13 @@ > .analyseCode(initializationScope, flowContext, flowInfo) > .unconditionalInits(); > flowInfo.markAsDefinitelyAssigned(this.binding); >+ if (this.binding.isFinal() && this.binding.isStatic()) { >+ int nullStatus = this.initialization.nullStatus(flowInfo); >+ // static final field being initialized. Record its null status for future reference >+ // since the flowInfo from an initialization wont be available in a method >+ >+ this.binding.setNullStatusForStaticFinalField(nullStatus); >+ } > } > return flowInfo; > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java,v >retrieving revision 1.131 >diff -u -r1.131 FieldReference.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 17 Dec 2010 09:38:55 -0000 1.131 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 1 Feb 2011 05:32:30 -0000 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2010 IBM Corporation and others. >+ * Copyright (c) 2000, 2011 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -35,6 +35,7 @@ > import org.eclipse.jdt.internal.compiler.lookup.TagBits; > import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; > import org.eclipse.jdt.internal.compiler.lookup.TypeIds; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > > public class FieldReference extends Reference implements InvocationSite { > >@@ -668,4 +669,18 @@ > } > visitor.endVisit(this, scope); > } >+ >+public VariableBinding variableBinding() { >+ if (this.receiver.isThis() || this.binding.isStatic()) { >+ if (this.receiver instanceof MessageSend) { >+ if (((MessageSend) this.receiver).actualReceiverType == this.receiver.resolvedType) { >+ return this.binding; >+ } >+ } else { >+ return this.binding; >+ } >+ } >+ return super.variableBinding(); >+} >+ > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java,v >retrieving revision 1.62 >diff -u -r1.62 InstanceOfExpression.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java 15 Sep 2010 16:10:51 -0000 1.62 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java 1 Feb 2011 05:32:30 -0000 >@@ -31,16 +31,16 @@ > } > > public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { >- LocalVariableBinding local = this.expression.localVariableBinding(); >- if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { >+ VariableBinding variable = this.expression.variableBinding(); >+ if (variable != null && (variable.type.tagBits & TagBits.IsBaseType) == 0) { > flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo). > unconditionalInits(); > FlowInfo initsWhenTrue = flowInfo.copy(); >- initsWhenTrue.markAsComparedEqualToNonNull(local); >+ initsWhenTrue.markAsComparedEqualToNonNull(variable ); > if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) { >- initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local); >+ initsWhenTrue.markedAsNullOrNonNullInAssertExpression(variable); > } >- flowContext.recordUsingNullReference(currentScope, local, >+ flowContext.recordUsingNullReference(currentScope, variable, > this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo); > // no impact upon enclosing try context > return FlowInfo.conditional(initsWhenTrue, flowInfo.copy()); >Index: compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java,v >retrieving revision 1.151 >diff -u -r1.151 MessageSend.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 16 Jan 2011 22:43:21 -0000 1.151 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 1 Feb 2011 05:32:30 -0000 >@@ -95,6 +95,9 @@ > // NullReferenceTest#test0510 > } > manageSyntheticAccessIfNecessary(currentScope, flowInfo); >+ // a method call can result in changed values for fields, >+ // so wipe out null info for fields collected till now. >+ flowInfo.resetNullInfoForFields(); > return flowInfo; > } > /** >Index: compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java,v >retrieving revision 1.129 >diff -u -r1.129 SingleNameReference.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 17 Dec 2010 09:38:55 -0000 1.129 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 1 Feb 2011 05:32:30 -0000 >@@ -807,6 +807,15 @@ > return null; > } > >+public VariableBinding variableBinding() { >+ switch (this.bits & ASTNode.RestrictiveFlagMASK) { >+ case Binding.FIELD : >+ // reading a field >+ case Binding.LOCAL : // reading a local variable >+ return (VariableBinding) this.binding; >+ } >+ return null; >+} > public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { > //If inlinable field, forget the access emulation, the code gen will directly target it > if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) { >@@ -859,11 +868,10 @@ > } > switch (this.bits & ASTNode.RestrictiveFlagMASK) { > case Binding.FIELD : // reading a field >- return FlowInfo.UNKNOWN; > case Binding.LOCAL : // reading a local variable >- LocalVariableBinding local = (LocalVariableBinding) this.binding; >- if (local != null) >- return flowInfo.nullStatus(local); >+ VariableBinding variable = (VariableBinding) this.binding; >+ if (variable != null) >+ return flowInfo.nullStatus(variable); > } > return FlowInfo.NON_NULL; // never get there > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java,v >retrieving revision 1.51 >diff -u -r1.51 Statement.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java 22 Jan 2011 23:39:25 -0000 1.51 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java 1 Feb 2011 05:32:30 -0000 >@@ -56,7 +56,7 @@ > public static final int COMPLAINED_UNREACHABLE = 2; > > /** Empty hook for checking null status against declaration using null annotations, once this will be supported. */ >-protected int checkAgainstNullAnnotation(BlockScope currentScope, LocalVariableBinding local, int nullStatus) { >+protected int checkAgainstNullAnnotation(BlockScope currentScope, VariableBinding local, int nullStatus) { > return nullStatus; > } > >Index: compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java,v >retrieving revision 1.165 >diff -u -r1.165 TypeDeclaration.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java 5 Jan 2011 19:57:26 -0000 1.165 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java 1 Feb 2011 05:32:30 -0000 >@@ -43,6 +43,7 @@ > public MethodScope staticInitializerScope; > public boolean ignoreFurtherInvestigation = false; > public int maxFieldCount; >+// public int maxFieldCountForFlowInfo; // cumulative count of fields in this type and enclosing types > public int declarationSourceStart; > public int declarationSourceEnd; > public int bodyStart; >@@ -59,6 +60,7 @@ > > // 1.5 support > public TypeParameter[] typeParameters; >+ private int maxFieldCountForFlowInfo; > > public TypeDeclaration(CompilationResult compilationResult){ > this.compilationResult = compilationResult; >@@ -198,8 +200,27 @@ > localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType)); > } > manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); >+ >+ >+ >+// if (this.enclosingType != null) { >+// this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount; >+// } else { >+// this.maxFieldCountForFlowInfo = this.maxFieldCount; >+// } > updateMaxFieldCount(); // propagate down the max field count >- internalAnalyseCode(flowContext, flowInfo); >+ >+// if ((this.binding.tagBits & ASTNode.IsLocalType) != 0) { >+// // non-anonymous local type can declare its fields. So change the cumulativeFieldCount >+// UnconditionalFlowInfo unconFlowInfo = flowInfo.unconditionalInits(); >+// int tempCount = unconFlowInfo.maxFieldCount; >+// unconFlowInfo.maxFieldCount = this.scope.cumulativeFieldCount; >+// internalAnalyseCode(flowContext, flowInfo); >+// unconFlowInfo.maxFieldCount = tempCount; >+// } else { >+ >+ internalAnalyseCode(flowContext, flowInfo); >+// } > } catch (AbortType e) { > this.ignoreFurtherInvestigation = true; > } >@@ -214,6 +235,13 @@ > if (this.ignoreFurtherInvestigation) > return; > try { >+ >+ >+// if (this.enclosingType == null) { >+// this.maxFieldCountForFlowInfo = this.maxFieldCount; >+// } else { >+// this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount; >+// } > // propagate down the max field count > updateMaxFieldCount(); > internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount)); >@@ -236,8 +264,22 @@ > localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType)); > } > manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); >+ >+ >+ >+// if (this.enclosingType == null) { >+// this.maxFieldCountForFlowInfo = this.maxFieldCount; >+// } else { >+// this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount; >+// } > updateMaxFieldCount(); // propagate down the max field count >+ //flowInfo.unconditionalInits().maxFieldCount = this.maxFieldCountForFlowInfo; >+ UnconditionalFlowInfo unconFlowInfo = flowInfo.unconditionalInits(); >+ //int tempCount = unconFlowInfo.maxFieldCount; >+ //unconFlowInfo.maxFieldCount = this.scope.cumulativeFieldCount; > internalAnalyseCode(flowContext, flowInfo); >+ //flowInfo.resetNullInfoForFields(); >+ //unconFlowInfo.maxFieldCount = tempCount; > } catch (AbortType e) { > this.ignoreFurtherInvestigation = true; > } >@@ -251,6 +293,11 @@ > if (this.ignoreFurtherInvestigation) > return; > try { >+// if (this.enclosingType == null) { >+// this.maxFieldCountForFlowInfo = this.maxFieldCount; >+// } else { >+// this.maxFieldCountForFlowInfo = this.enclosingType.maxFieldCountForFlowInfo + this.maxFieldCount; >+// } > internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount)); > } catch (AbortType e) { > this.ignoreFurtherInvestigation = true; >@@ -646,7 +693,7 @@ > // branch, since the previous initializer already got the blame. > if (staticFieldInfo == FlowInfo.DEAD_END) { > this.staticInitializerScope.problemReporter().initializerMustCompleteNormally(field); >- staticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE); >+ staticFieldInfo = FlowInfo.initial(this.scope.cumulativeFieldCount).setReachMode(FlowInfo.UNREACHABLE); > } > } else { > if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0) >@@ -662,7 +709,7 @@ > // branch, since the previous initializer already got the blame. > if (nonStaticFieldInfo == FlowInfo.DEAD_END) { > this.initializerScope.problemReporter().initializerMustCompleteNormally(field); >- nonStaticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE); >+ nonStaticFieldInfo = FlowInfo.initial(this.scope.cumulativeFieldCount).setReachMode(FlowInfo.UNREACHABLE); > } > } > } >@@ -678,7 +725,10 @@ > } > if (this.methods != null) { > UnconditionalFlowInfo outerInfo = flowInfo.unconditionalFieldLessCopy(); >- FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo); >+ boolean isLocal = (this.binding.tagBits & ASTNode.IsLocalType) != 0; >+ //int fieldOffset = isLocal ? this.scope.cumulativeFieldCount : this.maxFieldCount; >+ //int fieldStart = isLocal ? this.scope.localTypeFieldIdStart : 0; >+ FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations(0).addInitializationsFrom(outerInfo); > for (int i = 0, count = this.methods.length; i < count; i++) { > AbstractMethodDeclaration method = this.methods[i]; > if (method.ignoreFurtherInvestigation) >@@ -688,7 +738,7 @@ > method.analyseCode( > this.scope, > staticInitializerContext, >- staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo)); >+ staticFieldInfo.unconditionalInits().discardNonFieldInitializations(0).addInitializationsFrom(outerInfo)); > } else { // constructor > ((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode()); > } >@@ -1042,11 +1092,23 @@ > this.typeParameters[i].resolve(this.scope); > } > } >- if (this.memberTypes != null) { >- for (int i = 0, count = this.memberTypes.length; i < count; i++) { >- this.memberTypes[i].resolve(this.scope); >- } >- } >+ >+ // field count from supertypes should be included in maxFieldCount, >+ // so that a field from supertype doesn't end up with same id as a local variable >+ // in a method being analyzed. >+ int superFieldsCount = 0; >+ ReferenceBinding superClassBinding = sourceType.superclass; >+ while (superClassBinding != null) { >+ FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields(); >+ if (unResolvedFields != null) { >+ superFieldsCount += unResolvedFields.length; >+ } >+ superFieldsCount += findFieldCountFromSuperInterfaces(superClassBinding.superInterfaces()); >+ superClassBinding = superClassBinding.superclass(); >+ } >+ ReferenceBinding[] superInterfacesBinding = this.binding.superInterfaces; >+ superFieldsCount += findFieldCountFromSuperInterfaces(superInterfacesBinding); >+ this.scope.cumulativeFieldCount += superFieldsCount; > if (this.fields != null) { > for (int i = 0, count = this.fields.length; i < count; i++) { > FieldDeclaration field = this.fields[i]; >@@ -1067,6 +1129,7 @@ > this.ignoreFurtherInvestigation = true; > continue; > } >+ field.binding.id += superFieldsCount; > if (needSerialVersion > && ((fieldBinding.modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal)) == (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal)) > && CharOperation.equals(TypeConstants.SERIALVERSIONUID, fieldBinding.name) >@@ -1084,9 +1147,25 @@ > field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope); > } > } >- if (this.maxFieldCount < localMaxFieldCount) { >- this.maxFieldCount = localMaxFieldCount; >+ >+// if (this.maxFieldCount < localMaxFieldCount) { >+// this.maxFieldCount = localMaxFieldCount; >+// } >+ this.maxFieldCount = this.scope.cumulativeFieldCount; >+ if (this.memberTypes != null) { >+ for (int i = 0, count = this.memberTypes.length; i < count; i++) { >+ this.memberTypes[i].resolve(this.scope); >+ } > } >+// if (this.memberTypes != null) { >+// for (int i = 0, count = this.memberTypes.length; i < count; i++) { >+// this.memberTypes[i].maxFieldCount += this.maxFieldCount; >+// } >+// } >+ >+// if (this.enclosingType != null) >+// this.maxFieldCount += this.enclosingType.maxFieldCount; >+ > if (needSerialVersion) { > //check that the current type doesn't extend javax.rmi.CORBA.Stub > TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4); >@@ -1173,6 +1252,17 @@ > } > } > >+private int findFieldCountFromSuperInterfaces(ReferenceBinding[] superinterfaces) { >+ int numOfFields = 0; >+ if (superinterfaces == null) >+ return numOfFields ; >+ for (int i = 0; i < superinterfaces.length; i++) { >+ numOfFields += superinterfaces[i].fieldCount(); >+ numOfFields += findFieldCountFromSuperInterfaces(superinterfaces[i].superInterfaces()); >+ } >+ return numOfFields; >+} >+ > /** > * Resolve a local type declaration > */ >@@ -1449,8 +1539,30 @@ > } else { > this.maxFieldCount = outerMostType.maxFieldCount; // down > } >+ > } > >+//int getMaxFieldCountForFlowInfo() { >+// int maxFieldCountForFlowInfo = 0; >+// if (this.binding == null) >+// return maxFieldCountForFlowInfo; // error scenario >+// ReferenceBinding superClassBinding = this.binding.superclass; >+// while (superClassBinding != null) { >+// FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields(); >+// if (unResolvedFields != null) { >+// this.maxFieldCount += unResolvedFields.length; >+// } >+// superClassBinding = superClassBinding.superclass(); >+// } >+// ReferenceBinding[] superInterfacesBinding = this.binding.superInterfaces; >+// maxFieldCountForFlowInfo += findFieldCountFromSuperInterfaces(superInterfacesBinding); >+// if (this.enclosingType != null) { >+// maxFieldCountForFlowInfo += this.enclosingType.maxFieldCount; >+// } >+// return maxFieldCountForFlowInfo; >+// >+//} >+ > /** > * Returns whether the type is a secondary one or not. > */ >Index: compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java,v >retrieving revision 1.33 >diff -u -r1.33 ConditionalFlowInfo.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 16 Dec 2010 13:02:30 -0000 1.33 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 1 Feb 2011 05:32:30 -0000 >@@ -13,6 +13,7 @@ > > import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; > import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > > /** > * Record conditional initialization status during definite assignment analysis >@@ -85,17 +86,17 @@ > && this.initsWhenFalse.isDefinitelyAssigned(local); > } > >-public boolean isDefinitelyNonNull(LocalVariableBinding local) { >+public boolean isDefinitelyNonNull(VariableBinding local) { > return this.initsWhenTrue.isDefinitelyNonNull(local) > && this.initsWhenFalse.isDefinitelyNonNull(local); > } > >-public boolean isDefinitelyNull(LocalVariableBinding local) { >+public boolean isDefinitelyNull(VariableBinding local) { > return this.initsWhenTrue.isDefinitelyNull(local) > && this.initsWhenFalse.isDefinitelyNull(local); > } > >-public boolean isDefinitelyUnknown(LocalVariableBinding local) { >+public boolean isDefinitelyUnknown(VariableBinding local) { > return this.initsWhenTrue.isDefinitelyUnknown(local) > && this.initsWhenFalse.isDefinitelyUnknown(local); > } >@@ -110,37 +111,37 @@ > || this.initsWhenFalse.isPotentiallyAssigned(local); > } > >-public boolean isPotentiallyNonNull(LocalVariableBinding local) { >+public boolean isPotentiallyNonNull(VariableBinding local) { > return this.initsWhenTrue.isPotentiallyNonNull(local) > || this.initsWhenFalse.isPotentiallyNonNull(local); > } > >-public boolean isPotentiallyNull(LocalVariableBinding local) { >+public boolean isPotentiallyNull(VariableBinding local) { > return this.initsWhenTrue.isPotentiallyNull(local) > || this.initsWhenFalse.isPotentiallyNull(local); > } > >-public boolean isPotentiallyUnknown(LocalVariableBinding local) { >+public boolean isPotentiallyUnknown(VariableBinding local) { > return this.initsWhenTrue.isPotentiallyUnknown(local) > || this.initsWhenFalse.isPotentiallyUnknown(local); > } > >-public boolean isProtectedNonNull(LocalVariableBinding local) { >+public boolean isProtectedNonNull(VariableBinding local) { > return this.initsWhenTrue.isProtectedNonNull(local) > && this.initsWhenFalse.isProtectedNonNull(local); > } > >-public boolean isProtectedNull(LocalVariableBinding local) { >+public boolean isProtectedNull(VariableBinding local) { > return this.initsWhenTrue.isProtectedNull(local) > && this.initsWhenFalse.isProtectedNull(local); > } > >-public void markAsComparedEqualToNonNull(LocalVariableBinding local) { >+public void markAsComparedEqualToNonNull(VariableBinding local) { > this.initsWhenTrue.markAsComparedEqualToNonNull(local); > this.initsWhenFalse.markAsComparedEqualToNonNull(local); > } > >-public void markAsComparedEqualToNull(LocalVariableBinding local) { >+public void markAsComparedEqualToNull(VariableBinding local) { > this.initsWhenTrue.markAsComparedEqualToNull(local); > this.initsWhenFalse.markAsComparedEqualToNull(local); > } >@@ -155,37 +156,42 @@ > this.initsWhenFalse.markAsDefinitelyAssigned(local); > } > >-public void markAsDefinitelyNonNull(LocalVariableBinding local) { >+public void markAsDefinitelyNonNull(VariableBinding local) { > this.initsWhenTrue.markAsDefinitelyNonNull(local); > this.initsWhenFalse.markAsDefinitelyNonNull(local); > } > >-public void markAsDefinitelyNull(LocalVariableBinding local) { >+public void markAsDefinitelyNull(VariableBinding local) { > this.initsWhenTrue.markAsDefinitelyNull(local); > this.initsWhenFalse.markAsDefinitelyNull(local); > } > >-public void resetNullInfo(LocalVariableBinding local) { >+public void resetNullInfo(VariableBinding local) { > this.initsWhenTrue.resetNullInfo(local); > this.initsWhenFalse.resetNullInfo(local); > } > >-public void markPotentiallyNullBit(LocalVariableBinding local) { >+public void resetNullInfoForFields() { >+ this.initsWhenTrue.resetNullInfoForFields(); >+ this.initsWhenFalse.resetNullInfoForFields(); >+} >+ >+public void markPotentiallyNullBit(VariableBinding local) { > this.initsWhenTrue.markPotentiallyNullBit(local); > this.initsWhenFalse.markPotentiallyNullBit(local); > } > >-public void markPotentiallyNonNullBit(LocalVariableBinding local) { >+public void markPotentiallyNonNullBit(VariableBinding local) { > this.initsWhenTrue.markPotentiallyNonNullBit(local); > this.initsWhenFalse.markPotentiallyNonNullBit(local); > } > >-public void markAsDefinitelyUnknown(LocalVariableBinding local) { >+public void markAsDefinitelyUnknown(VariableBinding local) { > this.initsWhenTrue.markAsDefinitelyUnknown(local); > this.initsWhenFalse.markAsDefinitelyUnknown(local); > } > >-public void markPotentiallyUnknownBit(LocalVariableBinding local) { >+public void markPotentiallyUnknownBit(VariableBinding local) { > this.initsWhenTrue.markPotentiallyUnknownBit(local); > this.initsWhenFalse.markPotentiallyUnknownBit(local); > } >@@ -243,12 +249,12 @@ > mergedWith(this.initsWhenFalse.unconditionalInits()); > } > >-public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) { >+public void markedAsNullOrNonNullInAssertExpression(VariableBinding local) { > this.initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local); > this.initsWhenFalse.markedAsNullOrNonNullInAssertExpression(local); > } > >-public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) { >+public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding local) { > return (this.initsWhenTrue.isMarkedAsNullOrNonNullInAssertExpression(local) > || this.initsWhenFalse.isMarkedAsNullOrNonNullInAssertExpression(local)); > } >Index: compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java,v >retrieving revision 1.35 >diff -u -r1.35 FinallyFlowContext.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java 25 Feb 2010 15:27:00 -0000 1.35 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java 1 Feb 2011 05:32:30 -0000 >@@ -30,7 +30,7 @@ > VariableBinding[] finalVariables; > int assignCount; > >- LocalVariableBinding[] nullLocals; >+ VariableBinding[] nullVariables; > Expression[] nullReferences; > int[] nullCheckTypes; > int nullCount; >@@ -83,7 +83,7 @@ > // check inconsistent null checks > if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative > for (int i = 0; i < this.nullCount; i++) { >- this.parent.recordUsingNullReference(scope, this.nullLocals[i], >+ this.parent.recordUsingNullReference(scope, this.nullVariables[i], > this.nullReferences[i], this.nullCheckTypes[i], flowInfo); > } > } >@@ -91,18 +91,18 @@ > for (int i = 0; i < this.nullCount; i++) { > Expression expression = this.nullReferences[i]; > // final local variable >- LocalVariableBinding local = this.nullLocals[i]; >+ VariableBinding local = this.nullVariables[i]; > switch (this.nullCheckTypes[i]) { > case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: > case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: > if (flowInfo.isDefinitelyNonNull(local)) { > if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, expression); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, expression); >+ scope.problemReporter().variableNonNullComparedToNull(local, expression); > } > } > continue; >@@ -116,27 +116,27 @@ > switch(this.nullCheckTypes[i] & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNull(local, expression); > } > continue; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, expression); >+ scope.problemReporter().variableNullComparedToNonNull(local, expression); > } > continue; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, expression); >+ scope.problemReporter().variableRedundantNullAssignment(local, expression); > continue; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, expression); >+ scope.problemReporter().variableNullInstanceof(local, expression); > continue; > } > } else if (flowInfo.isPotentiallyNull(local)) { >@@ -144,14 +144,14 @@ > case FlowContext.IN_COMPARISON_NULL: > this.nullReferences[i] = null; > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > this.nullReferences[i] = null; > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; >@@ -160,11 +160,11 @@ > break; > case MAY_NULL: > if (flowInfo.isDefinitelyNull(local)) { >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if (flowInfo.isPotentiallyNull(local)) { >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > } > break; > default: >@@ -212,7 +212,7 @@ > return true; > } > >- public void recordUsingNullReference(Scope scope, LocalVariableBinding local, >+ public void recordUsingNullReference(Scope scope, VariableBinding local, > Expression reference, int checkType, FlowInfo flowInfo) { > if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && !flowInfo.isDefinitelyUnknown(local)) { > if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative >@@ -226,14 +226,14 @@ > if (flowInfo.cannotBeNull(local)) { > if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); > } > } else if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, reference); >+ scope.problemReporter().variableNonNullComparedToNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); >@@ -245,11 +245,11 @@ > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); >@@ -257,34 +257,34 @@ > return; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, reference); >+ scope.problemReporter().variableNullComparedToNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); > } > return; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, reference); >+ scope.problemReporter().variableRedundantNullAssignment(local, reference); > return; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, reference); >+ scope.problemReporter().variableNullInstanceof(local, reference); > return; > } > } else if (flowInfo.isPotentiallyNull(local)) { > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; >@@ -296,7 +296,7 @@ > return; > } > if (flowInfo.canOnlyBeNull(local)) { >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > break; >@@ -311,14 +311,14 @@ > if (flowInfo.isDefinitelyNonNull(local)) { > if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, reference); >+ scope.problemReporter().variableNonNullComparedToNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); >@@ -335,11 +335,11 @@ > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); >@@ -347,34 +347,34 @@ > return; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, reference); >+ scope.problemReporter().variableNullComparedToNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); > } > return; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, reference); >+ scope.problemReporter().variableRedundantNullAssignment(local, reference); > return; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, reference); >+ scope.problemReporter().variableNullInstanceof(local, reference); > return; > } > } else if (flowInfo.isPotentiallyNull(local)) { > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; >@@ -383,11 +383,11 @@ > break; > case MAY_NULL : > if (flowInfo.isDefinitelyNull(local)) { >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if (flowInfo.isPotentiallyNull(local)) { >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > if (flowInfo.isDefinitelyNonNull(local)) { >@@ -419,17 +419,17 @@ > } > } > >-protected void recordNullReference(LocalVariableBinding local, >+protected void recordNullReference(VariableBinding local, > Expression expression, int status) { > if (this.nullCount == 0) { >- this.nullLocals = new LocalVariableBinding[5]; >+ this.nullVariables = new VariableBinding[5]; > this.nullReferences = new Expression[5]; > this.nullCheckTypes = new int[5]; > } >- else if (this.nullCount == this.nullLocals.length) { >+ else if (this.nullCount == this.nullVariables.length) { > int newLength = this.nullCount * 2; >- System.arraycopy(this.nullLocals, 0, >- this.nullLocals = new LocalVariableBinding[newLength], 0, >+ System.arraycopy(this.nullVariables, 0, >+ this.nullVariables = new VariableBinding[newLength], 0, > this.nullCount); > System.arraycopy(this.nullReferences, 0, > this.nullReferences = new Expression[newLength], 0, >@@ -438,7 +438,7 @@ > this.nullCheckTypes = new int[newLength], 0, > this.nullCount); > } >- this.nullLocals[this.nullCount] = local; >+ this.nullVariables[this.nullCount] = local; > this.nullReferences[this.nullCount] = expression; > this.nullCheckTypes[this.nullCount++] = status; > } >Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java,v >retrieving revision 1.68 >diff -u -r1.68 FlowContext.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 1 Sep 2010 15:49:57 -0000 1.68 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 1 Feb 2011 05:32:30 -0000 >@@ -23,7 +23,6 @@ > import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; > import org.eclipse.jdt.internal.compiler.lookup.Binding; > import org.eclipse.jdt.internal.compiler.lookup.BlockScope; >-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; > import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; > import org.eclipse.jdt.internal.compiler.lookup.Scope; > import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; >@@ -520,7 +519,7 @@ > * combined with a context indicator (one of {@link #IN_COMPARISON_NULL}, > * {@link #IN_COMPARISON_NON_NULL}, {@link #IN_ASSIGNMENT} or {@link #IN_INSTANCEOF}) > */ >-protected void recordNullReference(LocalVariableBinding local, >+protected void recordNullReference(VariableBinding local, > Expression expression, int status) { > // default implementation: do nothing > } >@@ -563,7 +562,7 @@ > * be known at the time of calling this method (they are influenced by > * code that follows the current point) > */ >-public void recordUsingNullReference(Scope scope, LocalVariableBinding local, >+public void recordUsingNullReference(Scope scope, VariableBinding local, > Expression reference, int checkType, FlowInfo flowInfo) { > if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || > flowInfo.isDefinitelyUnknown(local)) { >@@ -575,14 +574,14 @@ > if (flowInfo.isDefinitelyNonNull(local)) { > if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, reference); >+ scope.problemReporter().variableNonNullComparedToNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); >@@ -602,11 +601,11 @@ > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); >@@ -614,34 +613,34 @@ > return; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, reference); >+ scope.problemReporter().variableNullComparedToNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); > } > return; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, reference); >+ scope.problemReporter().variableRedundantNullAssignment(local, reference); > return; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, reference); >+ scope.problemReporter().variableNullInstanceof(local, reference); > return; > } > } else if (flowInfo.isPotentiallyNull(local)) { > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; >@@ -652,11 +651,11 @@ > break; > case MAY_NULL : > if (flowInfo.isDefinitelyNull(local)) { >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if (flowInfo.isPotentiallyNull(local)) { >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; >Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java,v >retrieving revision 1.45 >diff -u -r1.45 FlowInfo.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 16 Dec 2010 13:02:30 -0000 1.45 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 1 Feb 2011 05:32:30 -0000 >@@ -17,6 +17,7 @@ > import org.eclipse.jdt.internal.compiler.ast.IfStatement; > import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; > import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > > public abstract class FlowInfo { > >@@ -79,39 +80,42 @@ > } > > /** >- * Check whether a given local variable is known to be unable to gain a definite >+ * Check whether a given field or local variable is known to be unable to gain a definite > * non null or definite null status by the use of an enclosing flow info. The > * semantics are that if the current flow info marks the variable as potentially > * unknown or else as being both potentially null and potentially non null, > * then it won't ever be promoted as definitely null or definitely non null. (It > * could still get promoted to definite unknown). >- * @param local the variable to check >- * @return true iff this flow info prevents local from being promoted to >+ * @param binding the field or local variable to check >+ * @return true iff this flow info prevents field or local from being promoted to > * definite non null or definite null against an enclosing flow info > */ >-public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) { >- return isPotentiallyUnknown(local) || >- isPotentiallyNonNull(local) && isPotentiallyNull(local); >+public boolean cannotBeDefinitelyNullOrNonNull(VariableBinding binding) { >+ return isPotentiallyUnknown(binding) || >+ isPotentiallyNonNull(binding) && isPotentiallyNull(binding); > } > > /** >- * Check whether a given local variable is known to be non null, either because >+ * Check whether a given field or local variable is known to be non null, either because > * it is definitely non null, or because is has been tested against non null. >- * @param local the variable to ckeck >- * @return true iff local cannot be null for this flow info >+ * @param binding the field or local to check >+ * @return true iff field or local cannot be null for this flow info > */ >-public boolean cannotBeNull(LocalVariableBinding local) { >- return isDefinitelyNonNull(local) || isProtectedNonNull(local); >+public boolean cannotBeNull(VariableBinding binding) { >+ return isDefinitelyNonNull(binding) || isProtectedNonNull(binding); > } > > /** >- * Check whether a given local variable is known to be null, either because it >- * is definitely null, or because is has been tested against null. >- * @param local the variable to ckeck >- * @return true iff local can only be null for this flow info >+ * Check whether a given field or local variable is known to be null, either because it >+ * is definitely null, or because is has been tested against null. Note that for fields, >+ * this method only takes compile time analysis into account and there's no >+ * guarantee of the field being definitely null during runtime >+ * since it can be modified in some other thread. >+ * @param binding the field or local to check >+ * @return true iff field or local can only be null for this flow info > */ >-public boolean canOnlyBeNull(LocalVariableBinding local) { >- return isDefinitelyNull(local) || isProtectedNull(local); >+public boolean canOnlyBeNull(VariableBinding binding) { >+ return isDefinitelyNull(binding) || isProtectedNull(binding); > } > > /** >@@ -159,25 +163,29 @@ > public abstract boolean isDefinitelyAssigned(LocalVariableBinding local); > > /** >- * Check status of definite non-null value for a given local variable. >- * @param local the variable to ckeck >- * @return true iff local is definitely non null for this flow info >+ * Check status of definite non-null value for a given field or local variable. Note that for fields, this method only >+ * takes compile time analysis into account and there's no guarantee of the field being definitely non null during runtime >+ * since it can be modified in some other thread. >+ * @param binding the field or local to check >+ * @return true iff field or local is definitely non null for this flow info > */ >- public abstract boolean isDefinitelyNonNull(LocalVariableBinding local); >+ public abstract boolean isDefinitelyNonNull(VariableBinding binding); > > /** >- * Check status of definite null value for a given local variable. >- * @param local the variable to ckeck >- * @return true iff local is definitely null for this flow info >+ * Check status of definite null value for a given field or local variable. Note that for fields, this method only >+ * takes compile time analysis into account and there's no guarantee of the field being definitely null during runtime >+ * since it can be modified in some other thread. >+ * @param binding the field or local to check >+ * @return true iff field or local is definitely null for this flow info > */ >-public abstract boolean isDefinitelyNull(LocalVariableBinding local); >+public abstract boolean isDefinitelyNull(VariableBinding binding); > > /** >- * Check status of definite unknown value for a given local variable. >- * @param local the variable to ckeck >- * @return true iff local is definitely unknown for this flow info >+ * Check status of definite unknown value for a given field or local variable. >+ * @param binding the field or local to check >+ * @return true iff field or local is definitely unknown for this flow info > */ >-public abstract boolean isDefinitelyUnknown(LocalVariableBinding local); >+public abstract boolean isDefinitelyUnknown(VariableBinding binding); > > /** > * Check status of potential assignment for a field. >@@ -191,59 +199,59 @@ > abstract public boolean isPotentiallyAssigned(LocalVariableBinding field); > > /** >- * Check status of potential null assignment for a local. Return true if there >+ * Check status of potential null assignment for a field or local. Return true if there > * is a reasonable expectation that the variable be non null at this point. >- * @param local LocalVariableBinding - the binding for the checked local >- * @return true if there is a reasonable expectation that local be non null at >+ * @param binding VariableBinding - the binding for the checked field or local >+ * @return true if there is a reasonable expectation that the field or local be non null at > * this point > */ >-public abstract boolean isPotentiallyNonNull(LocalVariableBinding local); >+public abstract boolean isPotentiallyNonNull(VariableBinding binding); > > /** >- * Check status of potential null assignment for a local. Return true if there >+ * Check status of potential null assignment for a field or local. Return true if there > * is a reasonable expectation that the variable be null at this point. This > * includes the protected null case, so as to augment diagnostics, but does not > * really check that someone deliberately assigned to null on any specific > * path >- * @param local LocalVariableBinding - the binding for the checked local >- * @return true if there is a reasonable expectation that local be null at >+ * @param binding VariableBinding - the binding for the checked field or local >+ * @return true if there is a reasonable expectation that the field or local be null at > * this point > */ >-public abstract boolean isPotentiallyNull(LocalVariableBinding local); >+public abstract boolean isPotentiallyNull(VariableBinding binding); > > /** >- * Return true if the given local may have been assigned to an unknown value. >- * @param local the local to check >- * @return true if the given local may have been assigned to an unknown value >+ * Return true if the given field or local may have been assigned to an unknown value. >+ * @param binding the field or local to check >+ * @return true if the given field or local may have been assigned to an unknown value > */ >-public abstract boolean isPotentiallyUnknown(LocalVariableBinding local); >+public abstract boolean isPotentiallyUnknown(VariableBinding binding); > > /** >- * Return true if the given local is protected by a test against a non null >+ * Return true if the given field or local is protected by a test against a non null > * value. >- * @param local the local to check >- * @return true if the given local is protected by a test against a non null >+ * @param binding the field or local to check >+ * @return true if the given field or local is protected by a test against a non null > */ >-public abstract boolean isProtectedNonNull(LocalVariableBinding local); >+public abstract boolean isProtectedNonNull(VariableBinding binding); > > /** >- * Return true if the given local is protected by a test against null. >- * @param local the local to check >- * @return true if the given local is protected by a test against null >+ * Return true if the given field or local is protected by a test against null. >+ * @param binding the field or local to check >+ * @return true if the given field or local is protected by a test against null > */ >-public abstract boolean isProtectedNull(LocalVariableBinding local); >+public abstract boolean isProtectedNull(VariableBinding binding); > > /** >- * Record that a local variable got checked to be non null. >- * @param local the checked local variable >+ * Record that a field or local variable got checked to be non null. >+ * @param binding the checked field or local variable > */ >-abstract public void markAsComparedEqualToNonNull(LocalVariableBinding local); >+abstract public void markAsComparedEqualToNonNull(VariableBinding binding); > > /** >- * Record that a local variable got checked to be null. >- * @param local the checked local variable >+ * Record that a field or local variable got checked to be null. >+ * @param binding the checked field or local variable > */ >-abstract public void markAsComparedEqualToNull(LocalVariableBinding local); >+abstract public void markAsComparedEqualToNull(VariableBinding binding); > > /** > * Record a field got definitely assigned. >@@ -251,34 +259,38 @@ > abstract public void markAsDefinitelyAssigned(FieldBinding field); > > /** >- * Record a local got definitely assigned to a non-null value. >+ * Record a field or local got definitely assigned to a non-null value. > */ >- abstract public void markAsDefinitelyNonNull(LocalVariableBinding local); >+ abstract public void markAsDefinitelyNonNull(VariableBinding binding); > > /** >- * Record a local got definitely assigned to null. >+ * Record a field or local got definitely assigned to null. > */ >- abstract public void markAsDefinitelyNull(LocalVariableBinding local); >+ abstract public void markAsDefinitelyNull(VariableBinding binding); > > /** >- * Reset all null-information about a given local. >+ * Reset all null-information about a given field or local. > */ >- abstract public void resetNullInfo(LocalVariableBinding local); >+ abstract public void resetNullInfo(VariableBinding binding); > > /** >- * Record a local may have got assigned to unknown (set the bit on existing info). >+ * variant of {@link #resetNullInfo(VariableBinding)} for resetting null info for all fields > */ >- abstract public void markPotentiallyUnknownBit(LocalVariableBinding local); >+ abstract public void resetNullInfoForFields(); >+ /** >+ * Record a field or local may have got assigned to unknown (set the bit on existing info). >+ */ >+ abstract public void markPotentiallyUnknownBit(VariableBinding binding); > > /** >- * Record a local may have got assigned to null (set the bit on existing info). >+ * Record a field or local may have got assigned to null (set the bit on existing info). > */ >- abstract public void markPotentiallyNullBit(LocalVariableBinding local); >+ abstract public void markPotentiallyNullBit(VariableBinding binding); > > /** >- * Record a local may have got assigned to non-null (set the bit on existing info). >+ * Record a field or local may have got assigned to non-null (set the bit on existing info). > */ >- abstract public void markPotentiallyNonNullBit(LocalVariableBinding local); >+ abstract public void markPotentiallyNonNullBit(VariableBinding binding); > > /** > * Record a local got definitely assigned. >@@ -286,59 +298,59 @@ > abstract public void markAsDefinitelyAssigned(LocalVariableBinding local); > > /** >- * Record a local got definitely assigned to an unknown value. >+ * Record a field or local got definitely assigned to an unknown value. > */ >-abstract public void markAsDefinitelyUnknown(LocalVariableBinding local); >+abstract public void markAsDefinitelyUnknown(VariableBinding binding); > > /** >- * Mark the null status of the given local according to the given status >- * @param local >+ * Mark the null status of the given field or local according to the given status >+ * @param binding > * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL > */ >-public void markNullStatus(LocalVariableBinding local, int nullStatus) { >+public void markNullStatus(VariableBinding binding, int nullStatus) { > switch(nullStatus) { > // definite status? > case FlowInfo.UNKNOWN : >- markAsDefinitelyUnknown(local); >+ markAsDefinitelyUnknown(binding); > break; > case FlowInfo.NULL : >- markAsDefinitelyNull(local); >+ markAsDefinitelyNull(binding); > break; > case FlowInfo.NON_NULL : >- markAsDefinitelyNonNull(local); >+ markAsDefinitelyNonNull(binding); > break; > default: > // collect potential status: >- resetNullInfo(local); >+ resetNullInfo(binding); > if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0) >- markPotentiallyUnknownBit(local); >+ markPotentiallyUnknownBit(binding); > if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) >- markPotentiallyNullBit(local); >+ markPotentiallyNullBit(binding); > if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0) >- markPotentiallyNonNullBit(local); >+ markPotentiallyNonNullBit(binding); > if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0) >- markAsDefinitelyUnknown(local); >+ markAsDefinitelyUnknown(binding); > } > } > > /** >- * Answer the null status of the given local >- * @param local >+ * Answer the null status of the given field or local >+ * @param binding > * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL > */ >-public int nullStatus(LocalVariableBinding local) { >- if (isDefinitelyUnknown(local)) >+public int nullStatus(VariableBinding binding) { >+ if (isDefinitelyUnknown(binding)) > return FlowInfo.UNKNOWN; >- if (isDefinitelyNull(local)) >+ if (isDefinitelyNull(binding)) > return FlowInfo.NULL; >- if (isDefinitelyNonNull(local)) >+ if (isDefinitelyNonNull(binding)) > return FlowInfo.NON_NULL; > int status = 0; >- if (isPotentiallyUnknown(local)) >+ if (isPotentiallyUnknown(binding)) > status |= FlowInfo.POTENTIALLY_UNKNOWN; >- if (isPotentiallyNull(local)) >+ if (isPotentiallyNull(binding)) > status |= FlowInfo.POTENTIALLY_NULL; >- if (isPotentiallyNonNull(local)) >+ if (isPotentiallyNonNull(binding)) > status |= FlowInfo.POTENTIALLY_NON_NULL; > if (status > 0) > return status; >@@ -555,12 +567,12 @@ > * where this variable is being checked against null > */ > // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448 >-abstract public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local); >+abstract public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding); > > /** > * Returns true if the local variable being checked for was marked as null or not null > * inside an assert expression due to comparison against null. > */ > //https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448 >-abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local); >+abstract public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding); > } >Index: compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java,v >retrieving revision 1.51 >diff -u -r1.51 LoopingFlowContext.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 23 Aug 2010 08:41:25 -0000 1.51 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 1 Feb 2011 05:32:30 -0000 >@@ -42,7 +42,7 @@ > VariableBinding finalVariables[]; > int assignCount = 0; > >- LocalVariableBinding[] nullLocals; >+ VariableBinding[] nullVariables; > Expression[] nullReferences; > int[] nullCheckTypes; > int nullCount; >@@ -138,7 +138,7 @@ > if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { > // check only immutable null checks on innermost looping context > for (int i = 0; i < this.nullCount; i++) { >- LocalVariableBinding local = this.nullLocals[i]; >+ VariableBinding local = this.nullVariables[i]; > Expression expression = this.nullReferences[i]; > // final local variable > switch (this.nullCheckTypes[i]) { >@@ -148,11 +148,11 @@ > this.nullReferences[i] = null; > if (this.nullCheckTypes[i] == (CAN_ONLY_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, expression); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, expression); >+ scope.problemReporter().variableNonNullComparedToNull(local, expression); > } > } > continue; >@@ -164,11 +164,11 @@ > this.nullReferences[i] = null; > if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, expression); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, expression); >+ scope.problemReporter().variableNonNullComparedToNull(local, expression); > } > } > continue; >@@ -177,11 +177,11 @@ > this.nullReferences[i] = null; > if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNull(local, expression); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, expression); >+ scope.problemReporter().variableNullComparedToNonNull(local, expression); > } > } > continue; >@@ -196,27 +196,27 @@ > switch(this.nullCheckTypes[i] & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNull(local, expression); > } > continue; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, expression); >+ scope.problemReporter().variableNullComparedToNonNull(local, expression); > } > continue; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, expression); >+ scope.problemReporter().variableRedundantNullAssignment(local, expression); > continue; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, expression); >+ scope.problemReporter().variableNullInstanceof(local, expression); > continue; > } > } else if (flowInfo.isPotentiallyNull(local)) { >@@ -224,14 +224,14 @@ > case FlowContext.IN_COMPARISON_NULL: > this.nullReferences[i] = null; > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > this.nullReferences[i] = null; > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; >@@ -241,7 +241,7 @@ > case MAY_NULL: > if (flowInfo.isDefinitelyNull(local)) { > this.nullReferences[i] = null; >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > break; >@@ -257,7 +257,7 @@ > for (int i = 0; i < this.nullCount; i++) { > Expression expression = this.nullReferences[i]; > // final local variable >- LocalVariableBinding local = this.nullLocals[i]; >+ VariableBinding local = this.nullVariables[i]; > switch (this.nullCheckTypes[i]) { > case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL: > case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL: >@@ -265,11 +265,11 @@ > this.nullReferences[i] = null; > if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, expression); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, expression); >+ scope.problemReporter().variableNonNullComparedToNull(local, expression); > } > } > continue; >@@ -284,27 +284,27 @@ > switch(this.nullCheckTypes[i] & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, expression); >+ scope.problemReporter().variableRedundantCheckOnNull(local, expression); > } > continue; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, expression); >+ scope.problemReporter().variableNullComparedToNonNull(local, expression); > } > continue; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, expression); >+ scope.problemReporter().variableRedundantNullAssignment(local, expression); > continue; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, expression); >+ scope.problemReporter().variableNullInstanceof(local, expression); > continue; > } > } else if (flowInfo.isPotentiallyNull(local)) { >@@ -312,14 +312,14 @@ > case FlowContext.IN_COMPARISON_NULL: > this.nullReferences[i] = null; > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > this.nullReferences[i] = null; > if (((this.nullCheckTypes[i] & CHECK_MASK) == CAN_ONLY_NULL) && (expression.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; >@@ -329,12 +329,12 @@ > case MAY_NULL: > if (flowInfo.isDefinitelyNull(local)) { > this.nullReferences[i] = null; >- scope.problemReporter().localVariableNullReference(local, expression); >+ scope.problemReporter().variableNullReference(local, expression); > continue; > } > if (flowInfo.isPotentiallyNull(local)) { > this.nullReferences[i] = null; >- scope.problemReporter().localVariablePotentialNullReference(local, expression); >+ scope.problemReporter().variablePotentialNullReference(local, expression); > continue; > } > break; >@@ -458,27 +458,27 @@ > return true; > } > >-protected void recordNullReference(LocalVariableBinding local, >+protected void recordNullReference(VariableBinding local, > Expression expression, int status) { > if (this.nullCount == 0) { >- this.nullLocals = new LocalVariableBinding[5]; >+ this.nullVariables = new VariableBinding[5]; > this.nullReferences = new Expression[5]; > this.nullCheckTypes = new int[5]; > } >- else if (this.nullCount == this.nullLocals.length) { >- System.arraycopy(this.nullLocals, 0, >- this.nullLocals = new LocalVariableBinding[this.nullCount * 2], 0, this.nullCount); >+ else if (this.nullCount == this.nullVariables.length) { >+ System.arraycopy(this.nullVariables, 0, >+ this.nullVariables = new VariableBinding[this.nullCount * 2], 0, this.nullCount); > System.arraycopy(this.nullReferences, 0, > this.nullReferences = new Expression[this.nullCount * 2], 0, this.nullCount); > System.arraycopy(this.nullCheckTypes, 0, > this.nullCheckTypes = new int[this.nullCount * 2], 0, this.nullCount); > } >- this.nullLocals[this.nullCount] = local; >+ this.nullVariables[this.nullCount] = local; > this.nullReferences[this.nullCount] = expression; > this.nullCheckTypes[this.nullCount++] = status; > } > >-public void recordUsingNullReference(Scope scope, LocalVariableBinding local, >+public void recordUsingNullReference(Scope scope, VariableBinding local, > Expression reference, int checkType, FlowInfo flowInfo) { > if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || > flowInfo.isDefinitelyUnknown(local)) { >@@ -490,14 +490,14 @@ > if (flowInfo.isDefinitelyNonNull(local)) { > if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNonNullComparedToNull(local, reference); >+ scope.problemReporter().variableNonNullComparedToNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); >@@ -506,21 +506,21 @@ > } else if (flowInfo.isDefinitelyNull(local)) { > if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL)) { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); > } > } else { > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, reference); >+ scope.problemReporter().variableNullComparedToNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); > } > } > } else if (this.upstreamNullFlowInfo.isDefinitelyNonNull(local) && !flowInfo.isPotentiallyNull(local)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291418 >- flowInfo.markAsDefinitelyNonNull(local); >+ flowInfo.markAsDefinitelyNonNull(local ); > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { > recordNullReference(local, reference, checkType); > } >@@ -546,11 +546,11 @@ > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableRedundantCheckOnNull(local, reference); >+ scope.problemReporter().variableRedundantCheckOnNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE); >@@ -558,34 +558,34 @@ > return; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) == 0) { >- scope.problemReporter().localVariableNullComparedToNonNull(local, reference); >+ scope.problemReporter().variableNullComparedToNonNull(local, reference); > } > if (!flowInfo.isMarkedAsNullOrNonNullInAssertExpression(local)) { > flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE); > } > return; > case FlowContext.IN_ASSIGNMENT: >- scope.problemReporter().localVariableRedundantNullAssignment(local, reference); >+ scope.problemReporter().variableRedundantNullAssignment(local, reference); > return; > case FlowContext.IN_INSTANCEOF: >- scope.problemReporter().localVariableNullInstanceof(local, reference); >+ scope.problemReporter().variableNullInstanceof(local, reference); > return; > } > } else if (flowInfo.isPotentiallyNull(local)) { > switch(checkType & CONTEXT_MASK) { > case FlowContext.IN_COMPARISON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; > case FlowContext.IN_COMPARISON_NON_NULL: > if (((checkType & CHECK_MASK) == CAN_ONLY_NULL) && (reference.implicitConversion & TypeIds.UNBOXING) != 0) { // check for auto-unboxing first and report appropriate warning >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > break; >@@ -604,11 +604,11 @@ > return; > } > if (flowInfo.isDefinitelyNull(local)) { >- scope.problemReporter().localVariableNullReference(local, reference); >+ scope.problemReporter().variableNullReference(local, reference); > return; > } > if (flowInfo.isPotentiallyNull(local)) { >- scope.problemReporter().localVariablePotentialNullReference(local, reference); >+ scope.problemReporter().variablePotentialNullReference(local, reference); > return; > } > recordNullReference(local, reference, checkType); >Index: compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java,v >retrieving revision 1.12 >diff -u -r1.12 NullInfoRegistry.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java 19 Jan 2011 05:29:54 -0000 1.12 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java 1 Feb 2011 05:32:30 -0000 >@@ -11,7 +11,8 @@ > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.flow; > >-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; >+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > > /** > * A degenerate form of UnconditionalFlowInfo explicitly meant to capture >@@ -116,13 +117,18 @@ > return this; > } > >-public void markAsComparedEqualToNonNull(LocalVariableBinding local) { >+public void markAsComparedEqualToNonNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits >+ if (position < BitCacheSize) { // use bits > // set protected non null > this.nullBit1 |= (1L << position); > if (COVERAGE_TEST_FLAG) { >@@ -161,13 +167,18 @@ > } > } > >-public void markAsDefinitelyNonNull(LocalVariableBinding local) { >+public void markAsDefinitelyNonNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { // use bits > // set assigned non null > this.nullBit3 |= (1L << position); > if (COVERAGE_TEST_FLAG) { >@@ -207,13 +218,18 @@ > } > // PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either > // PREMATURE project protected non null onto something else >-public void markAsDefinitelyNull(LocalVariableBinding local) { >+public void markAsDefinitelyNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits >+ if (position < BitCacheSize) { // use bits > // set assigned null > this.nullBit2 |= (1L << position); > if (COVERAGE_TEST_FLAG) { >@@ -252,13 +268,18 @@ > } > } > >-public void markAsDefinitelyUnknown(LocalVariableBinding local) { >+public void markAsDefinitelyUnknown(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits >+ if (position < BitCacheSize) { // use bits > // set assigned unknown > this.nullBit4 |= (1L << position); > if (COVERAGE_TEST_FLAG) { >@@ -407,13 +428,18 @@ > * Mark a local as potentially having been assigned to an unknown value. > * @param local the local to mark > */ >-public void markPotentiallyUnknownBit(LocalVariableBinding local) { >+public void markPotentiallyUnknownBit(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > mask = 1L << position; > isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$ >@@ -454,12 +480,17 @@ > } > } > >-public void markPotentiallyNullBit(LocalVariableBinding local) { >+public void markPotentiallyNullBit(VariableBinding local) { > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > mask = 1L << position; > isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$ >@@ -500,12 +531,17 @@ > } > } > >-public void markPotentiallyNonNullBit(LocalVariableBinding local) { >+public void markPotentiallyNonNullBit(VariableBinding local) { > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > mask = 1L << position; > isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$ >Index: compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java,v >retrieving revision 1.72 >diff -u -r1.72 UnconditionalFlowInfo.java >--- compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 19 Jan 2011 05:29:54 -0000 1.72 >+++ compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 1 Feb 2011 05:32:30 -0000 >@@ -18,6 +18,7 @@ > import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; > import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; > import org.eclipse.jdt.internal.compiler.lookup.TagBits; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > > /** > * Record initialization status during definite assignment analysis >@@ -515,13 +516,18 @@ > return this; > } > >-final public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) { >+final public boolean cannotBeDefinitelyNullOrNonNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > return ( > (~this.nullBit1 >@@ -546,13 +552,18 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean cannotBeNull(LocalVariableBinding local) { >+final public boolean cannotBeNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > return (this.nullBit1 & this.nullBit3 > & ((this.nullBit2 & this.nullBit4) | ~this.nullBit2) >@@ -573,13 +584,18 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean canOnlyBeNull(LocalVariableBinding local) { >+final public boolean canOnlyBeNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > return (this.nullBit1 & this.nullBit2 > & (~this.nullBit3 | ~this.nullBit4) >@@ -664,10 +680,11 @@ > * Remove local variables information from this flow info and return this. > * @return this, deprived from any local variable information > */ >-public UnconditionalFlowInfo discardNonFieldInitializations() { >+public UnconditionalFlowInfo discardNonFieldInitializations(int fieldStart) { > int limit = this.maxFieldCount; > if (limit < BitCacheSize) { > long mask = (1L << limit)-1; >+ //mask = mask & (-1L << fieldStart); > this.definiteInits &= mask; > this.potentialInits &= mask; > this.nullBit1 &= mask; >@@ -745,7 +762,13 @@ > return isDefinitelyAssigned(local.id + this.maxFieldCount); > } > >-final public boolean isDefinitelyNonNull(LocalVariableBinding local) { >+final public boolean isDefinitelyNonNull(VariableBinding local) { >+ if (local instanceof FieldBinding && (this.tagBits & NULL_FLAG_MASK) == 0) { >+ // no local yet in scope. Came here because of a field being queried for non null >+ // will only happen for final fields, since they are assigned in a constructor or static block >+ // and we may currently be in some other method >+ this.tagBits |= NULL_FLAG_MASK; >+ } > // do not want to complain in unreachable code > if ((this.tagBits & UNREACHABLE) != 0 || > (this.tagBits & NULL_FLAG_MASK) == 0) { >@@ -755,7 +778,16 @@ > local.constant() != Constant.NotAConstant) { // String instances > return true; > } >- int position = local.id + this.maxFieldCount; >+ int position; >+ if (local instanceof FieldBinding) { >+ if (local.isFinal() && ((FieldBinding)local).isStatic()) { >+ // static final field's null status may not be in the flow info >+ return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.NON_NULL); >+ } >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > if (position < BitCacheSize) { // use bits > return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4)) > & (1L << position)) != 0; >@@ -774,14 +806,29 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean isDefinitelyNull(LocalVariableBinding local) { >+final public boolean isDefinitelyNull(VariableBinding local) { >+ if (local instanceof FieldBinding && (this.tagBits & NULL_FLAG_MASK) == 0) { >+ // no local yet in scope. Came here because of a field being queried for non null >+ // will only happen for final fields, since they are assigned in a constructor or static block >+ // and we may currently be in some other method >+ this.tagBits |= NULL_FLAG_MASK; >+ } > // do not want to complain in unreachable code > if ((this.tagBits & UNREACHABLE) != 0 || > (this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } >- int position = local.id + this.maxFieldCount; >+ int position; >+ if (local instanceof FieldBinding) { >+ if (local.isFinal() && ((FieldBinding)local).isStatic()) { >+ // static final field's null status may not be in the flow info >+ return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.NULL); >+ } >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > if (position < BitCacheSize) { // use bits > return ((this.nullBit1 & this.nullBit2 > & (~this.nullBit3 | ~this.nullBit4)) >@@ -801,13 +848,18 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean isDefinitelyUnknown(LocalVariableBinding local) { >+final public boolean isDefinitelyUnknown(VariableBinding local) { > // do not want to complain in unreachable code > if ((this.tagBits & UNREACHABLE) != 0 || > (this.tagBits & NULL_FLAG_MASK) == 0) { > return false; > } >- int position = local.id + this.maxFieldCount; >+ int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > if (position < BitCacheSize) { // use bits > return ((this.nullBit1 & this.nullBit4 > & ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0; >@@ -860,13 +912,18 @@ > return isPotentiallyAssigned(local.id + this.maxFieldCount); > } > >-final public boolean isPotentiallyNonNull(LocalVariableBinding local) { >+final public boolean isPotentiallyNonNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { // use bits > // use bits > return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2)) > & (1L << position)) != 0; >@@ -885,13 +942,22 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean isPotentiallyNull(LocalVariableBinding local) { >+final public boolean isPotentiallyNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ if (local.isFinal() && ((FieldBinding)local).isStatic()) { >+ // static final field's null status may not be in the flow info >+ return (((FieldBinding) local).getNullStatusForStaticFinalField() == FlowInfo.POTENTIALLY_NULL); >+ } >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3)) > & (1L << position)) != 0; >@@ -910,13 +976,18 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean isPotentiallyUnknown(LocalVariableBinding local) { >+final public boolean isPotentiallyUnknown(VariableBinding local) { > // do not want to complain in unreachable code > if ((this.tagBits & UNREACHABLE) != 0 || > (this.tagBits & NULL_FLAG_MASK) == 0) { > return false; > } >- int position = local.id + this.maxFieldCount; >+ int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > if (position < BitCacheSize) { // use bits > return (this.nullBit4 > & (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3) >@@ -937,14 +1008,18 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean isProtectedNonNull(LocalVariableBinding local) { >+final public boolean isProtectedNonNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >- // use bits >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { // use bits > return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0; > } > // use extra vector >@@ -962,13 +1037,18 @@ > & (1L << (position % BitCacheSize))) != 0; > } > >-final public boolean isProtectedNull(LocalVariableBinding local) { >+final public boolean isProtectedNull(VariableBinding local) { > if ((this.tagBits & NULL_FLAG_MASK) == 0 || > (local.type.tagBits & TagBits.IsBaseType) != 0) { > return false; > } > int position; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > return (this.nullBit1 & this.nullBit2 > & (this.nullBit3 ^ this.nullBit4) >@@ -1001,15 +1081,21 @@ > throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$ > return expression; > } >-public void markAsComparedEqualToNonNull(LocalVariableBinding local) { >+public void markAsComparedEqualToNonNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; >+ if (local instanceof FieldBinding) { >+ this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL); >+ return; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > long mask; > long a1, a2, a3, a4, na2; > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (position < BitCacheSize) { > // use bits > if (((mask = 1L << position) > & (a1 = this.nullBit1) >@@ -1098,14 +1184,20 @@ > } > } > >-public void markAsComparedEqualToNull(LocalVariableBinding local) { >+public void markAsComparedEqualToNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL); >+ return; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > if (((mask = 1L << position) & this.nullBit1) != 0) { > if ((mask >@@ -1236,14 +1328,20 @@ > markAsDefinitelyAssigned(local.id + this.maxFieldCount); > } > >-public void markAsDefinitelyNonNull(LocalVariableBinding local) { >+public void markAsDefinitelyNonNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > long mask; > int position; >+ if (local instanceof FieldBinding) { >+ this.markNullStatus(local, FlowInfo.POTENTIALLY_NON_NULL); >+ return; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits >+ if (position < BitCacheSize) { // use bits > // set assigned non null > this.nullBit1 |= (mask = 1L << position); > this.nullBit3 |= mask; >@@ -1258,8 +1356,25 @@ > } > else { > // use extra vector >- int vectorIndex ; >- this.extra[2][vectorIndex = (position / BitCacheSize) - 1] >+ int vectorIndex = (position / BitCacheSize) - 1; >+ if (this.extra == null) { >+ int length = vectorIndex + 1; >+ this.extra = new long[extraLength][]; >+ for (int j = 0; j < extraLength; j++) { >+ this.extra[j] = new long[length]; >+ } >+ } >+ else { >+ int oldLength; // might need to grow the arrays >+ if (vectorIndex >= (oldLength = this.extra[0].length)) { >+ for (int j = 0; j < extraLength; j++) { >+ System.arraycopy(this.extra[j], 0, >+ (this.extra[j] = new long[vectorIndex + 1]), 0, >+ oldLength); >+ } >+ } >+ } >+ this.extra[2][vectorIndex] > |= (mask = 1L << (position % BitCacheSize)); > this.extra[4][vectorIndex] |= mask; > this.extra[3][vectorIndex] &= (mask = ~mask); >@@ -1273,14 +1388,20 @@ > } > } > >-public void markAsDefinitelyNull(LocalVariableBinding local) { >+public void markAsDefinitelyNull(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > long mask; > int position; >+ if (local instanceof FieldBinding) { >+ this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL); >+ return; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits >+ if (position < BitCacheSize) { // use bits > // mark assigned null > this.nullBit1 |= (mask = 1L << position); > this.nullBit2 |= mask; >@@ -1295,8 +1416,25 @@ > } > else { > // use extra vector >- int vectorIndex ; >- this.extra[2][vectorIndex = (position / BitCacheSize) - 1] >+ int vectorIndex = (position / BitCacheSize) - 1; >+ if (this.extra == null) { >+ int length = vectorIndex + 1; >+ this.extra = new long[extraLength][]; >+ for (int j = 0; j < extraLength; j++) { >+ this.extra[j] = new long[length]; >+ } >+ } >+ else { >+ int oldLength; // might need to grow the arrays >+ if (vectorIndex >= (oldLength = this.extra[0].length)) { >+ for (int j = 0; j < extraLength; j++) { >+ System.arraycopy(this.extra[j], 0, >+ (this.extra[j] = new long[vectorIndex + 1]), 0, >+ oldLength); >+ } >+ } >+ } >+ this.extra[2][vectorIndex] > |= (mask = 1L << (position % BitCacheSize)); > this.extra[3][vectorIndex] |= mask; > this.extra[4][vectorIndex] &= (mask = ~mask); >@@ -1316,14 +1454,19 @@ > */ > // PREMATURE may try to get closer to markAsDefinitelyAssigned, but not > // obvious >-public void markAsDefinitelyUnknown(LocalVariableBinding local) { >+public void markAsDefinitelyUnknown(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > long mask; > int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } > // position is zero-based >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (position < BitCacheSize) { > // use bits > // mark assigned null > this.nullBit1 |= (mask = 1L << position); >@@ -1339,8 +1482,25 @@ > } > else { > // use extra vector >- int vectorIndex ; >- this.extra[2][vectorIndex = (position / BitCacheSize) - 1] >+ int vectorIndex = (position / BitCacheSize) - 1; >+ if (this.extra == null) { >+ int length = vectorIndex + 1; >+ this.extra = new long[extraLength][]; >+ for (int j = 0; j < extraLength; j++) { >+ this.extra[j] = new long[length]; >+ } >+ } >+ else { >+ int oldLength; // might need to grow the arrays >+ if (vectorIndex >= (oldLength = this.extra[0].length)) { >+ for (int j = 0; j < extraLength; j++) { >+ System.arraycopy(this.extra[j], 0, >+ (this.extra[j] = new long[vectorIndex + 1]), 0, >+ oldLength); >+ } >+ } >+ } >+ this.extra[2][vectorIndex] > |= (mask = 1L << (position % BitCacheSize)); > this.extra[5][vectorIndex] |= mask; > this.extra[3][vectorIndex] &= (mask = ~mask); >@@ -1354,12 +1514,17 @@ > } > } > >-public void resetNullInfo(LocalVariableBinding local) { >+public void resetNullInfo(VariableBinding local) { > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > this.nullBit1 &= (mask = ~(1L << position)); > this.nullBit2 &= mask; >@@ -1381,18 +1546,54 @@ > } > } > } >+public void resetNullInfoForFields() { >+ if (this != DEAD_END) { >+ long mask; >+ if (this.maxFieldCount < BitCacheSize) { >+ // use bits >+ this.nullBit1 &= (mask = -1L << this.maxFieldCount); >+ this.nullBit2 &= mask; >+ this.nullBit3 &= mask; >+ this.nullBit4 &= mask; >+ } >+ else { >+ this.nullBit1 &= (mask = 0L); >+ this.nullBit2 &= mask; >+ this.nullBit3 &= mask; >+ this.nullBit4 &= mask; >+ if (this.extra != null){ >+ for (int position = BitCacheSize; position < this.maxFieldCount; position++) { >+ // use extra vector >+ int vectorIndex = (position / BitCacheSize) - 1; >+ if (vectorIndex >= this.extra[2].length) >+ break; // No null info about fields beyond this point in the extra vector >+ this.extra[2][vectorIndex] >+ &= (mask = ~(1L << (position % BitCacheSize))); >+ this.extra[3][vectorIndex] &= mask; >+ this.extra[4][vectorIndex] &= mask; >+ this.extra[5][vectorIndex] &= mask; >+ } >+ } >+ } >+ } >+} > > /** > * Mark a local as potentially having been assigned to an unknown value. > * @param local the local to mark > */ >-public void markPotentiallyUnknownBit(LocalVariableBinding local) { >+public void markPotentiallyUnknownBit(VariableBinding local) { > // protected from non-object locals in calling methods > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > mask = 1L << position; > isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$ >@@ -1434,12 +1635,17 @@ > } > } > >-public void markPotentiallyNullBit(LocalVariableBinding local) { >+public void markPotentiallyNullBit(VariableBinding local) { > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > mask = 1L << position; > isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$ >@@ -1481,12 +1687,17 @@ > } > } > >-public void markPotentiallyNonNullBit(LocalVariableBinding local) { >+public void markPotentiallyNonNullBit(VariableBinding local) { > if (this != DEAD_END) { > this.tagBits |= NULL_FLAG_MASK; > int position; > long mask; >- if ((position = local.id + this.maxFieldCount) < BitCacheSize) { >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ if (position < BitCacheSize) { > // use bits > mask = 1L << position; > isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$ >@@ -2007,8 +2218,13 @@ > return this; > } > >-public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) { >- int position = local.id + this.maxFieldCount; >+public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding) { >+ int position; >+ if (binding instanceof FieldBinding) { >+ position = binding.id; >+ } else { >+ position = binding.id + this.maxFieldCount; >+ } > int oldLength; > if (this.nullStatusChangedInAssert == null) { > this.nullStatusChangedInAssert = new int[position + 1]; >@@ -2021,8 +2237,13 @@ > this.nullStatusChangedInAssert[position] = 1; > } > >-public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) { >- int position = local.id + this.maxFieldCount; >+public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding) { >+ int position; >+ if (binding instanceof FieldBinding) { >+ position = binding.id; >+ } else { >+ position = binding.id + this.maxFieldCount; >+ } > if(this.nullStatusChangedInAssert == null || position >= this.nullStatusChangedInAssert.length) { > return false; > } >Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java,v >retrieving revision 1.123 >diff -u -r1.123 BlockScope.java >--- compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 17 Dec 2010 09:38:59 -0000 1.123 >+++ compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 1 Feb 2011 05:32:30 -0000 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2010 IBM Corporation and others. >+ * Copyright (c) 2000, 2011 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -97,6 +97,18 @@ > // update local variable binding > binding.declaringScope = this; > binding.id = outerMostMethodScope().analysisIndex++; >+// int cumulativeMaxFieldCounts = 0; >+ ClassScope outerClassScope = this.enclosingClassScope(); >+// TypeDeclaration typeDeclaration = (outerClassScope != null)? outerClassScope.referenceType() : null; >+// while (typeDeclaration != null) { >+// cumulativeMaxFieldCounts += typeDeclaration.maxFieldCount; >+// typeDeclaration = typeDeclaration.enclosingType; >+// } >+ if (outerClassScope != null) { >+ //if (outerClassScope.referenceContext.binding != null && ((outerClassScope.referenceContext.binding.tagBits & ASTNode.IsLocalType) != 0)) >+ //binding.id += outerClassScope.cumulativeFieldCount; >+ } >+ > // share the outermost method scope analysisIndex > } > >Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java,v >retrieving revision 1.183 >diff -u -r1.183 ClassScope.java >--- compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 1 Nov 2010 14:15:47 -0000 1.183 >+++ compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 1 Feb 2011 05:32:30 -0000 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2010 IBM Corporation and others. >+ * Copyright (c) 2000, 2011 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -34,11 +34,14 @@ > public TypeDeclaration referenceContext; > public TypeReference superTypeReference; > java.util.ArrayList deferredBoundChecks; >+ public int cumulativeFieldCount; // cumulative field count from all enclosing types, used to build unique field id's for member types. >+ public int localTypeFieldIdStart; > > public ClassScope(Scope parent, TypeDeclaration context) { > super(Scope.CLASS_SCOPE, parent); > this.referenceContext = context; > this.deferredBoundChecks = null; // initialized if required >+ this.localTypeFieldIdStart = this.cumulativeFieldCount = 0; > } > > void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) { >@@ -75,6 +78,8 @@ > } > } > } >+ this.cumulativeFieldCount += outerMostMethodScope().analysisIndex; >+ this.localTypeFieldIdStart = outerMostMethodScope().analysisIndex; > connectMemberTypes(); > buildFieldsAndMethods(); > anonymousType.faultInTypesForFieldsAndMethods(); >@@ -104,6 +109,24 @@ > FieldBinding[] fieldBindings = new FieldBinding[count]; > HashtableOfObject knownFieldNames = new HashtableOfObject(count); > count = 0; >+ ClassScope enclosingClass = this.enclosingClassScope(); >+ if (enclosingClass != null) { >+ this.cumulativeFieldCount += enclosingClass.cumulativeFieldCount; >+ } >+// SourceTypeBinding enclosingSourceType = this.enclosingSourceType(); >+// if (enclosingSourceType != null) { >+// ReferenceBinding superClassBinding = sourceType.superclass; >+// while (superClassBinding != null) { >+// FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields(); >+// if (unResolvedFields != null) { >+// this.cumulativeFieldCount += unResolvedFields.length; >+// } >+// superClassBinding = superClassBinding.superclass(); >+// } >+// ReferenceBinding[] superInterfacesBinding = enclosingSourceType.superInterfaces; >+// this.cumulativeFieldCount += findFieldCountFromSuperInterfaces(superInterfacesBinding); >+// } >+ > for (int i = 0; i < size; i++) { > FieldDeclaration field = fields[i]; > if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) { >@@ -111,7 +134,7 @@ > // now this error reporting is moved into the parser itself. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=212713 > } else { > FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | ExtraCompilerModifiers.AccUnresolved, sourceType); >- fieldBinding.id = count; >+ fieldBinding.id = count + this.cumulativeFieldCount; > // field's type will be resolved when needed for top level types > checkAndSetModifiersForField(fieldBinding, field); > >@@ -139,6 +162,7 @@ > // remove duplicate fields > if (count != fieldBindings.length) > System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count); >+ this.cumulativeFieldCount += count; > sourceType.tagBits &= ~(TagBits.AreFieldsSorted|TagBits.AreFieldsComplete); // in case some static imports reached already into this type > sourceType.setFields(fieldBindings); > } >@@ -218,6 +242,8 @@ > checkParameterizedTypeBounds(); > checkParameterizedSuperTypeCollisions(); > } >+ this.cumulativeFieldCount += outerMostMethodScope().analysisIndex; >+ this.localTypeFieldIdStart = outerMostMethodScope().analysisIndex; > buildFieldsAndMethods(); > localType.faultInTypesForFieldsAndMethods(); > >@@ -1251,4 +1277,15 @@ > + this.referenceContext.binding.toString(); > return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$ > } >+ >+ private int findFieldCountFromSuperInterfaces(ReferenceBinding[] superinterfaces) { >+ int numOfFields = 0; >+ if (superinterfaces == null) >+ return numOfFields ; >+ for (int i = 0; i < superinterfaces.length; i++) { >+ numOfFields += superinterfaces[i].fieldCount(); >+ numOfFields += findFieldCountFromSuperInterfaces(superinterfaces[i].superInterfaces()); >+ } >+ return numOfFields; >+ } > } >Index: compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java,v >retrieving revision 1.60 >diff -u -r1.60 FieldBinding.java >--- compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java 22 Oct 2010 22:42:56 -0000 1.60 >+++ compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java 1 Feb 2011 05:32:30 -0000 >@@ -16,11 +16,13 @@ > import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; > import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; > import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; >+import org.eclipse.jdt.internal.compiler.flow.FlowInfo; > import org.eclipse.jdt.internal.compiler.impl.Constant; > > public class FieldBinding extends VariableBinding { > public ReferenceBinding declaringClass; > public int compoundUseFlag = 0; // number or accesses via postIncrement or compoundAssignment >+ private int nullStatus; > > protected FieldBinding() { > super(null, null, 0, null); >@@ -29,12 +31,14 @@ > public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) { > super(name, type, modifiers, constant); > this.declaringClass = declaringClass; >+ this.nullStatus = FlowInfo.UNKNOWN; > } > // special API used to change field declaring class for runtime visibility check > public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) { > super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant()); > this.declaringClass = declaringClass; > this.id = initialFieldBinding.id; >+ this.nullStatus = FlowInfo.UNKNOWN; > setAnnotations(initialFieldBinding.getAnnotations()); > } > /* API >@@ -386,4 +390,12 @@ > } > return null; > } >+ >+public int getNullStatusForStaticFinalField() { >+ return this.nullStatus; >+} >+ >+public void setNullStatusForStaticFinalField(int nullStatusToMark) { >+ this.nullStatus = nullStatusToMark; >+} > } >Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java,v >retrieving revision 1.140 >diff -u -r1.140 ReferenceBinding.java >--- compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java 23 Dec 2010 13:57:49 -0000 1.140 >+++ compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java 1 Feb 2011 05:32:30 -0000 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2010 IBM Corporation and others. >+ * Copyright (c) 2000, 2011 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >@@ -38,6 +38,7 @@ > char[] fileName; > char[] constantPoolName; > char[] signature; >+// int cumulativeFieldCount; > > private SimpleLookupTable compatibleCache; > >@@ -1380,4 +1381,17 @@ > public FieldBinding[] unResolvedFields() { > return Binding.NO_FIELDS; > } >+ >+//public int findCumulativeFieldCount() { >+// FieldBinding[] unResolvedFields = this.unResolvedFields(); >+// if (unResolvedFields != null) { >+// this.cumulativeFieldCount += unResolvedFields.length; >+// } >+// ReferenceBinding superClassBinding = this.superclass(); >+// if (superClassBinding != null) { >+// this.cumulativeFieldCount += superClassBinding.cumulativeFieldCount; >+// } >+// ReferenceBinding[] superInterfacesBinding = this.superInterfaces; >+// return this.cumulativeFieldCount; >+//} > } >Index: compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java,v >retrieving revision 1.430 >diff -u -r1.430 ProblemReporter.java >--- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 16 Jan 2011 22:43:21 -0000 1.430 >+++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 1 Feb 2011 05:32:30 -0000 >@@ -103,6 +103,7 @@ > import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; > import org.eclipse.jdt.internal.compiler.lookup.TypeIds; > import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; > import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants; > import org.eclipse.jdt.internal.compiler.parser.Parser; >@@ -280,17 +281,25 @@ > return CompilerOptions.VarargsArgumentNeedCast; > > case IProblem.NullLocalVariableReference: >+ case IProblem.NullFieldReference: > return CompilerOptions.NullReference; > > case IProblem.PotentialNullLocalVariableReference: >+ case IProblem.PotentialNullFieldReference: > return CompilerOptions.PotentialNullReference; > > case IProblem.RedundantLocalVariableNullAssignment: >+ case IProblem.RedundantFieldNullAssignment: > case IProblem.RedundantNullCheckOnNonNullLocalVariable: > case IProblem.RedundantNullCheckOnNullLocalVariable: > case IProblem.NonNullLocalVariableComparisonYieldsFalse: > case IProblem.NullLocalVariableComparisonYieldsFalse: > case IProblem.NullLocalVariableInstanceofYieldsFalse: >+ case IProblem.NullFieldInstanceofYieldsFalse: >+ case IProblem.RedundantNullCheckOnNonNullField: >+ case IProblem.RedundantNullCheckOnNullField: >+ case IProblem.NonNullFieldComparisonYieldsFalse: >+ case IProblem.NullFieldComparisonYieldsFalse: > return CompilerOptions.RedundantNullCheck; > > case IProblem.BoxingConversion : >@@ -4866,108 +4875,156 @@ > } > } > >-public void localVariableNonNullComparedToNull(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.NonNullLocalVariableComparisonYieldsFalse); >+public void variableNonNullComparedToNull(VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.NonNullFieldComparisonYieldsFalse; >+ } else { >+ problem = IProblem.NonNullLocalVariableComparisonYieldsFalse; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.NonNullLocalVariableComparisonYieldsFalse, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.NullLocalVariableComparisonYieldsFalse); >+public void variableNullComparedToNonNull(VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.NullFieldComparisonYieldsFalse; >+ } else { >+ problem = IProblem.NullLocalVariableComparisonYieldsFalse; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.NullLocalVariableComparisonYieldsFalse, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse); >+public void variableNullInstanceof(VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.NullFieldInstanceofYieldsFalse; >+ } else { >+ problem = IProblem.NullLocalVariableInstanceofYieldsFalse; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.NullLocalVariableInstanceofYieldsFalse, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariableNullReference(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.NullLocalVariableReference); >+public void variableNullReference(VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.NullFieldReference; >+ } else { >+ problem = IProblem.NullLocalVariableReference; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.NullLocalVariableReference, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.PotentialNullLocalVariableReference); >+public void variablePotentialNullReference(VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.PotentialNullFieldReference; >+ } else { >+ problem = IProblem.PotentialNullLocalVariableReference; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name)}; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.PotentialNullLocalVariableReference, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable); >+public void variableRedundantCheckOnNonNull(VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.RedundantNullCheckOnNonNullField; >+ } else { >+ problem = IProblem.RedundantNullCheckOnNonNullLocalVariable; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.RedundantNullCheckOnNonNullLocalVariable, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariableRedundantCheckOnNull(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.RedundantNullCheckOnNullLocalVariable); >+public void variableRedundantCheckOnNull (VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.RedundantNullCheckOnNullField; >+ } else { >+ problem = IProblem.RedundantNullCheckOnNullLocalVariable; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.RedundantNullCheckOnNullLocalVariable, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > >-public void localVariableRedundantNullAssignment(LocalVariableBinding local, ASTNode location) { >- int severity = computeSeverity(IProblem.RedundantLocalVariableNullAssignment); >+public void variableRedundantNullAssignment (VariableBinding variable, ASTNode location) { >+ int problem; >+ if (variable instanceof FieldBinding) { >+ problem = IProblem.RedundantFieldNullAssignment; >+ } else { >+ problem = IProblem.RedundantLocalVariableNullAssignment; >+ } >+ int severity = computeSeverity(problem); > if (severity == ProblemSeverities.Ignore) return; >- String[] arguments = new String[] {new String(local.name) }; >+ String[] arguments = new String[] {new String(variable.name) }; > this.handle( >- IProblem.RedundantLocalVariableNullAssignment, >+ problem, > arguments, > arguments, > severity, >- nodeSourceStart(local, location), >- nodeSourceEnd(local, location)); >+ nodeSourceStart(variable, location), >+ nodeSourceEnd(variable, location)); > } > > public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) { >Index: compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties,v >retrieving revision 1.262 >diff -u -r1.262 messages.properties >--- compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 16 Jan 2011 22:43:21 -0000 1.262 >+++ compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 1 Feb 2011 05:32:30 -0000 >@@ -572,6 +572,16 @@ > ### MORE GENERICS > 660 = Unused type arguments for the non generic constructor {0}({1}) of type {2}; it should not be parameterized with arguments <{3}> > >+### NULL ANALYSIS FOR FIELDS >+670 = Null pointer access: The field {0} can only be null at this location >+671 = Potential null pointer access: The field {0} may be null at this location >+672 = Redundant null check: The field {0} can only be null at this location >+673 = Null comparison always yields false: The field {0} can only be null at this location >+674 = Redundant null check: The field {0} cannot be null at this location >+675 = Null comparison always yields false: The field {0} cannot be null at this location >+676 = Redundant assignment: The field {0} can only be null at this location >+677 = instanceof always yields false: The field {0} can only be null at this location >+ > ### CORRUPTED BINARIES > 700 = The class file {0} contains a signature ''{1}'' ill-formed at position {2} > >Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java,v >retrieving revision 1.56 >diff -u -r1.56 CodeSnippetClassFile.java >--- eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java 7 Jan 2010 20:17:47 -0000 1.56 >+++ eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java 1 Feb 2011 05:32:30 -0000 >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2000, 2010 IBM Corporation and others. >+ * Copyright (c) 2000, 2011 IBM Corporation and others. > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 > * which accompanies this distribution, and is available at >#P org.eclipse.jdt.core.tests >Index: Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java >=================================================================== >RCS file: /home/cvs/numbat/org.eclipse.jdt.core.tests/Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java,v >retrieving revision 1.130 >diff -u -r1.130 InitializationTest.java >--- Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java 10 Jan 2011 19:30:50 -0000 1.130 >+++ Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java 1 Feb 2011 05:32:36 -0000 >@@ -32,7 +32,7 @@ > // Only the highest compliance level is run; add the VM argument > // -Dcompliance=1.4 (for example) to lower it if needed > static { >-// TESTS_NAMES = new String[] { "test011" }; >+ TESTS_NAMES = new String[] { "test001" }; > // TESTS_NUMBERS = new int[] { 204 }; > // TESTS_RANGE = new int[] { 231, 240 }; > } >#P org.eclipse.jdt.core.tests.compiler >Index: src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java,v >retrieving revision 1.40 >diff -u -r1.40 CompilerInvocationTests.java >--- src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java 16 Jan 2011 22:43:57 -0000 1.40 >+++ src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java 1 Feb 2011 05:32:37 -0000 >@@ -696,6 +696,7 @@ > expectedProblemAttributes.put("NonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); > expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); > expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); >+ expectedProblemAttributes.put("NonNullFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE)); > expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE)); >@@ -708,6 +709,9 @@ > expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); > expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); > expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); >+ expectedProblemAttributes.put("NullFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >+ expectedProblemAttributes.put("NullFieldInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >+ expectedProblemAttributes.put("NullFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >@@ -745,6 +749,7 @@ > expectedProblemAttributes.put("ParsingErrorReplaceTokens", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX)); > expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX)); > expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >+ expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); > expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); >@@ -752,8 +757,11 @@ > expectedProblemAttributes.put("RecursiveConstructorInvocation", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); > expectedProblemAttributes.put("RedefinedArgument", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); > expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); >+ expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); >+ expectedProblemAttributes.put("RedundantNullCheckOnNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); > expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE)); > expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER)); >@@ -1333,6 +1341,7 @@ > expectedProblemAttributes.put("NonGenericConstructor", SKIP); > expectedProblemAttributes.put("NonGenericMethod", SKIP); > expectedProblemAttributes.put("NonGenericType", SKIP); >+ expectedProblemAttributes.put("NonNullFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER)); > expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER)); >@@ -1345,6 +1354,9 @@ > expectedProblemAttributes.put("NotVisibleField", SKIP); > expectedProblemAttributes.put("NotVisibleMethod", SKIP); > expectedProblemAttributes.put("NotVisibleType", SKIP); >+ expectedProblemAttributes.put("NullFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); >+ expectedProblemAttributes.put("NullFieldInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); >+ expectedProblemAttributes.put("NullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE)); > expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE)); >@@ -1382,6 +1394,7 @@ > expectedProblemAttributes.put("ParsingErrorReplaceTokens", SKIP); > expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", SKIP); > expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT)); >+ expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE)); > expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE)); > expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP); > expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP); >@@ -1389,8 +1402,11 @@ > expectedProblemAttributes.put("RecursiveConstructorInvocation", SKIP); > expectedProblemAttributes.put("RedefinedArgument", SKIP); > expectedProblemAttributes.put("RedefinedLocal", SKIP); >+ expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); >+ expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); >+ expectedProblemAttributes.put("RedundantNullCheckOnNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK)); > expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE)); > expectedProblemAttributes.put("ReferenceToForwardField", SKIP); >Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java,v >retrieving revision 1.12 >diff -u -r1.12 NullReferenceImplTests.java >--- src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java 9 Sep 2010 17:36:17 -0000 1.12 >+++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java 1 Feb 2011 05:32:37 -0000 >@@ -34,9 +34,11 @@ > import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; > import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException; > import org.eclipse.jdt.internal.compiler.impl.Constant; >+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; > import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; > import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; > import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; >+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; > > /** > * A tests series especially meant to validate the internals of our null >@@ -1083,18 +1085,36 @@ > return copy; > } > >-public void markAsDefinitelyNonNull(LocalVariableBinding local) { >- grow(local.id + this.maxFieldCount); >+public void markAsDefinitelyNonNull(VariableBinding local) { >+ int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ grow(position); > super.markAsDefinitelyNonNull(local); > } > >-public void markAsDefinitelyNull(LocalVariableBinding local) { >- grow(local.id + this.maxFieldCount); >+public void markAsDefinitelyNull(VariableBinding local) { >+ int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ grow(position); > super.markAsDefinitelyNull(local); > } > >-public void markAsDefinitelyUnknown(LocalVariableBinding local) { >- grow(local.id + this.maxFieldCount); >+public void markAsDefinitelyUnknown(VariableBinding local) { >+ int position; >+ if (local instanceof FieldBinding) { >+ position = local.id; >+ } else { >+ position = local.id + this.maxFieldCount; >+ } >+ grow(position); > super.markAsDefinitelyUnknown(local); > } > >Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java,v >retrieving revision 1.109 >diff -u -r1.109 NullReferenceTest.java >--- src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 19 Jan 2011 05:29:57 -0000 1.109 >+++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 1 Feb 2011 05:32:37 -0000 >@@ -36,7 +36,7 @@ > // Only the highest compliance level is run; add the VM argument > // -Dcompliance=1.4 (for example) to lower it if needed > static { >-// TESTS_NAMES = new String[] { "testBug325229" }; >+ TESTS_NAMES = new String[] { "testBug247564h_1" }; > // TESTS_NUMBERS = new int[] { 561 }; > // TESTS_RANGE = new int[] { 1, 2049 }; > } >@@ -96,13 +96,12 @@ > " o.toString();\n" + > " }\n" + > "}\n"}, >- "" >-// "----------\n" + >-// "1. ERROR in X.java (at line 5)\n" + >-// " o.toString();\n" + >-// " ^\n" + >-// "The field o is likely null; it was either set to null or checked for null when last used\n" + >-// "----------\n" >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" > ); > } > >@@ -333,13 +332,12 @@ > " this.o.toString();\n" + > " }\n" + > "}\n"}, >- "" >-// "----------\n" + >-// "1. ERROR in X.java (at line 5)\n" + >-// " this.o.toString();\n" + >-// " ^^^^^^\n" + >-// "The field o is likely null; it was either set to null or checked for null when last used\n" + >-// "----------\n" >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " this.o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" > ); > } > >@@ -355,13 +353,12 @@ > " o.toString();\n" + > " }\n" + > "}\n"}, >- "" >-// "----------\n" + >-// "1. ERROR in X.java (at line 5)\n" + >-// " o.toString();\n" + >-// " ^\n" + >-// "The field o is likely null; it was either set to null or checked for null when last used\n" + >-// "----------\n" >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" > ); > } > >@@ -411,13 +408,12 @@ > " }\n" + > " }\n" + > "}\n"}, >- "" >-// "----------\n" + >-// "1. ERROR in X.java (at line 6)\n" + >-// " X.this.o.toString();\n" + >-// " ^^^^^^^^\n" + >-// "The field o is likely null; it was either set to null or checked for null when last used\n" + >-// "----------\n" >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " X.this.o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" > ); > } > >@@ -436,13 +432,12 @@ > " }\n" + > " void bar() {/* */}\n" + > "}\n"}, >- "" >-// "----------\n" + >-// "1. ERROR in X.java (at line 5)\n" + >-// " o.toString();\n" + >-// " ^\n" + >-// "The field o is likely null; it was either set to null or checked for null when last used\n" + >-// "----------\n" >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" > ); > } > >@@ -13673,6 +13668,549 @@ > "}"}, > "null220"); > } >+ >+// null analysis -- simple case for field >+public void testBug247564a() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object o;\n" + >+ " void foo() {\n" + >+ " if (o == null && o.toString() == \"\"){}\n" + >+ " else {}\n" + >+ " o.toString();\n" + // toString() call above defuses null info, so no warning here >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " if (o == null && o.toString() == \"\"){}\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- simple case for field >+// no redundant null check warnings should be obtained since value of field >+// may be changed in another thread. >+public void testBug247564a_1() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object o;\n" + >+ " void foo() {\n" + >+ " o = null;" + >+ " if (o == null){}\n" + >+ " if (o != null){}\n" + >+ " o.toString();\n" + // warn here >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- simple case for field >+public void testBug247564a_2() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object o;\n" + >+ " void foo() {\n" + >+ " if (o == null){\n" + // o is null inside the if block >+ " o.toString();\n" + >+ " }\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- simple case for field >+// null info from one method should not be present in the other (for instance fields) >+public void testBug247564a_3() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object o;\n" + >+ " void foo() {\n" + >+ " }\n" + >+ " void foo1() {\n" + >+ " o.toString();\n" + >+ " }\n" + >+ "}\n"}, >+ "" >+ ); >+} >+ >+// null analysis -- simple case for static final field >+public void testBug247564b() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " static final Object o = null;\n" + >+ " static final Object o1 = new Object();\n" + >+ " void foo() {\n" + >+ " if (o.toString() == \"\") {}\n" + >+ " if (o == null) {}\n" + >+ " if (o != null) {}\n" + >+ " if (o1 == null) {}\n" + >+ " if (o1 != null) {}\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " if (o.toString() == \"\") {}\n" + >+ " ^\n" + >+ "Null pointer access: The field o can only be null at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 6)\n" + >+ " if (o == null) {}\n" + >+ " ^\n" + >+ "Redundant null check: The field o can only be null at this location\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 7)\n" + >+ " if (o != null) {}\n" + >+ " ^\n" + >+ "Null comparison always yields false: The field o can only be null at this location\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 7)\n" + >+ " if (o != null) {}\n" + >+ " ^^\n" + >+ "Dead code\n" + >+ "----------\n" + >+ "5. ERROR in X.java (at line 8)\n" + >+ " if (o1 == null) {}\n" + >+ " ^^\n" + >+ "Null comparison always yields false: The field o1 cannot be null at this location\n" + >+ "----------\n" + >+ "6. WARNING in X.java (at line 8)\n" + >+ " if (o1 == null) {}\n" + >+ " ^^\n" + >+ "Dead code\n" + >+ "----------\n" + >+ "7. ERROR in X.java (at line 9)\n" + >+ " if (o1 != null) {}\n" + >+ " ^^\n" + >+ "Redundant null check: The field o1 cannot be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- simple case for static final field >+public void testBug247564b_1() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " static final Object o;\n" + >+ " static final Object o1;\n" + >+ " static {\n" + >+ " o = null;\n" + >+ " o1 = new Object();\n" + >+ " }\n" + >+ " void foo() {\n" + >+ " if (o.toString() == \"\") {}\n" + >+ " if (o == null) {}\n" + >+ " if (o != null) {}\n" + >+ " if (o1 == null) {}\n" + >+ " if (o1 != null) {}\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 9)\n" + >+ " if (o.toString() == \"\") {}\n" + >+ " ^\n" + >+ "Null pointer access: The field o can only be null at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 10)\n" + >+ " if (o == null) {}\n" + >+ " ^\n" + >+ "Redundant null check: The field o can only be null at this location\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 11)\n" + >+ " if (o != null) {}\n" + >+ " ^\n" + >+ "Null comparison always yields false: The field o can only be null at this location\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 11)\n" + >+ " if (o != null) {}\n" + >+ " ^^\n" + >+ "Dead code\n" + >+ "----------\n" + >+ "5. ERROR in X.java (at line 12)\n" + >+ " if (o1 == null) {}\n" + >+ " ^^\n" + >+ "Null comparison always yields false: The field o1 cannot be null at this location\n" + >+ "----------\n" + >+ "6. WARNING in X.java (at line 12)\n" + >+ " if (o1 == null) {}\n" + >+ " ^^\n" + >+ "Dead code\n" + >+ "----------\n" + >+ "7. ERROR in X.java (at line 13)\n" + >+ " if (o1 != null) {}\n" + >+ " ^^\n" + >+ "Redundant null check: The field o1 cannot be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- fields in synchronized methods >+// check that null analysis for fields in synchronized methods >+// behave as it does in ordinary methods. >+public void testBug247564c() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object o;\n" + >+ " Object o1;\n" + >+ " static final Object o2 = null;\n" + >+ " static final Object o3 = new Object();\n" + >+ " synchronized void foo() {\n" + >+ " o = null;\n" + >+ " if (o == null) {\n" + >+ " o.toString();\n" + >+ " }\n" + >+ " o1 = new Object();\n" + >+ " if (o1 == null) {\n" + >+ " o1.toString();\n" + >+ " }\n" + >+ " if (o2 != null) {\n" + >+ " }\n" + >+ " else {\n" + >+ " o2.toString();\n" + >+ " }\n" + >+ " if (o3 == null) {\n" + >+ " }\n" + >+ " else {\n" + >+ " o3.toString();\n" + >+ " }\n" + >+ " }\n" + >+ " void foo1() {\n" + >+ " o.toString();\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 9)\n" + >+ " o.toString();\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 13)\n" + >+ " o1.toString();\n" + >+ " ^^\n" + >+ "Potential null pointer access: The field o1 may be null at this location\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 15)\n" + >+ " if (o2 != null) {\n" + >+ " ^^\n" + >+ "Null comparison always yields false: The field o2 can only be null at this location\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 15)\n" + >+ " if (o2 != null) {\n" + >+ " }\n" + >+ " ^^^^^\n" + >+ "Dead code\n" + >+ "----------\n" + >+ "5. ERROR in X.java (at line 18)\n" + >+ " o2.toString();\n" + >+ " ^^\n" + >+ "Null pointer access: The field o2 can only be null at this location\n" + >+ "----------\n" + >+ "6. ERROR in X.java (at line 20)\n" + >+ " if (o3 == null) {\n" + >+ " ^^\n" + >+ "Null comparison always yields false: The field o3 cannot be null at this location\n" + >+ "----------\n" + >+ "7. WARNING in X.java (at line 20)\n" + >+ " if (o3 == null) {\n" + >+ " }\n" + >+ " ^^^^^\n" + >+ "Dead code\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- test redundant instanceof warning for static final field >+public void testBug247564d() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " static final Object o = null;\n" + >+ " static final Object o1 = new Object();\n" + >+ " void foo() {\n" + >+ " if (o instanceof String) {}\n" + >+ " if (o1 instanceof String) {}\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 5)\n" + >+ " if (o instanceof String) {}\n" + >+ " ^\n" + >+ "instanceof always yields false: The field o can only be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- test redundant instanceof warning for static final fields >+public void testBug247564e_1() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " static final Object o = null;\n" + >+ " void foo() {\n" + >+ " if (o instanceof X) return;\n" + >+ " }\n" + >+ "}"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 4)\n" + >+ " if (o instanceof X) return;\n" + >+ " ^\n" + >+ "instanceof always yields false: The field o can only be null at this location\n" + >+ "----------\n", >+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); >+} >+ >+// null analysis -- test potential null ptr access warning because of static field access through object returned by method call >+public void testBug247564f() { >+ Map compilerOptions = getCompilerOptions(); >+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ false, >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " static Object o;\n" + >+ " static Object o1;\n" + >+ " Object o2;\n" + >+ " X getX() { return new X();\n}\n" + >+ " void foo() {\n" + >+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" + >+ " if (getX().o2 == null && this.o2.hashCode() == 0) return;\n" + >+ " }\n" + >+ "}"}, >+ null, >+ compilerOptions, >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n", >+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); >+} >+ >+// null analysis -- test potential null ptr access warning because of static field access through object returned by method call >+public void testBug247564f_1() { >+ Map compilerOptions = getCompilerOptions(); >+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ false, >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " static Object o;\n" + >+ " X getX() { return new X();\n}\n" + >+ " Y getY() { return new Y();\n}\n" + >+ " void foo() {\n" + >+ " if (getY().o == null && this.o.hashCode() == 0) return;\n" + >+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" + >+ " }\n" + >+ "}\n" + >+ "class Y{\n" + >+ " static Object o;\n" + >+ "}\n"}, >+ null, >+ compilerOptions, >+ "----------\n" + >+ "1. ERROR in X.java (at line 9)\n" + >+ " if (getX().o == null && this.o.hashCode() == 0) return;\n" + >+ " ^\n" + >+ "Potential null pointer access: The field o may be null at this location\n" + >+ "----------\n", >+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); >+} >+ >+// null analysis -- test field analysis in case of more than 64 fields >+public void testBug247564g() { >+ Map compilerOptions = getCompilerOptions(); >+ compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE); >+ this.runNegativeTest( >+ false, >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ "Object field0, \n" + >+ "field1, field2, field3, field4, \n" + >+ "field5, field6, field7, field8, \n" + >+ "field9, field10, field11, field12, \n" + >+ "field13, field14, field15, field16, \n" + >+ "field17, field18, field19, field20, \n" + >+ "field21, field22, field23, field24, \n" + >+ "field25, field26, field27, field28, \n" + >+ "field29, field30, field31, field32, \n" + >+ "field33, field34, field35, field36, \n" + >+ "field37, field38, field39, field40, \n" + >+ "field41, field42, field43, field44, \n" + >+ "field45, field46, field47, field48, \n" + >+ "field49, field50, field51, field52, \n" + >+ "field53, field54, field55, field56, \n" + >+ "field57, field58, field59, field60, \n" + >+ "field61, field62, field63, field64, \n" + >+ "field65, field66, field67, field68, \n" + >+ "field69, field70, field71, field72, \n" + >+ "field73, field74, field75, field76, \n" + >+ "field77, field78, field79, field80, \n" + >+ "field81, field82, field83, field84, \n" + >+ "field85, field86, field87, field88, \n" + >+ "field89, field90, field91, field92, \n" + >+ "field93, field94, field95, field96, \n" + >+ "field97, field98, field99;\n" + >+ "static final Object field100 = null;\n" + >+ " void foo() {\n" + >+ " int i = 0;" + >+ " while (i<10){\n" + >+ " i++;\n" + >+ " if (this.field99 == null && this.field99.hashCode() == 0){}\n" + >+ " this.field98 = null;\n" + >+ " }\n" + >+ " if (this.field98.hashCode() == 0) {}\n" + // should not complain >+ " this.field97 = null;\n" + >+ " if (this.field97.hashCode() == 0) {}\n" + >+ " if (this.field100.hashCode() == 0) {}\n" + >+ " }\n" + >+ "}"}, >+ null, >+ compilerOptions, >+ "----------\n" + >+ "1. ERROR in X.java (at line 32)\n" + >+ " if (this.field99 == null && this.field99.hashCode() == 0){}\n" + >+ " ^^^^^^^\n" + >+ "Potential null pointer access: The field field99 may be null at this location\n" + >+ "----------\n" + >+ "2. ERROR in X.java (at line 37)\n" + >+ " if (this.field97.hashCode() == 0) {}\n" + >+ " ^^^^^^^\n" + >+ "Potential null pointer access: The field field97 may be null at this location\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 38)\n" + >+ " if (this.field100.hashCode() == 0) {}\n" + >+ " ^^^^^^^^\n" + >+ "Null pointer access: The field field100 can only be null at this location\n" + >+ "----------\n", >+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); >+} >+ >+// null analysis -- simple case for field for inner class >+// to make sure field id's of inner and outer classes are not same for flow analysis >+public void testBug247564h() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object o;\n" + >+ " class X1 {\n" + >+ " Object x;" + >+ " Object x1;" + >+ " Object x2;" + >+ " void goo() {\n" + >+ " if (o == null && x.toString() == \"\"){}\n" + >+ " if (o2 == null && o2.toString() == \"\"){}\n" + >+ " if (o2 == null && x2.toString() == \"\"){}\n" + >+ " }\n" + >+ >+ " }\n" + >+ " Object o1;\n" + >+ " static Object o2;\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 6)\n" + >+ " if (o2 == null && o2.toString() == \"\"){}\n" + >+ " ^^\n" + >+ "Potential null pointer access: The field o2 may be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- simple case for field for inner class >+// to make sure that id's of local variables in inner classes dotn conflict with those of fields. >+public void testBug247564h_1() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object field0;\n" + >+ " Object field1;\n" + >+ " class X1 {\n" + >+ " Object field2;" + >+ " Object field3;" + >+ " void goo(Object var) {\n" + >+ " if (var == null && field2.toString() == \"\"){}\n" + >+ " if (var == null && field3.toString() == \"\"){}\n" + >+ " if (field2 == null && field2.toString() == \"\"){}\n" + >+ " }\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 8)\n" + >+ " if (field2 == null && field2.toString() == \"\"){}\n" + >+ " ^^^^^^\n" + >+ "Potential null pointer access: The field field2 may be null at this location\n" + >+ "----------\n" >+ ); >+} >+ >+// null analysis -- simple case for field for inner class >+// to make sure that id's of local variables in inner classes dotn conflict with those of fields. >+public void testBug247564h_2() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public class X {\n" + >+ " Object field0;\n" + >+ " Object field1;\n" + >+ " class X1 {\n" + >+ " Object field2;\n" + >+ " Object field3;\n" + >+ " class X2 {\n" + >+ " Object field4;\n" + >+ " Object field5;\n" + >+ " void goo(Object var) {\n" + >+ " if (var == null && field4.toString() == \"\"){}\n" + >+ " if (var == null && field5.toString() == \"\"){}\n" + >+ " if (field3 == null && field3.toString() == \"\"){}\n" + >+ " if (field3 == null && field1.toString() == \"\"){}\n" + >+ " }\n" + >+ " }\n" + >+ " Object field2;\n" + >+ " }\n" + >+ "}\n"}, >+ "----------\n" + >+ "1. ERROR in X.java (at line 9)\n" + >+ " if (field3 == null && field3.toString() == \"\"){}\n" + >+ " ^^^^^^\n" + >+ "Potential null pointer access: The field field3 may be null at this location\n" + >+ "----------\n" >+ ); >+} > // https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 > // Dead Code detection removing code that isn't dead > public void testBug332637() {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 247564
:
185536
|
185729
|
186938
|
187094
|
188023
|
206514
|
206570
|
206572
|
207019
|
209475
|
209486
|
209552
|
209734
|
209741
|
209759
|
209774
|
209775