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 --- compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 23 Nov 2006 17:27:18 -0000 1.215 +++ compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 12 Jan 2007 22:37:32 -0000 @@ -326,6 +326,9 @@ 397 = The variable {0} cannot be null; it was either set to a non-null value or assumed to be non-null when last used 398 = The variable {0} can only be null; it was either set to null or checked for null when last used 399 = The variable {0} may be null + +417 = The variable {0} can only be null; it was either set to null or checked for null when last used +418 = The variable {0} may be null 400 = The type {3} must implement the inherited abstract method {2}.{0}({1}) 401 = Cannot override the final method from {0} 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 --- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 10 Jan 2007 17:56:47 -0000 1.336 +++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 12 Jan 2007 22:37:32 -0000 @@ -189,6 +189,10 @@ case IProblem.LocalVariableMayBeNull : return CompilerOptions.NullReference; + case IProblem.LocalVariableCanOnlyBeNullWhenDereferenced : + case IProblem.LocalVariableMayBeNullWhenDereferenced : + return CompilerOptions.NullDereference; + case IProblem.BoxingConversion : case IProblem.UnboxingConversion : return CompilerOptions.AutoBoxing; @@ -370,6 +374,7 @@ case (int)(CompilerOptions.MissingSerialVersion >>> 32): case (int)(CompilerOptions.VarargsArgumentNeedCast >>> 32): case (int)(CompilerOptions.NullReference >>> 32): + case (int)(CompilerOptions.NullDereference >>> 32): case (int)(CompilerOptions.IncompleteEnumSwitch >>> 32): case (int)(CompilerOptions.FallthroughCase >>> 32): case (int)(CompilerOptions.OverridingMethodWithoutSuperInvocation >>> 32): @@ -4346,11 +4351,16 @@ nodeSourceEnd(local, location)); } public void localVariableCanOnlyBeNull(LocalVariableBinding local, ASTNode location) { - int severity = computeSeverity(IProblem.LocalVariableCanOnlyBeNull); + localVariableCanOnlyBeNull(local, location, false); +} +public void localVariableCanOnlyBeNull(LocalVariableBinding local, ASTNode location, boolean isDereference) { + int problem = (isDereference ? IProblem.LocalVariableCanOnlyBeNullWhenDereferenced + : IProblem.LocalVariableCanOnlyBeNull); + int severity = computeSeverity(problem); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name) }; this.handle( - IProblem.LocalVariableCanOnlyBeNull, + problem, arguments, arguments, severity, @@ -4392,11 +4402,16 @@ } } public void localVariableMayBeNull(LocalVariableBinding local, ASTNode location) { - int severity = computeSeverity(IProblem.LocalVariableMayBeNull); + localVariableMayBeNull(local, location, false); +} +public void localVariableMayBeNull(LocalVariableBinding local, ASTNode location, boolean isDereference) { + int problem = (isDereference ? IProblem.LocalVariableMayBeNullWhenDereferenced + : IProblem.LocalVariableMayBeNull); + int severity = computeSeverity(problem); if (severity == ProblemSeverities.Ignore) return; String[] arguments = new String[] {new String(local.name)}; this.handle( - IProblem.LocalVariableMayBeNull, + problem, arguments, arguments, severity, 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 --- compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 22 Nov 2006 16:36:24 -0000 1.109 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 12 Jan 2007 22:37:32 -0000 @@ -479,13 +479,17 @@ * @param flowInfo the upstream flow info; caveat: may get modified */ public void checkNPE(BlockScope scope, FlowContext flowContext, - FlowInfo flowInfo) { + FlowInfo flowInfo) { + checkNPE(scope, flowContext, flowInfo, false); +} +public void checkNPE(BlockScope scope, FlowContext flowContext, + FlowInfo flowInfo, boolean isDereference) { LocalVariableBinding local = this.localVariableBinding(); if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { if ((this.bits & IsNonNull) == 0) { flowContext.recordUsingNullReference(scope, local, this, - FlowContext.MAY_NULL, flowInfo); + FlowContext.MAY_NULL, flowInfo, isDereference); } flowInfo.markAsComparedEqualToNonNull(local); // from thereon it is set Index: compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java,v --- compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java 28 Oct 2006 04:11:27 -0000 1.44 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java 12 Jan 2007 22:37:32 -0000 @@ -49,7 +49,7 @@ BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { - receiver.checkNPE(currentScope, flowContext, flowInfo); + receiver.checkNPE(currentScope, flowContext, flowInfo, true); flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo); return position.analyseCode(currentScope, flowContext, flowInfo); } 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 --- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 7 Dec 2006 14:50:04 -0000 1.118 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 12 Jan 2007 22:37:32 -0000 @@ -45,7 +45,7 @@ boolean nonStatic = !binding.isStatic(); flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits(); if (nonStatic) { - receiver.checkNPE(currentScope, flowContext, flowInfo); + receiver.checkNPE(currentScope, flowContext, flowInfo, true); } if (arguments != null) { 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 --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 8 Nov 2006 04:03:21 -0000 1.106 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 12 Jan 2007 22:37:32 -0000 @@ -99,7 +99,7 @@ boolean nonStatic = !binding.isStatic(); receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic); if (nonStatic) { - receiver.checkNPE(currentScope, flowContext, flowInfo); + receiver.checkNPE(currentScope, flowContext, flowInfo, true); } if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { Index: compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java,v --- compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 23 Aug 2006 16:32:56 -0000 1.42 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 12 Jan 2007 22:37:32 -0000 @@ -81,7 +81,7 @@ continueLabel = new BranchLabel(); // process the element variable and collection - this.collection.checkNPE(currentScope, flowContext, flowInfo); + this.collection.checkNPE(currentScope, flowContext, flowInfo, true); flowInfo = this.elementVariable.analyseCode(scope, flowContext, flowInfo); FlowInfo condInfo = this.collection.analyseCode(scope, flowContext, flowInfo.copy()); Index: batch/org/eclipse/jdt/internal/compiler/batch/Main.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java,v --- batch/org/eclipse/jdt/internal/compiler/batch/Main.java 8 Jan 2007 15:52:42 -0000 1.276 +++ batch/org/eclipse/jdt/internal/compiler/batch/Main.java 12 Jan 2007 22:37:32 -0000 @@ -1604,6 +1604,13 @@ this.options.put( CompilerOptions.OPTION_ReportNullReference, isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); + this.options.put( + CompilerOptions.OPTION_ReportNullDereference, + isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); + } else if (token.equals("nullDereference")) { //$NON-NLS-1$ + this.options.put( + CompilerOptions.OPTION_ReportNullDereference, + isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); } else if (token.equals("boxing")) { //$NON-NLS-1$ this.options.put( CompilerOptions.OPTION_ReportAutoboxing, Index: model/org/eclipse/jdt/core/JavaCore.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v --- model/org/eclipse/jdt/core/JavaCore.java 12 Jan 2007 17:58:48 -0000 1.559 +++ model/org/eclipse/jdt/core/JavaCore.java 12 Jan 2007 22:37:32 -0000 @@ -679,6 +679,12 @@ * @see #getDefaultOptions() * @since 3.3 */ + public static final String COMPILER_PB_NULL_DEREFERENCE = PLUGIN_ID + ".compiler.problem.nullDereference"; //$NON-NLS-1$ + /** + * Possible configurable option ID. + * @see #getDefaultOptions() + * @since 3.3 + */ public static final String COMPILER_PB_OVERRIDING_METHOD_WITHOUT_SUPER_INVOCATION = PLUGIN_ID + ".compiler.problem.overridingMethodWithoutSuperInvocation"; //$NON-NLS-1$ /** * Possible configurable option ID. Index: compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java,v --- compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 14 Dec 2006 18:31:06 -0000 1.177 +++ compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 12 Jan 2007 22:37:32 -0000 @@ -94,6 +94,7 @@ public static final String OPTION_TaskCaseSensitive = "org.eclipse.jdt.core.compiler.taskCaseSensitive"; //$NON-NLS-1$ public static final String OPTION_InlineJsr = "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"; //$NON-NLS-1$ public static final String OPTION_ReportNullReference = "org.eclipse.jdt.core.compiler.problem.nullReference"; //$NON-NLS-1$ + public static final String OPTION_ReportNullDereference = "org.eclipse.jdt.core.compiler.problem.nullDereference"; //$NON-NLS-1$ public static final String OPTION_ReportAutoboxing = "org.eclipse.jdt.core.compiler.problem.autoboxing"; //$NON-NLS-1$ public static final String OPTION_ReportAnnotationSuperInterface = "org.eclipse.jdt.core.compiler.problem.annotationSuperInterface"; //$NON-NLS-1$ public static final String OPTION_ReportMissingOverrideAnnotation = "org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation"; //$NON-NLS-1$ @@ -181,6 +182,8 @@ public static final long ForbiddenReference = ASTNode.Bit35L; public static final long VarargsArgumentNeedCast = ASTNode.Bit36L; public static final long NullReference = ASTNode.Bit37L; +//* DSRG: can we use bit 51? + public static final long NullDereference = ASTNode.Bit51L; public static final long AutoBoxing = ASTNode.Bit38L; public static final long AnnotationSuperInterface = ASTNode.Bit39L; public static final long TypeHiding = ASTNode.Bit40L; @@ -413,6 +416,7 @@ optionsMap.put(OPTION_MaxProblemPerUnit, String.valueOf(this.maxProblemsPerUnit)); optionsMap.put(OPTION_InlineJsr, this.inlineJsrBytecode ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportNullReference, getSeverityString(NullReference)); + optionsMap.put(OPTION_ReportNullDereference, getSeverityString(NullDereference)); optionsMap.put(OPTION_SuppressWarnings, this.suppressWarnings ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportUnhandledWarningToken, getSeverityString(UnhandledWarningToken)); optionsMap.put(OPTION_ReportParameterAssignment, getSeverityString(ParameterAssignment)); @@ -652,6 +656,7 @@ if ((optionValue = optionsMap.get(OPTION_ReportDiscouragedReference)) != null) updateSeverity(DiscouragedReference, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportVarargsArgumentNeedCast)) != null) updateSeverity(VarargsArgumentNeedCast, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportNullReference)) != null) updateSeverity(NullReference, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportNullDereference)) != null) updateSeverity(NullDereference, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportAutoboxing)) != null) updateSeverity(AutoBoxing, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportAnnotationSuperInterface)) != null) updateSeverity(AnnotationSuperInterface, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingOverrideAnnotation)) != null) updateSeverity(MissingOverrideAnnotation, optionValue); @@ -959,6 +964,7 @@ OPTION_ReportNonExternalizedStringLiteral, OPTION_ReportNonStaticAccessToStatic, OPTION_ReportNullReference, + OPTION_ReportNullDereference, OPTION_ReportOverridingPackageDefaultMethod, OPTION_ReportParameterAssignment, OPTION_ReportPossibleAccidentalBooleanAssignment, @@ -1037,6 +1043,8 @@ return "restriction"; //$NON-NLS-1$ case (int) (NullReference >>> 32) : return "null"; //$NON-NLS-1$ + case (int) (NullDereference >>> 32) : + return "nullDereference"; //$NON-NLS-1$ case (int) (FallthroughCase >>> 32) : return "fallthrough"; //$NON-NLS-1$ case (int) (OverridingMethodWithoutSuperInvocation >>> 32) : @@ -1058,6 +1066,7 @@ "incomplete-switch", //$NON-NLS-1$ "nls", //$NON-NLS-1$ "null", //$NON-NLS-1$ + "nullDereference", //$NON-NLS-1$ "restriction", //$NON-NLS-1$ "serial", //$NON-NLS-1$ "static-access", //$NON-NLS-1$ @@ -1107,6 +1116,8 @@ return NonExternalizedString; if ("null".equals(warningToken)) //$NON-NLS-1$ return NullReference; + if ("nullDereference".equals(warningToken)) //$NON-NLS-1$ + return NullDereference; break; case 'r' : if ("restriction".equals(warningToken)) //$NON-NLS-1$ 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 --- compiler/org/eclipse/jdt/core/compiler/IProblem.java 23 Nov 2006 17:27:18 -0000 1.185 +++ compiler/org/eclipse/jdt/core/compiler/IProblem.java 12 Jan 2007 22:37:32 -0000 @@ -724,6 +724,12 @@ int LocalVariableCanOnlyBeNull = Internal + 398; /** @since 3.2 */ int LocalVariableMayBeNull = Internal + 399; + + //* the following 2 probably need to have the numbers adjusted... + /** @since 3.3 */ + int LocalVariableCanOnlyBeNullWhenDereferenced = Internal + 417; + /** @since 3.3 */ + int LocalVariableMayBeNullWhenDereferenced = Internal + 418; // method verifier problems int AbstractMethodMustBeImplemented = MethodRelated + 400; 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 --- compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java 25 Sep 2006 11:36:59 -0000 1.21 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java 12 Jan 2007 22:37:32 -0000 @@ -157,7 +157,7 @@ } public void recordUsingNullReference(Scope scope, LocalVariableBinding local, - Expression reference, int checkType, FlowInfo flowInfo) { + Expression reference, int checkType, FlowInfo flowInfo, boolean isDereference) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { if (deferNullDiagnostic) { // within an enclosing loop, be conservative switch (checkType) { @@ -179,7 +179,7 @@ return; } if (flowInfo.canOnlyBeNull(local)) { - scope.problemReporter().localVariableCanOnlyBeNull(local, reference); + scope.problemReporter().localVariableCanOnlyBeNull(local, reference, isDereference); return; } break; 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 --- compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 26 Sep 2006 12:04:03 -0000 1.35 +++ compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 12 Jan 2007 22:37:32 -0000 @@ -317,7 +317,7 @@ } public void recordUsingNullReference(Scope scope, LocalVariableBinding local, - Expression reference, int checkType, FlowInfo flowInfo) { + Expression reference, int checkType, FlowInfo flowInfo, boolean isDereference) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || flowInfo.isDefinitelyUnknown(local)) { return; @@ -357,11 +357,11 @@ return; } if (flowInfo.isDefinitelyNull(local)) { - scope.problemReporter().localVariableCanOnlyBeNull(local, reference); + scope.problemReporter().localVariableCanOnlyBeNull(local, reference, isDereference); return; } if (flowInfo.isPotentiallyNull(local)) { - scope.problemReporter().localVariableMayBeNull(local, reference); + scope.problemReporter().localVariableMayBeNull(local, reference, isDereference); return; } recordNullReference(local, reference, checkType); 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 --- compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 26 Sep 2006 12:04:03 -0000 1.53 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 12 Jan 2007 22:37:32 -0000 @@ -493,6 +493,10 @@ */ public void recordUsingNullReference(Scope scope, LocalVariableBinding local, Expression reference, int checkType, FlowInfo flowInfo) { + recordUsingNullReference(scope, local, reference, checkType, flowInfo, false); +} +public void recordUsingNullReference(Scope scope, LocalVariableBinding local, + Expression reference, int checkType, FlowInfo flowInfo, boolean isDereference) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || flowInfo.isDefinitelyUnknown(local)) { return; @@ -517,11 +521,11 @@ break; case MAY_NULL : if (flowInfo.isDefinitelyNull(local)) { - scope.problemReporter().localVariableCanOnlyBeNull(local, reference); + scope.problemReporter().localVariableCanOnlyBeNull(local, reference, isDereference); return; } if (flowInfo.isPotentiallyNull(local)) { - scope.problemReporter().localVariableMayBeNull(local, reference); + scope.problemReporter().localVariableMayBeNull(local, reference, isDereference); return; } break;