Merge remote branch 'origin/master' into NullAnalysisForFields
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Options.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Options.java
index 7b29f99..9dc391f 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Options.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Options.java
@@ -184,6 +184,7 @@
 						|| token.equals("noImplicitStringConversion")//$NON-NLS-1$
 						|| token.equals("null")//$NON-NLS-1$
 						|| token.equals("nullDereference")//$NON-NLS-1$
+						|| token.equals("nullFields")//$NON-NLS-1$
 						|| token.equals("over-ann")//$NON-NLS-1$
 						|| token.equals("packageDefaultMethod")//$NON-NLS-1$
 						|| token.equals("paramAssign")//$NON-NLS-1$
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 3e46fd6..0328324 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -1668,7 +1668,7 @@
         "      allDeprecation       deprecation including inside deprecated code\n" + 
         "      allJavadoc           invalid or missing javadoc\n" + 
         "      allOver-ann          all missing @Override annotations\n" + 
-        "      all-static-method    all method can be declared as static warnings\n" +
+        "      all-static-method    all method can be declared as static warnings\n" + 
         "      assertIdentifier   + ''assert'' used as identifier\n" + 
         "      boxing               autoboxing conversion\n" + 
         "      charConcat         + char[] in String concat\n" + 
@@ -1703,6 +1703,7 @@
         "      noEffectAssign     + assignment without effect\n" + 
         "      null                 potential missing or redundant null check\n" + 
         "      nullDereference    + missing null check\n" + 
+        "      nullFields    	  + null analysis for fields\n" + 
         "      over-ann             missing @Override annotation (superclass)\n" + 
         "      paramAssign          assignment to a parameter\n" + 
         "      pkgDefaultMethod   + attempt to override package-default method\n" + 
@@ -1722,7 +1723,7 @@
         "      syntheticAccess      synthetic access for innerclass\n" + 
         "      tasks(<tags separated by |>) tasks identified by tags inside comments\n" + 
         "      typeHiding         + type parameter hiding another type\n" + 
-        "      unavoidableGenericProblems + ignore unavoidable type safety problems\n" +
+        "      unavoidableGenericProblems + ignore unavoidable type safety problems\n" + 
         "                                   due to raw APIs\n" + 
         "      unchecked          + unchecked type operation\n" + 
         "      unnecessaryElse      unnecessary else clause\n" + 
@@ -1740,7 +1741,7 @@
         "      unusedTypeArgs     + unused type arguments for method and constructor\n" + 
         "      uselessTypeCheck     unnecessary cast/instanceof operation\n" + 
         "      varargsCast        + varargs argument need explicit cast\n" + 
-        "      warningToken       + unsupported or unnecessary @SuppressWarnings\n" + 
+        "      warningToken       + unsupported or unnecessary @SuppressWarnings\n" +
         "\n";
 	String expandedExpectedOutput =
 		MessageFormat.format(expectedOutput, new String[] {
@@ -1800,11 +1801,11 @@
 			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
 			"	</command_line>\n" + 
 			"	<options>\n" + 
-			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnull\" value=\"org.eclipse.jdt.annotation.NonNull\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnullbydefault\" value=\"org.eclipse.jdt.annotation.NonNullByDefault\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnullisdefault\" value=\"disabled\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nullable\" value=\"org.eclipse.jdt.annotation.Nullable\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nullanalysis\" value=\"disabled\"/>\n" +
+			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnull\" value=\"org.eclipse.jdt.annotation.NonNull\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnullbydefault\" value=\"org.eclipse.jdt.annotation.NonNullByDefault\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnullisdefault\" value=\"disabled\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nullable\" value=\"org.eclipse.jdt.annotation.Nullable\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nullanalysis\" value=\"disabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"disabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"1.5\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.unusedLocal\" value=\"optimize out\"/>\n" + 
@@ -1814,7 +1815,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.debug.sourceFile\" value=\"generate\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.doc.comment.support\" value=\"disabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.generateClassFiles\" value=\"enabled\"/>\n" + 
-			"		<option key=\"org.eclipse.jdt.core.compiler.maxProblemPerUnit\" value=\"100\"/>\n" +
+			"		<option key=\"org.eclipse.jdt.core.compiler.maxProblemPerUnit\" value=\"100\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.annotationSuperInterface\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.assertIdentifier\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.autoboxing\" value=\"ignore\"/>\n" + 
@@ -1835,6 +1836,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.forbiddenReference\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock\" value=\"warning\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.includeFieldsInNullAnalysis\" value=\"disabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts\" value=\"disabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch\" value=\"ignore\"/>\n" + 
@@ -1863,18 +1865,18 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noEffectAssignment\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" + 
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo\" value=\"warning\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecViolation\" value=\"error\"/>\n" +
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo\" value=\"warning\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecViolation\" value=\"error\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation\" value=\"error\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" +
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation\" value=\"warning\"/>\n" +
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation\" value=\"error\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSuperinterface\" value=\"ignore\"/>\n" + 
@@ -1887,7 +1889,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.tasks\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.typeParameterHiding\" value=\"warning\"/>\n" + 
-			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems\" value=\"enabled\"/>\n" +
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems\" value=\"enabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.unclosedCloseable\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock\" value=\"ignore\"/>\n" + 
@@ -1915,7 +1917,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.source\" value=\"1.5\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.taskCaseSensitive\" value=\"enabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.taskPriorities\" value=\"\"/>\n" + 
-			"		<option key=\"org.eclipse.jdt.core.compiler.taskTags\" value=\"\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.taskTags\" value=\"\"/>\n" +
 			"	</options>\n" + 
 			"	<classpaths>NORMALIZED SECTION</classpaths>\n" + 
 			"	<sources>\n" + 
@@ -12352,4 +12354,34 @@
 		"1 problem (1 warning)", 
 		true);
 }
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nulLFields
+// Null warnings should be flagged on fields
+public void test311_warn_options() {
+	this.runConformTest(
+		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",
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "X.java\""
+		+ " -sourcepath \"" + OUTPUT_DIR + "\""
+		+ " -warn:null,nullFields -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"----------\n" + 
+		"1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/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" + 
+		"1 problem (1 warning)", 
+		true);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 95fa1b1..670e436 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -724,6 +724,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));
@@ -736,6 +737,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));
@@ -779,6 +783,7 @@
 		expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
 		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", 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("PotentialNullMessageSendReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -788,10 +793,13 @@
 		expectedProblemAttributes.put("RedefinedArgument", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+		expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
+		expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", 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));
@@ -1414,6 +1422,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));
@@ -1426,6 +1435,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));
@@ -1469,6 +1481,7 @@
 		expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
 		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
 		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
+		expectedProblemAttributes.put("PotentialNullFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
 		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
 		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
 		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
@@ -1478,10 +1491,13 @@
 		expectedProblemAttributes.put("RedefinedArgument", SKIP);
 		expectedProblemAttributes.put("RedefinedLocal", SKIP);
 		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
+		expectedProblemAttributes.put("RedundantFieldNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
+		expectedProblemAttributes.put("RedundantNullCheckOnNonNullField", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", 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);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java
index 4e75828..669345c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2012 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
@@ -31,7 +31,7 @@
 
 public class FlowAnalysisTest extends AbstractRegressionTest {
 static {
-//	TESTS_NAMES = new String[] { "testLocalClassInInitializer1" };
+//	TESTS_NAMES = new String[] { "testInnerClassesWithFields1" };
 //	TESTS_NUMBERS = new int[] { 69 };
 }
 public FlowAnalysisTest(String name) {
@@ -2496,6 +2496,119 @@
 			"continue cannot be used outside of a loop\n" + 
 			"----------\n");
 }
+// final field in anonymous nested class
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+public void testFinalFieldInNested1() {
+	this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"public class X {\n" +
+				"    void print4() {\n" +
+				"        for (int i=0; i<4; i++)\n" +
+				"            new Runnable() {\n" +
+				"                final String s1local;\n" +
+				"                public void run() {\n" +
+				"                     s1local.toString();\n" +
+				"                }\n" +
+				"            }.run();\n" +
+				"    }\n" +
+				"}\n"
+			}, 
+			"----------\n" + 
+			"1. ERROR in X.java (at line 4)\n" + 
+			"	new Runnable() {\n" + 
+			"	    ^^^^^^^^^^\n" + 
+			"The blank final field s1local may not have been initialized\n" + 
+			"----------\n");
+}
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+// local variable in inner class triggered IAE in StackMapFrame.addStackItem
+public void testInnerClassesWithFields1() {
+	if (this.complianceLevel >= ClassFileConstants.JDK1_6) { // we're specifically interested in StackMap generation
+		this.runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n" +
+					"    int f1, f2, f3;\n" +
+					"    class I1 {\n" +
+					"        int f4;\n" +
+					"        String m(boolean b) {\n" +
+					"            String l1 = \"Hello\";\n" +
+					"            if (b) {\n" +
+					"                l1 += \" world!\";\n" +
+					"            } else {\n" +
+					"                l1 += \" test.\";\n" +
+					"            }\n" +
+					"            return l1;\n" +
+					"        }\n" +
+					"    }\n" +
+					"    class I2 {\n" +
+					"        int f5, f6, f7;\n" +
+					"    }\n" +
+					"}\n"
+				}, 
+				"");
+	}
+}
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+// local variable in local class triggered IAE in StackMapFrame.addStackItem
+public void testInnerClassesWithFields1a() {
+	if (this.complianceLevel >= ClassFileConstants.JDK1_6) { // we're specifically interested in StackMap generation
+		this.runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n" +
+					"    int f1, f2, f3;\n" +
+					"    void foo() {\n" +
+					"        class I1 {\n" +
+					"            int f4;\n" +
+					"            String m(boolean b) {\n" +
+					"                String l1 = \"Hello\";\n" +
+					"                if (b) {\n" +
+					"                    l1 += \" world!\";\n" +
+					"                } else {\n" +
+					"                    l1 += \" test.\";\n" +
+					"                }\n" +
+					"                return l1;\n" +
+					"            }\n" +
+					"        }\n" +
+					"    }\n" +
+					"    class I2 {\n" +
+					"        int f5, f6, f7;\n" +
+					"    }\n" +
+					"}\n"
+				}, 
+				"");
+	}
+}
+// witness a regression during working on Bug 247564 - [compiler][null] Detecting null field reference
+// final fields in parameterized nested were reported as uninitialized
+public void testInnerClassesWithFields2() {
+	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
+		this.runConformTest(
+			new String[] {
+				"X.java",
+				"public class X {\n" +
+				"    static final String f1 = \"f1\";\n" +
+				"    static final String f2 = \"f2\";\n" +
+				"    String f3;\n" +
+				"    X() {\n" +
+				"        f3 = \"f3\";\n" +
+				"    }\n" +
+				"    protected abstract class I<T> {\n" +
+				"        final String f5, f6;\n" +
+				"        T f7;\n" +
+				"        I(T a) {\n" +
+				"            f5 = \"f5\";\n" +
+				"            f6 = \"f6\";\n" +
+				"            f7 = a;\n" +
+				"        }\n" +
+				"    }\n" +
+				"}\n"
+			}, 
+			"");
+	}
+}
 public static Class testClass() {
 	return FlowAnalysisTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java
index 23d9410..0309b5f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InitializationTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * Copyright (c) 2010, 2012 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
@@ -464,6 +464,44 @@
 		"The local variable b2 may not have been initialized\n" + 
 		"----------\n");
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564
+// Change in the way field id's are calculated should not affect initializations
+public void testBug247564j() {
+	this.runNegativeTest(
+		new String[] {
+			"Z.java",
+			"public class Z {\n" +
+			"    final int field1 = 0;\n" +
+			"    {\n" +
+			"        class ZInner {\n" +
+			"            final int fieldz1;\n" +
+			"            final int fieldz2 = 0;\n" +
+			"        }\n" +
+			"    }\n" +
+			"}\n"},
+			"----------\n" +
+			"1. WARNING in Z.java (at line 4)\n" +
+			"	class ZInner {\n" +
+			"	      ^^^^^^\n" +
+			"The type ZInner is never used locally\n" +
+			"----------\n" +
+			"2. ERROR in Z.java (at line 4)\n" +
+			"	class ZInner {\n" +
+			"	      ^^^^^^\n" +
+			"The blank final field fieldz1 may not have been initialized\n" +
+			"----------\n" +
+			"3. WARNING in Z.java (at line 5)\n" +
+			"	final int fieldz1;\n" +
+			"	          ^^^^^^^\n" +
+			"The value of the field ZInner.fieldz1 is not used\n" +
+			"----------\n" +
+			"4. WARNING in Z.java (at line 6)\n" +
+			"	final int fieldz2 = 0;\n" +
+			"	          ^^^^^^^\n" +
+			"The value of the field ZInner.fieldz2 is not used\n" +
+			"----------\n"
+	);
+}
 public static Class testClass() {
 	return InitializationTests.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
index 95af131..2bb4c61 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * Copyright (c) 2005, 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
@@ -37,6 +37,7 @@
 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 +1084,21 @@
 	return copy;
 }
 
-public void markAsDefinitelyNonNull(LocalVariableBinding local) {
-	grow(local.id + this.maxFieldCount);
+public void markAsDefinitelyNonNull(VariableBinding local) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	grow(position);
 	super.markAsDefinitelyNonNull(local);
 }
 
-public void markAsDefinitelyNull(LocalVariableBinding local) {
-	grow(local.id + this.maxFieldCount);
+public void markAsDefinitelyNull(VariableBinding local) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	grow(position);
 	super.markAsDefinitelyNull(local);
 }
 
-public void markAsDefinitelyUnknown(LocalVariableBinding local) {
-	grow(local.id + this.maxFieldCount);
+public void markAsDefinitelyUnknown(VariableBinding local) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	grow(position);
 	super.markAsDefinitelyUnknown(local);
 }
 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
index e24388f..22562bf 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
@@ -49,7 +49,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[] { "testBug360328" };
+//		TESTS_NAMES = new String[] { "testBug247564k_3" };
 //		TESTS_NUMBERS = new int[] { 561 };
 //		TESTS_RANGE = new int[] { 1, 2049 };
 }
@@ -72,6 +72,7 @@
 	    defaultOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
 		defaultOptions.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE);
 		defaultOptions.put(CompilerOptions.OPTION_IncludeNullInfoFromAsserts, CompilerOptions.ENABLED);
+		defaultOptions.put(CompilerOptions.OPTION_IncludeFieldsInNullAnalysis, CompilerOptions.ENABLED);
     }
     return defaultOptions;
 }
@@ -109,13 +110,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"
 	);
 }
 
@@ -346,13 +346,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"
 	);
 }
 
@@ -368,13 +367,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"
 	);
 }
 
@@ -424,13 +422,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"
 	);
 }
 
@@ -449,13 +446,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"
 	);
 }
 
@@ -3099,7 +3095,7 @@
 
 // null analysis -- while
 public void test0413_while_unknown_field() {
-	this.runConformTest(
+	this.runNegativeTest(
 		new String[] {
 			"X.java",
 			"public class X {\n" +
@@ -3111,7 +3107,12 @@
 			"    o.toString();\n" +
 			"  }\n" +
 			"}\n"},
-		"");
+		"----------\n" + 
+		"1. ERROR in X.java (at line 7)\n" + 
+		"	o.toString();\n" + 
+		"	^\n" + 
+		"Potential null pointer access: The field o may be null at this location\n" + 
+		"----------\n");
 }
 
 // null analysis -- while
@@ -15453,4 +15454,2255 @@
 		"",/* expected error */
 	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
 }
-}
\ No newline at end of file
+
+// 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 field
+public void testBug247564a_4() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  Object o;\n" +
+			"  int foo() {\n" +
+			"    if (o != null && o.toString() == \"\") {\n" +
+			"    } else {\n" +
+			"    }\n" +
+			"    return o.hashCode();\n" + // the above check has shed doubts so give a warning here
+			"  }\n" +
+			"}\n"},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 7)\n" +
+		"	return o.hashCode();\n" +
+		"	       ^\n" +
+		"Potential null pointer access: The field o may be null at this location\n" +
+		"----------\n"
+	);
+}
+
+// null analysis -- field accessed inside control structure
+// from https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564#c121
+public void testBug247564a_5() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"    private Object field;\n" +
+			"    void goo(Object var) throws Exception{\n" +
+			"        if (field != null)  field.hashCode();\n" +
+			"        int i = 20;\n" +
+			"        while (i<10) {\n" +
+			"            if (field == null) { \n" +
+			"                field = new Object();\n" +
+			"            }\n" +
+			"            field.toString(); //Pot. NPE\n" +
+			"            i--;\n" +
+			"        }\n" +
+			"    }\n" +
+			"}\n"},
+			""
+	);
+}
+
+// null analysis -- simple case for static final field
+// once dereferenced, treat as non null. Consistent with local variables.
+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" + 
+			"Null comparison always yields false: The field o cannot be null at this location\n" + 
+			"----------\n" + 
+			"3. WARNING in X.java (at line 6)\n" + 
+			"	if (o == null) {}\n" + 
+			"	               ^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 7)\n" + 
+			"	if (o != null) {}\n" + 
+			"	    ^\n" + 
+			"Redundant null check: The field o cannot be null at this location\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" + 
+			"Null comparison always yields false: The field o cannot be null at this location\n" + 
+			"----------\n" + 
+			"3. WARNING in X.java (at line 10)\n" + 
+			"	if (o == null) {}\n" + 
+			"	               ^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 11)\n" + 
+			"	if (o != null) {}\n" + 
+			"	    ^\n" + 
+			"Redundant null check: The field o cannot be null at this location\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 -- simple case for static final field
+public void testBug247564b_1_2() {
+	this.runNegativeTest(
+		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 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 35)\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 36)\n" + 
+			"	if (o == null) {}\n" + 
+			"	    ^\n" + 
+			"Null comparison always yields false: The field o cannot be null at this location\n" + 
+			"----------\n" + 
+			"3. WARNING in X.java (at line 36)\n" + 
+			"	if (o == null) {}\n" + 
+			"	               ^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 37)\n" + 
+			"	if (o != null) {}\n" + 
+			"	    ^\n" + 
+			"Redundant null check: The field o cannot be null at this location\n" + 
+			"----------\n" + 
+			"5. ERROR in X.java (at line 38)\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 38)\n" + 
+			"	if (o1 == null) {}\n" + 
+			"	                ^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"7. ERROR in X.java (at line 39)\n" + 
+			"	if (o1 != null) {}\n" + 
+			"	    ^^\n" + 
+			"Redundant null check: The field o1 cannot be null at this location\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_2() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static final Object o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo1() {\n" +
+			"    if (o == null) \n" +
+			"       return;\n" +
+			"	 o.toString();\n" + // cant be null for sure, dont complain
+			"  }\n" +
+			"}\n"},
+			""
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_2_2() {
+	this.runNegativeTest(
+		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 o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo1() {\n" +
+			"    if (o == null) \n" +
+			"       return;\n" +
+			"	 o.toString();\n" + // cant be null for sure, dont complain
+			"  }\n" +
+			"}\n"},
+			""
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// Check pot. NPE case for constant fields
+// Once dereferenced, treat as non null. Just like locals.
+public void testBug247564b_3() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static final Object o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo() {\n" +
+			"    if (o.toString() == \"\") {}\n" +
+			"    if (o == null) {}\n" +
+			"	 if (o != null) {}\n" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 12)\n" + 
+			"	if (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" + 
+			"	if (o == null) {}\n" + 
+			"	    ^\n" + 
+			"Null comparison always yields false: The field o cannot be null at this location\n" + 
+			"----------\n" + 
+			"3. WARNING in X.java (at line 13)\n" + 
+			"	if (o == null) {}\n" + 
+			"	               ^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 14)\n" + 
+			"	if (o != null) {}\n" + 
+			"	    ^\n" + 
+			"Redundant null check: The field o cannot be null at this location\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// Check pot. NPE case for constant fields
+// Once dereferenced, treat as non null. Just like locals.
+public void testBug247564b_3_2() {
+	this.runNegativeTest(
+		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 o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo() {\n" +
+			"    if (o.toString() == \"\") {}\n" +
+			"    if (o == null) {}\n" +
+			"	 if (o != null) {}\n" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 38)\n" + 
+			"	if (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 39)\n" + 
+			"	if (o == null) {}\n" + 
+			"	    ^\n" + 
+			"Null comparison always yields false: The field o cannot be null at this location\n" + 
+			"----------\n" + 
+			"3. WARNING in X.java (at line 39)\n" + 
+			"	if (o == null) {}\n" + 
+			"	               ^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 40)\n" + 
+			"	if (o != null) {}\n" + 
+			"	    ^\n" + 
+			"Redundant null check: The field o cannot be null at this location\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_4() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static final Object o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo1() {\n" +
+			"    if (o == null) {\n" +
+			"        o.toString(); // danger" +
+			"        return;\n" +
+			"    }\n" +
+			"	 o.toString(); // safe\n" +
+			"  }\n" +
+			"  void foo2() {\n" +
+			"    if (o != null) {\n" +
+			"         o.toString(); // safe (2)\n" +
+			"    }\n" +
+			"	 o.toString(); // uncertain\n" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 13)\n" + 
+			"	o.toString(); // danger        return;\n" + 
+			"	^\n" + 
+			"Null pointer access: The field o can only be null at this location\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 21)\n" + 
+			"	o.toString(); // uncertain\n" + 
+			"	^\n" + 
+			"Potential null pointer access: The field o may be null at this location\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// checked before use
+public void testBug247564b_4_2() {
+	this.runNegativeTest(
+		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 o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo1() {\n" +
+			"    if (o == null) {\n" +
+			"        o.toString(); // danger" +
+			"        return;\n" +
+			"    }\n" +
+			"	 o.toString(); // safe\n" +
+			"  }\n" +
+			"  void foo2() {\n" +
+			"    if (o != null) {\n" +
+			"         o.toString(); // safe (2)\n" +
+			"    }\n" +
+			"	 o.toString(); // uncertain\n" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 39)\n" + 
+			"	o.toString(); // danger        return;\n" + 
+			"	^\n" + 
+			"Null pointer access: The field o can only be null at this location\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 47)\n" + 
+			"	o.toString(); // uncertain\n" + 
+			"	^\n" + 
+			"Potential null pointer access: The field o may be null at this location\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be 
+// reset on method calls.
+public void testBug247564b_5() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static final Object o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static final Object o2 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo1() {\n" +
+			"	 final Object local = null;\n" +
+			"	 if (local == null) {\n" +
+			"		local.toString();\n" +
+			"	 }\n" +
+			"	 local.toString();\n" +
+			"	 if (o == null) {\n" +	// don't know o's nullness, so silent
+			"		o.toString();\n" + // report NPE
+			"	 }\n" +
+			"	 o.toString();\n" +	// already reported NPE above. So silent. Same behaviour as 'local'
+			"	 if (o2 == null) {\n" + // report always false null check
+			"		o2.toString();\n" + // dead code
+			"	 }\n" +
+			"	 o2.toString();" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 14)\n" + 
+			"	if (local == null) {\n" + 
+			"	    ^^^^^\n" + 
+			"Redundant null check: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 15)\n" + 
+			"	local.toString();\n" + 
+			"	^^^^^\n" + 
+			"Null pointer access: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"3. ERROR in X.java (at line 19)\n" + 
+			"	o.toString();\n" + 
+			"	^\n" + 
+			"Null pointer access: The field o can only be null at this location\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 22)\n" + 
+			"	if (o2 == null) {\n" + 
+			"	    ^^\n" + 
+			"Null comparison always yields false: The field o2 cannot be null at this location\n" + 
+			"----------\n" + 
+			"5. WARNING in X.java (at line 22)\n" + 
+			"	if (o2 == null) {\n" + 
+			"		o2.toString();\n" + 
+			"	 }\n" + 
+			"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Dead code\n" + 
+			"----------\n"
+	);
+}
+
+//null analysis -- case for static final field initialized inside static block with different values
+//check if the resetting works properly i.e. null status for constant fields should not be 
+//reset on method calls. This test is for constructors
+public void testBug247564b_6() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static final Object o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static final Object o2 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  public X() {\n" +
+			"	 final Object local = null;\n" +
+			"	 if (local == null) {\n" +
+			"		local.toString();\n" +
+			"	 }\n" +
+			"	 local.toString();\n" +
+			"	 if (o == null) {\n" +	// don't know o's nullness, so silent
+			"		o.toString();\n" + // report NPE
+			"	 }\n" +
+			"	 o.toString();\n" +	// already reported NPE above. So silent. Same behaviour as 'local'
+			"	 if (o2 == null) {\n" + // report always false null check
+			"		o2.toString();\n" + // dead code
+			"	 }\n" +
+			"	 o2.toString();" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 14)\n" + 
+			"	if (local == null) {\n" + 
+			"	    ^^^^^\n" + 
+			"Redundant null check: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 15)\n" + 
+			"	local.toString();\n" + 
+			"	^^^^^\n" + 
+			"Null pointer access: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"3. ERROR in X.java (at line 19)\n" + 
+			"	o.toString();\n" + 
+			"	^\n" + 
+			"Null pointer access: The field o can only be null at this location\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 22)\n" + 
+			"	if (o2 == null) {\n" + 
+			"	    ^^\n" + 
+			"Null comparison always yields false: The field o2 cannot be null at this location\n" + 
+			"----------\n" + 
+			"5. WARNING in X.java (at line 22)\n" + 
+			"	if (o2 == null) {\n" + 
+			"		o2.toString();\n" + 
+			"	 }\n" + 
+			"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Dead code\n" + 
+			"----------\n"
+	);
+}
+
+//null analysis -- case for static final field initialized inside static block with different values
+//check if the resetting works properly i.e. null status for constant fields should not be 
+//reset on method calls. This test is for constructors
+public void testBug247564b_6_2() {
+	this.runNegativeTest(
+		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 o;\n" +
+			"  static final Object o1 = new Object();\n" +
+			"  static final Object o2 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" +
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  public X() {\n" +
+			"	 final Object local = null;\n" +
+			"	 if (local == null) {\n" +
+			"		local.toString();\n" +
+			"	 }\n" +
+			"	 local.toString();\n" +
+			"	 if (o == null) {\n" +	// don't know o's nullness, so silent
+			"		o.toString();\n" + // report NPE
+			"	 }\n" +
+			"	 o.toString();\n" +	// already reported NPE above. So silent. Same behaviour as 'local'
+			"	 if (o2 == null) {\n" + // report always false null check
+			"		o2.toString();\n" + // dead code
+			"	 }\n" +
+			"	 o2.toString();" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 40)\n" + 
+			"	if (local == null) {\n" + 
+			"	    ^^^^^\n" + 
+			"Redundant null check: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 41)\n" + 
+			"	local.toString();\n" + 
+			"	^^^^^\n" + 
+			"Null pointer access: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"3. ERROR in X.java (at line 45)\n" + 
+			"	o.toString();\n" + 
+			"	^\n" + 
+			"Null pointer access: The field o can only be null at this location\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 48)\n" + 
+			"	if (o2 == null) {\n" + 
+			"	    ^^\n" + 
+			"Null comparison always yields false: The field o2 cannot be null at this location\n" + 
+			"----------\n" + 
+			"5. WARNING in X.java (at line 48)\n" + 
+			"	if (o2 == null) {\n" + 
+			"		o2.toString();\n" + 
+			"	 }\n" + 
+			"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Dead code\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be 
+// reset on method calls. Also, null info of constant field from static block is available in methods
+public void testBug247564b_7() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static final Object o;\n" +
+			"  static final Object o1 = null;\n" +
+			"  static final Object o2 = new Object();\n" +
+			"  static {\n" +
+			"		if (o1.hashCode() == 2){\n" + // report NPE. But dereferenced here, so later it should be treated as non null
+			"			o = new Object();\n" +
+			"		} else {\n" +
+			"			o = null;\n" +
+			"		}\n" +
+			"  }\n" +
+			"  void foo1() {\n" +
+			"	 final Object local = null;\n" +
+			"	 if (local == null) {\n" +
+			"		local.toString();\n" +
+			"	 }\n" +
+			"	 local.toString();\n" +
+			"	 if (o1 == null) {\n" +	// can't be null, was dereferenced in static initializer
+			"		o1.toString();\n" + // dead
+			"	 }\n" +
+			"	 o1.toString();\n" +	// safe
+			"	 if (o2 == null) {\n" + // report always false null check
+			"		o2.toString();\n" + // dead code
+			"	 }\n" +
+			"	 o2.toString();" +
+			"  }\n" +
+			"}\n"},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 6)\n" + 
+			"	if (o1.hashCode() == 2){\n" + 
+			"	    ^^\n" + 
+			"Null pointer access: The field o1 can only be null at this location\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 14)\n" + 
+			"	if (local == null) {\n" + 
+			"	    ^^^^^\n" + 
+			"Redundant null check: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"3. ERROR in X.java (at line 15)\n" + 
+			"	local.toString();\n" + 
+			"	^^^^^\n" + 
+			"Null pointer access: The variable local can only be null at this location\n" + 
+			"----------\n" + 
+			"4. ERROR in X.java (at line 18)\n" + 
+			"	if (o1 == null) {\n" + 
+			"	    ^^\n" + 
+			"Null comparison always yields false: The field o1 cannot be null at this location\n" + 
+			"----------\n" + 
+			"5. WARNING in X.java (at line 18)\n" + 
+			"	if (o1 == null) {\n" + 
+			"		o1.toString();\n" + 
+			"	 }\n" + 
+			"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"6. ERROR in X.java (at line 22)\n" + 
+			"	if (o2 == null) {\n" + 
+			"	    ^^\n" + 
+			"Null comparison always yields false: The field o2 cannot be null at this location\n" + 
+			"----------\n" + 
+			"7. WARNING in X.java (at line 22)\n" + 
+			"	if (o2 == null) {\n" + 
+			"		o2.toString();\n" + 
+			"	 }\n" + 
+			"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Dead code\n" + 
+			"----------\n"
+	);
+}
+
+// null analysis -- case for static final field initialized inside static block with different values
+// check if the resetting works properly i.e. null status for constant fields should not be 
+// reset on method calls. This test is for more than 64 fields to check for extra bits.
+public void testBug247564b_8() {
+	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 o1 = null;\n" +
+			"static final Object o2 = new Object();\n" +
+			"  void foo1() {\n" +
+			"	 final Object local = null;\n" +
+			"	 if (local == null) {\n" +
+			"		local.toString();\n" +
+			"	 }\n" +
+			"	 local.toString();\n" +
+			"	 if (o1 == null) {\n" +	// report redundant null check
+			"		o1.toString();\n" + // report NPE
+			"	 }\n" +
+			"	 o1.toString();\n" +	// already reported NPE above. So silent. Same behaviour as 'local'
+			"	 if (o2 == null) {\n" + // report always false null check
+			"		o2.toString();\n" + // dead code
+			"	 }\n" +
+			"	 o2.toString();" +
+			"  }\n" +
+			"}\n"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 32)\n" + 
+		"	if (local == null) {\n" + 
+		"	    ^^^^^\n" + 
+		"Redundant null check: The variable local can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 33)\n" + 
+		"	local.toString();\n" + 
+		"	^^^^^\n" + 
+		"Null pointer access: The variable local can only be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 36)\n" + 
+		"	if (o1 == null) {\n" + 
+		"	    ^^\n" + 
+		"Redundant null check: The field o1 can only be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 37)\n" + 
+		"	o1.toString();\n" + 
+		"	^^\n" + 
+		"Null pointer access: The field o1 can only be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in X.java (at line 40)\n" + 
+		"	if (o2 == null) {\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The field o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"6. WARNING in X.java (at line 40)\n" + 
+		"	if (o2 == null) {\n" + 
+		"		o2.toString();\n" + 
+		"	 }\n" + 
+		"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Dead code\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// null analysis -- case for static final field initialized inside static block where some locals are also present
+// check if the resetting works properly
+public void testBug247564b_9() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		false,
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"	static final Object o1;\n" +
+			"	static final Object o2 = new Object();\n" +
+			"	static {\n" +
+			"		int i = 10;\n" +
+			"		o1 = null;\n" +
+			"	}\n" +
+			"  void foo1() {\n" +
+			"	 final Object local = null;\n" +
+			"	 if (local == null) {\n" +
+			"		local.toString();\n" +
+			"	 }\n" +
+			"	 local.toString();\n" +
+			"	 if (o1 == null) {\n" +	// report redundant null check
+			"		o1.toString();\n" + // report NPE
+			"	 }\n" +
+			"	 o1.toString();\n" +	// already reported NPE above. So silent. Same behaviour as 'local'
+			"	 if (o2 == null) {\n" + // report always false null check
+			"		o2.toString();\n" + // dead code
+			"	 }\n" +
+			"	 o2.toString();" +
+			"  }\n" +
+			"}\n"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 10)\n" + 
+		"	if (local == null) {\n" + 
+		"	    ^^^^^\n" + 
+		"Redundant null check: The variable local can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 11)\n" + 
+		"	local.toString();\n" + 
+		"	^^^^^\n" + 
+		"Null pointer access: The variable local can only be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 14)\n" + 
+		"	if (o1 == null) {\n" + 
+		"	    ^^\n" + 
+		"Redundant null check: The field o1 can only be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 15)\n" + 
+		"	o1.toString();\n" + 
+		"	^^\n" + 
+		"Null pointer access: The field o1 can only be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in X.java (at line 18)\n" + 
+		"	if (o2 == null) {\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The field o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"6. WARNING in X.java (at line 18)\n" + 
+		"	if (o2 == null) {\n" + 
+		"		o2.toString();\n" + 
+		"	 }\n" + 
+		"	                ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Dead code\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+}
+
+// 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 -- fields in synchronized methods
+// check that null analysis for fields in synchronized methods
+// behave as it does in ordinary methods. Higher no. of fields
+public void testBug247564c_2() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  Object o;\n" +
+			"  Object o1;\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 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 35)\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 39)\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 41)\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 41)\n" + 
+			"	if (o2 != null) {\n" + 
+			"		}\n" + 
+			"	                ^^^^^\n" + 
+			"Dead code\n" + 
+			"----------\n" + 
+			"5. ERROR in X.java (at line 44)\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 46)\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 46)\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 field. More fields
+public void testBug247564d_1() {
+	this.runNegativeTest(
+		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 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 31)\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 35)\n" + 
+		"	if (this.field98.hashCode() == 0) {}\n" + 
+		"	         ^^^^^^^\n" + 
+		"Potential null pointer access: The field field98 may be null at this location\n" + 
+		"----------\n" + 
+		"3. 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" + 
+		"4. 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 field22;\n" +
+			"  }\n" +
+			"}\n"},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 13)\n" + 
+		"	if (field3 == null && field3.toString() == \"\"){}\n" + 
+		"	                      ^^^^^^\n" + 
+		"Potential null pointer access: The field field3 may be null at this location\n" + 
+		"----------\n"
+	);
+}
+
+// null analysis -- simple case for static fields
+// to make sure that static field only of the current type is assigned potentially null when compared against null
+// Static fields belonging to any other class should be ignored
+// Qualified access to static fields should also work
+public void testBug247564i_1() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		true,
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static Object field0;\n" +
+			"  static Object field1;\n" +
+			"  Y getY(){ return new Y();}\n" +
+			"  X getX() { return new X();}\n" +
+			"  void goo(Object var) {\n" +
+			"    	if (Y.yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.yField1 == null && this.field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +  // warn, qualified access
+			"    	if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (X.field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (this.field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (X.field0 == null && this.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (X.field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn
+			"  }\n" +
+			"}\n" +
+			"class Y{\n" +
+			"	Y getY(){ return new Y();}\n" +
+			"	X getX(){ return new X();}\n" +
+			"   static Object yField1;" +
+			"	static X xiny;\n" +
+			"}"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 9)\n" + 
+		"	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + 
+		"	                                    ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 12)\n" + 
+		"	if (X.field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                          ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 13)\n" + 
+		"	if (this.field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                             ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 14)\n" + 
+		"	if (X.field0 == null && this.field0.toString() == \"\"){}\n" + 
+		"	                             ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+// null analysis -- static fields accessed via MessageSend
+// to make sure that static field only of the current type is assigned potentially null when compared against null
+// Static fields belonging to any other class should be ignored
+// Qualified access to static fields should also work
+public void testBug247564i_2() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		true,
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static Object field0;\n" +
+			"  static Object field1;\n" +
+			"  Y getY(){ return new Y();}\n" +
+			"  X getX() { return new X();}\n" +
+			"  void goo(Object var) {\n" +
+			"    	if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && this.field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && this.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn, getX() wipes out null info
+			"    	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +   // warn, qualified access
+			// fields from other types, don't warn
+			"    	if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"  }\n" +
+			"}\n" +
+			"class Y{\n" +
+			"	Y getY(){ return new Y();}\n" +
+			"	X getX(){ return new X();}\n" +
+			"   static Object yField1;\n" +
+			"}"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 10)\n" + 
+		"	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                                     ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 11)\n" + 
+		"	if (getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                             ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 12)\n" + 
+		"	if (getX().field0 == null && this.field0.toString() == \"\"){}\n" + 
+		"	                                  ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 14)\n" + 
+		"	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                               ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+// null analysis -- static fields accessed from Member type
+// Qualified access to static fields should also work
+public void testBug247564i_3() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		true,
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static Object field0;\n" +
+			"  static Object field1;\n" +
+			"  static Y getY(){ return new Y();}\n" +
+			"  static X getX() { return new X();}\n" +
+			"  static class XInner{\n" +
+			"   static Object xinnerfield;\n" +
+			"   XInner getXInner() { return new XInner();\n}" +
+			"   void goo(Object var) {\n" +
+			"    	if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn, getX() wipes out null info
+			"    	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +   // warn, qualified access
+			"    	if (getXInner().xinnerfield == null && xinnerfield.toString() == \"\"){}\n" +   // warn
+			"    	if (getXInner().xinnerfield == null && this.xinnerfield.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && this.xinnerfield.toString() == \"\"){}\n" +   // no warn
+			"    	if (getXInner().xinnerfield == null && field0.toString() == \"\"){}\n" +   // no warn
+			// fields from other types, don't warn
+			"    	if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			// qualified accesses
+			"    	if (Y.yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +  // warn, qualified access
+			"    	if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (X.field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (X.field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn
+			"   }\n" +
+			"  }\n" +
+			"}\n" +
+			"class Y{\n" +
+			"	Y getY(){ return new Y();}\n" +
+			"	X getX(){ return new X();}\n" +
+			"   static Object yField1;\n" +
+			"   static X xiny;\n" +
+			"}"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 12)\n" + 
+		"	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                                     ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 13)\n" + 
+		"	if (getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                             ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 15)\n" + 
+		"	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                               ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 16)\n" + 
+		"	if (getXInner().xinnerfield == null && xinnerfield.toString() == \"\"){}\n" + 
+		"	                                       ^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The field xinnerfield may be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in X.java (at line 17)\n" + 
+		"	if (getXInner().xinnerfield == null && this.xinnerfield.toString() == \"\"){}\n" + 
+		"	                                            ^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The field xinnerfield may be null at this location\n" + 
+		"----------\n" +
+		"6. ERROR in X.java (at line 24)\n" + 
+		"	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + 
+		"	                                    ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"7. ERROR in X.java (at line 27)\n" + 
+		"	if (X.field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                          ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+// null analysis -- static fields accessed from a local type
+// Qualified access to static fields should also work
+public void testBug247564i_4() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		true,
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  static Object field0;\n" +
+			"  static Object field1;\n" +
+			"  Y getY(){ return new Y();}\n" +
+			"  X getX() { return new X();}\n" +
+			"  void goo(Object var) {\n" +
+			"	class Local{\n" +
+			"	  void localfoo(){\n " +
+			"    	if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn, getX() wipes out null info
+			"    	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +   // warn, qualified access
+			// fields from other types, don't warn
+			"    	if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			// qualified accesses
+			"    	if (Y.yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +  // warn, qualified access
+			"    	if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (X.field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (X.field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn	
+			"    }\n" +
+			"   }\n" +
+			"  }\n" +
+			"}\n" +
+			"class Y{\n" +
+			"	Y getY(){ return new Y();}\n" +
+			"	X getX(){ return new X();}\n" +
+			"   static Object yField1;\n" +
+			"   static X xiny;\n" +
+			"}"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. WARNING in X.java (at line 7)\n" + 
+		"	class Local{\n" + 
+		"	      ^^^^^\n" + 
+		"The type Local is never used locally\n" + 
+		"----------\n" + 
+		"2. WARNING in X.java (at line 8)\n" + 
+		"	void localfoo(){\n" + 
+		"	     ^^^^^^^^^^\n" + 
+		"The method localfoo() from the type Local is never used locally\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 11)\n" + 
+		"	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                                     ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 12)\n" + 
+		"	if (getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                             ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in X.java (at line 14)\n" + 
+		"	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                               ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"6. ERROR in X.java (at line 19)\n" + 
+		"	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + 
+		"	                                    ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"7. ERROR in X.java (at line 22)\n" + 
+		"	if (X.field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                          ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+// null analysis -- static fields from an anonymous type
+// Qualified access to static fields should also work
+public void testBug247564i_5() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		true,
+		new String[] {
+			"X.java",
+			"interface Anon{}\n" +
+			"public class X {\n" +
+			"  static Object field0;\n" +
+			"  static Object field1;\n" +
+			"  Y getY(){ return new Y();}\n" +
+			"  X getX() { return new X();}\n" +
+			"  void goo(Object var) {\n" +
+			"	new Anon(){\n" +
+			"	  void localfoo(){\n " +
+			"    	if (new Y().getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn, getX() wipes out null info
+			"    	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +   // warn, qualified access
+			// fields from other types, don't warn
+			"    	if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			// qualified accesses
+			"    	if (Y.yField1 == null && field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" +  // warn, qualified access
+			"    	if (Y.yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (Y.xiny.field1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (X.field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (X.field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn	
+			"    }\n" +
+			"   };\n" +
+			"  }\n" +
+			"}\n" +
+			"class Y{\n" +
+			"	Y getY(){ return new Y();}\n" +
+			"	X getX(){ return new X();}\n" +
+			"   static Object yField1;\n" +
+			"   static X xiny;\n" +
+			"}"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. WARNING in X.java (at line 9)\n" + 
+		"	void localfoo(){\n" + 
+		"	     ^^^^^^^^^^\n" + 
+		"The method localfoo() from the type new Anon(){} is never used locally\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 12)\n" + 
+		"	if (new Y().getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                                     ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 13)\n" + 
+		"	if (getX().field0 == null && field0.toString() == \"\"){}\n" + 
+		"	                             ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 15)\n" + 
+		"	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                               ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in X.java (at line 20)\n" + 
+		"	if (Y.xiny.field0 == null && Y.xiny.field0.toString() == \"\"){}\n" + 
+		"	                                    ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"6. ERROR in X.java (at line 23)\n" + 
+		"	if (X.field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                          ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+// null analysis -- static fields
+// to check static field access from fieldReference and QualifiedReference when the type is parameterized
+public void testBug247564i_6() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_5) return;
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
+	this.runNegativeTest(
+		true,
+		new String[] {
+			"X.java",
+			"public class X<T> {\n" +
+			"  static Object field0;\n" +
+			"  static Object field1;\n" +
+			"  Y getY(){ return new Y();}\n" +
+			"  X getX() { return new X();}\n" +
+			"  void goo(Object var) {\n" +
+			"    	if (new Y().getY().yField1 == null && X.field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && X.field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && this.field0.toString() == \"\"){}\n" +  // no warn
+			"    	if (new Y().getX().field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && this.field0.toString() == \"\"){}\n" +   // warn
+			"    	if (getX().field0 == null && getX().field0.toString() == \"\"){}\n" +   // no warn, getX() wipes out null info
+			// fields from other types, don't warn
+			"    	if (new Y().getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getY().yField1 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"    	if (getX().field0 == null && Y.yField1.toString() == \"\"){}\n" +  // no warn
+			"  }\n" +
+			"}\n" +
+			"class Y<K>{\n" +
+			"	Y getY(){ return new Y();}\n" +
+			"	X getX(){ return new X();}\n" +
+			"   static Object yField1;\n" +
+			"}"},
+		null,
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 10)\n" + 
+		"	if (new Y().getX().field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                                       ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 11)\n" + 
+		"	if (getX().field0 == null && X.field0.toString() == \"\"){}\n" + 
+		"	                               ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 12)\n" + 
+		"	if (getX().field0 == null && this.field0.toString() == \"\"){}\n" + 
+		"	                                  ^^^^^^\n" + 
+		"Potential null pointer access: The field field0 may be null at this location\n" + 
+		"----------\n",
+		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+//null analysis -- simple case for field of parent type
+public void testBug247564j() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X extends Y {\n" +
+			"  private Object fieldx;\n" +
+			"	 void goo(Object var) {\n" +
+			"    	if (fieldx == null && fieldy.toString() == \"\"){}\n" + // don't flag fieldy, nothing known
+			"  }\n" +
+			"}\n" +
+			"class Y{\n" +
+			"	protected Object fieldy = null;\n" +
+			"}\n" +
+			""},
+		""
+	);
+}
+
+// null analysis -- simple case for field in try-finally
+public void testBug247564k() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  private Object f;\n" +
+			"	 void goo(Object var) {\n" +
+			"		try {\n" +
+			"			int i = 10;\n" +
+			"			while (i<20){\n" +
+			"				if (i == 15) {\n" +
+			"					f = null;\n" +
+			"					break;\n" +
+			"				}\n" +
+			"				i++;\n" +
+			"			}\n" +
+			"			return;\n" +
+			"		} finally {\n" +
+			"			if (f != null && f.hashCode() == 0){}\n" +
+			"		}\n" +
+			"  }\n" +
+			"}\n"},
+		""
+	);
+}
+
+// null analysis -- simple case for field in try-finally
+// presence or absence of throw should not affect the behaviour
+public void testBug247564k_1() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  private Object f;\n" +
+			"	 void goo(Object var) throws Exception{\n" +
+			"		try {\n" +
+			"			int i = 10;\n" +
+			"		} catch(Exception e) {\n" +
+			"			f = null;\n" +
+			"			throw e;\n" +
+			"		} finally {\n" +
+			"			if (f != null && f.hashCode() == 0){}\n" +
+			"		}\n" +
+			"  }\n" +
+			"}\n"},
+		""
+	);
+}
+
+// null analysis -- simple case for field in try-finally
+// presence or absence of method call in finally should not affect the behaviour
+public void testBug247564k_2() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  private Object f;\n" +
+			"	 void gooCalls(){}\n" +
+			"	 void goo(Object var) throws Exception{\n" +
+			"		try {\n" +
+			"			if (f != null) {}\n" +
+			"		} finally {\n" +
+			"			if (f != null ) {\n" +
+			"				gooCalls();\n" +
+			"				f.toString();\n" +
+			"			}\n" +	// silent
+			"		}\n" +
+			"  }\n" +
+			"}\n"},
+		""
+	);
+}
+
+// null analysis -- simple case for constant field in try-catch-finally
+// presence or absence of method call in finally should not affect the behaviour
+public void testBug247564k_3() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"  private static final Object f = null;\n" +
+			"	 void gooCalls() throws NumberFormatException{}\n" +
+			"	 void goo(Object var) throws Exception{\n" +
+			"		try {\n" +
+			"			gooCalls();\n" +
+			"		} catch(NumberFormatException e) {\n" +
+			"			if (f.hashCode() == 0){}\n" +
+			"		} finally {\n" +
+			"			gooCalls();\n" +
+			"			if (f.hashCode() == 0){}\n" +
+			"		}\n" +
+			"  }\n" +
+			"}\n"},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 8)\n" + 
+		"	if (f.hashCode() == 0){}\n" + 
+		"	    ^\n" + 
+		"Null pointer access: The field f can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 11)\n" + 
+		"	if (f.hashCode() == 0){}\n" + 
+		"	    ^\n" + 
+		"Null pointer access: The field f can only be null at this location\n" + 
+		"----------\n"
+	);
+}
+
+// null analysis -- potentially redundant checks against the same field
+public void testBug247564l_1() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"    private Object f;\n" +
+			"	 int foo() throws Exception{\n" +
+			"		 if (f == null && f != null)\n" +
+			"            return 13;\n" +
+			"        return -13;\n" +
+			"    }\n" +
+			"	 int goo() throws Exception{\n" +
+			"		 if (f == null && f == null)\n" +
+			"            return 14;\n" +
+			"        return -14;\n" +
+			"    }\n" +
+			"	 boolean hoo() throws Exception{\n" +
+			"		 if (f == null)\n" +
+			"            return f != null;\n" +
+			"        return f == null;\n" +
+			"    }\n" +
+			"}\n"},
+		""
+	);
+}
+
+// null analysis -- fields assigned a def. non null value in a loop
+// comment 121
+public void testBug247564l_2() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"    private Object field;\n" +
+			"	 void foo() throws Exception{\n" +
+			"		 if (field != null) field.hashCode();\n" +
+			"        int i = 10;\n" +
+			"       while (i<20) {\n" +
+			"			if (field == null) field = new Object();\n" +
+			"			field.toString();\n" +	// should not warn
+			"			i++;\n" +
+			"    	}\n" +
+			"    }\n" +
+			"}\n"},
+		""
+	);
+}
+
+// null analysis -- checked and unchecked exceptions
+public void testBug247564m() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"class MyException extends Exception{}" +
+			"public class X {\n" +
+			"  private Object f;\n" +
+			"	 void gooCalls() throws MyException{}\n" +
+			"	 void goo(){\n" +
+			"		try {\n" +
+			"			if (f == null)  return;\n" +
+			"			gooCalls();\n" +
+			"		} catch(MyException e) {\n" +	// checked Exception	
+			"			f.toString();\n" +			// silent - at gooCalls() in 'try', f is not going to be null
+			"		} catch(NumberFormatException e) {\n" +	// unchecked Exception	
+			"			f.toString();\n" +			// could have come from anywhere, f can be null as doubted in 'try'
+			"		}\n" +
+			"  }\n" +
+			"}\n"},
+		"----------\n" + 
+		"1. WARNING in X.java (at line 1)\n" + 
+		"	class MyException extends Exception{}public class X {\n" + 
+		"	      ^^^^^^^^^^^\n" + 
+		"The serializable class MyException does not declare a static final serialVersionUID field of type long\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 11)\n" + 
+		"	f.toString();\n" + 
+		"	^\n" + 
+		"Potential null pointer access: The field f may be null at this location\n" + 
+		"----------\n"
+	);
+}
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index a67f3cc..89562a4 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -3404,7 +3404,12 @@
 					setSeverity(CompilerOptions.OPTION_ReportRedundantNullCheck, ProblemSeverities.Ignore, isEnabling);
 				}
 				return;
-			}
+			} else if (token.equals("nullFields")) { //$NON-NLS-1$
+				this.options.put(
+						CompilerOptions.OPTION_IncludeFieldsInNullAnalysis,
+						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+				return;
+			} 
 			break;
 		case 'o' :
 			if (token.equals("over-sync") /*|| token.equals("syncOverride")*/) { //$NON-NLS-1$ 
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 2a5f956..e2e6a74 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -307,6 +307,7 @@
 \      noEffectAssign     + assignment without effect\n\
 \      null                 potential missing or redundant null check\n\
 \      nullDereference    + missing null check\n\
+\      nullFields    	  + null analysis for fields\n\
 \      over-ann             missing @Override annotation (superclass)\n\
 \      paramAssign          assignment to a parameter\n\
 \      pkgDefaultMethod   + attempt to override package-default method\n\
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 6b2f414..d31e466 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -1281,6 +1281,26 @@
     /** @since 3.4 */
     int UnusedTypeArgumentsForConstructorInvocation = MethodRelated + 660;
 
+    /**
+	 * Null analysis for fields
+	 */
+    /** @since 3.8*/
+	int NullFieldReference = Internal + FieldRelated + 670;
+	/** @since 3.8*/
+	int PotentialNullFieldReference = Internal + FieldRelated + 671;
+	/** @since 3.8*/
+	int RedundantNullCheckOnNullField = Internal + FieldRelated + 672;
+	/** @since 3.8*/
+	int NullFieldComparisonYieldsFalse = Internal + FieldRelated + 673;
+	/** @since 3.8*/
+	int RedundantNullCheckOnNonNullField = Internal + FieldRelated + 674;
+	/** @since 3.8*/
+	int NonNullFieldComparisonYieldsFalse = Internal + FieldRelated + 675;
+	/** @since 3.8*/
+	int RedundantFieldNullAssignment = Internal + FieldRelated + 676;
+	/** @since 3.8*/
+	int NullFieldInstanceofYieldsFalse = Internal + FieldRelated + 677;
+	
 	/**
 	 * Corrupted binaries
 	 */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 5035d83..a7e3ca7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -3934,6 +3934,7 @@
 
 		// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
 		// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+		// see also https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564#c65
 		this.codeStream.maxFieldCount = aType.scope.outerMostClassScope().referenceType().maxFieldCount;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index ea1af7b..a5c7405 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -43,43 +43,46 @@
 	// 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 var = this.lhs.variableBinding(currentScope);
 	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
 		this.expression.checkNPE(currentScope, flowContext, flowInfo);
 	}
 	
 	FlowInfo preInitInfo = null;
-	boolean shouldAnalyseResource = local != null 
+	LocalVariableBinding localToAnalyseAsResource = null;
+	if (var instanceof LocalVariableBinding 
 			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
 			&& (FakedTrackingVariable.isAnyCloseable(this.expression.resolvedType)
-					|| this.expression.resolvedType == TypeBinding.NULL);
-	if (shouldAnalyseResource) {
+					|| this.expression.resolvedType == TypeBinding.NULL)) {
+		localToAnalyseAsResource = (LocalVariableBinding) var;
+
 		preInitInfo = flowInfo.unconditionalCopy();
 		// analysis of resource leaks needs additional context while analyzing the RHS:
-		FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, local, this.expression);
+		FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, localToAnalyseAsResource, this.expression);
 	}
 	
 	flowInfo = ((Reference) this.lhs)
 		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
 		.unconditionalInits();
 
-	if (shouldAnalyseResource)
-		FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, this, this.expression, local);
-	else
+	if (localToAnalyseAsResource != null) {
+		FakedTrackingVariable.handleResourceAssignment(currentScope, preInitInfo, flowInfo, this, this.expression, localToAnalyseAsResource);
+	} else {
 		FakedTrackingVariable.cleanUpAfterAssignment(currentScope, this.lhs.bits, this.expression);
+	}
 
 	int nullStatus = this.expression.nullStatus(flowInfo);
-	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
+	if (var != null && (var.type.tagBits & TagBits.IsBaseType) == 0) {
 		if (nullStatus == FlowInfo.NULL) {
-			flowContext.recordUsingNullReference(currentScope, local, this.lhs,
+			flowContext.recordUsingNullReference(currentScope, var, this.lhs,
 				FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
 		}
 	}
-	nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, local, nullStatus, this.expression);
-	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
-		flowInfo.markNullStatus(local, nullStatus);
+	nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, var, nullStatus, this.expression);
+	if (var != null && (var.type.tagBits & TagBits.IsBaseType) == 0) {
+		flowInfo.markNullStatus(var, nullStatus);
 		if (flowContext.initsOnFinally != null)
-			flowContext.initsOnFinally.markNullStatus(local, nullStatus);
+			flowContext.initsOnFinally.markNullStatus(var, nullStatus);
 	}
 	return flowInfo;
 }
@@ -233,4 +236,7 @@
 public LocalVariableBinding localVariableBinding() {
 	return this.lhs.localVariableBinding();
 }
+public VariableBinding variableBinding(Scope scope) {
+	return this.lhs.variableBinding(scope);
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index 90b2f96..c61629e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -37,6 +37,7 @@
 			flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo);
 		}
 	}
+
 	if (this.explicitDeclarations > 0) // if block has its own scope analyze tracking vars now:
 		this.scope.checkUnclosedCloseables(flowInfo, null, null);
 	return flowInfo;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 396276a..03bd333 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -33,6 +33,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 {
@@ -445,6 +446,13 @@
 	return this.expression.localVariableBinding();
 }
 
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#variableBinding(Scope)
+ */
+public VariableBinding variableBinding(Scope scope) {
+	return this.expression.variableBinding(scope);
+}
+
 public int nullStatus(FlowInfo flowInfo) {
 	return this.expression.nullStatus(flowInfo);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index 9763111..7f47925 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -39,16 +39,16 @@
 			// TODO: handle all kinds of expressions (cf. also https://bugs.eclipse.org/364326)
 		}
 
-		LocalVariableBinding local = this.left.localVariableBinding();
+		VariableBinding local = this.left.variableBinding(scope);
 		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
 			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, rightStatus, this.left);
 		}
-		local = this.right.localVariableBinding();
+		local = this.right.variableBinding(scope);
 		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
 			checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, leftStatus, 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) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index df21615..87d886d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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,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;
@@ -525,14 +526,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(scope);
 	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);
@@ -872,7 +873,7 @@
 		this.constant != null && this.constant != Constant.NotAConstant)
 	return FlowInfo.NON_NULL; // constant expression cannot be null
 
-	LocalVariableBinding local = localVariableBinding();
+	VariableBinding local = variableBinding(null);
 	if (local != null)
 		return flowInfo.nullStatus(local);
 	return FlowInfo.NON_NULL;
@@ -1112,4 +1113,15 @@
 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...
+ * This is used for the purpose of obtaining a local variable or field binding for the purpose of null analysis.
+ * @param scope This is the current scope in which binding is requested and is needed to ascertain if a static field
+ * belongs to the current type for null analysis. A <code>null</code> value may be passed to this parameter
+*/
+public VariableBinding variableBinding(Scope scope) {
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 30ab54e..a31b905 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -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
+			flowInfo.markNullStatus(this.binding, nullStatus);
+//			this.binding.setNullStatusForStaticFinalField(nullStatus);
+		}
 	}
 	return flowInfo;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index 66f16b6..e8c6fab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -18,9 +18,11 @@
 import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -35,6 +37,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 +671,22 @@
 	}
 	visitor.endVisit(this, scope);
 }
+
+public VariableBinding variableBinding(Scope scope) {
+	if (scope != null) {
+		CompilerOptions options = scope.compilerOptions();
+		if(!options.includeFieldsInNullAnalysis) return null;
+		if (this.receiver.isThis()) return this.binding;
+		if (this.binding != null && this.binding.isStatic()) {
+			// does the static field belong to the current type or one of the enclosing ones?
+			ClassScope enclosingClass = scope.enclosingClassScope();
+			while (enclosingClass != null) {
+				TypeDeclaration type = enclosingClass.referenceContext;
+				if (type != null && (this.binding.declaringClass.original() == type.binding)) return this.binding;
+				enclosingClass = enclosingClass.enclosingClassScope();
+			}
+		}
+	}
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 3382ebb..4687113 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -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(currentScope);
+	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());
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 0dda53f..6469df3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -116,6 +116,11 @@
 		//               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.
+	CompilerOptions options = currentScope.compilerOptions();
+	if(options.includeFieldsInNullAnalysis)
+		flowInfo.resetNullInfoForFields();
 	return flowInfo;
 }
 public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index a9f98e2..95bb17b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -1070,4 +1070,32 @@
 public String unboundReferenceErrorName() {
 	return new String(this.tokens[0]);
 }
+
+public VariableBinding variableBinding(Scope scope) {
+	// if this is a *static* field and its actualResolvedType is the type in which we currently are asking for the binding,
+	// we can safely return the field binding
+	if (scope != null) {
+		CompilerOptions options = scope.compilerOptions();
+		if(!options.includeFieldsInNullAnalysis) return null;
+		if (this.binding != null && (this.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+			FieldBinding fieldBinding;
+			if (this.otherBindings == null) {
+				fieldBinding = (FieldBinding) this.binding;
+			} else {
+				fieldBinding = this.otherBindings[this.otherBindings.length - 1];
+			}
+			if (fieldBinding.isStatic()) {
+				// does the static field belong to the current type or one of the enclosing ones?
+				ClassScope enclosingClass = scope.enclosingClassScope();
+				while (enclosingClass != null) {
+					TypeDeclaration type = enclosingClass.referenceContext;
+					if (type != null && fieldBinding.declaringClass.original() == type.binding)
+						return fieldBinding;
+					enclosingClass = enclosingClass.enclosingClassScope();
+				}
+			}
+		}
+	}
+	return super.variableBinding(scope);
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index f8955db..18c1ebf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -143,7 +143,7 @@
 		} catch (NullPointerException npe) {
 			// chain of references in try-block has several potential nulls;
 			// any null means we cannot perform the following check
-			return;			
+			return;
 		}
 		if ((tagBits & TagBits.AnnotationNonNull) != 0) {
 			flowContext.recordNullityMismatch(scope, this.expression, nullStatus, methodBinding.returnType);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index d625d5b..f0891de 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -806,6 +806,20 @@
 	return null;
 }
 
+public VariableBinding variableBinding(Scope scope) {
+	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
+		case Binding.FIELD : 
+			// reading a field
+			if (scope != null) {
+				CompilerOptions options = scope.compilerOptions();
+				if(!options.includeFieldsInNullAnalysis) return null;
+			}			
+			//$FALL-THROUGH$
+		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)) {
@@ -858,11 +872,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
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 8f68b7c..66c17f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -59,7 +59,6 @@
 	public static final int COMPLAINED_FAKE_REACHABLE = 1;
 	public static final int COMPLAINED_UNREACHABLE = 2;
 	
-
 /** Analysing arguments of MessageSend, ExplicitConstructorCall, AllocationExpression. */
 protected void analyseArguments(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, MethodBinding methodBinding, Expression[] arguments)
 {
@@ -98,12 +97,12 @@
 
 /** Check null-ness of 'local' against a possible null annotation */
 protected int checkAssignmentAgainstNullAnnotation(BlockScope currentScope, FlowContext flowContext,
-												   LocalVariableBinding local, int nullStatus, Expression expression)
+												   VariableBinding var, int nullStatus, Expression expression)
 {
-	if (local != null
-			&& (local.tagBits & TagBits.AnnotationNonNull) != 0
+	if (var != null
+			&& (var.tagBits & TagBits.AnnotationNonNull) != 0
 			&& nullStatus != FlowInfo.NON_NULL) {
-		flowContext.recordNullityMismatch(currentScope, expression, nullStatus, local.type);
+		flowContext.recordNullityMismatch(currentScope, expression, nullStatus, var.type);
 		nullStatus=FlowInfo.NON_NULL;
 	}
 	return nullStatus;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 4b32c61..a3b569e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -43,7 +43,7 @@
 	public MethodScope initializerScope;
 	public MethodScope staticInitializerScope;
 	public boolean ignoreFurtherInvestigation = false;
-	public int maxFieldCount;
+	public int maxFieldCount; // maximum cumulative number of fields of this type and its inners (see updateMaxFieldCount())
 	public int declarationSourceStart;
 	public int declarationSourceEnd;
 	public int bodyStart;
@@ -199,7 +199,6 @@
 			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
 		}
 		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
-		updateMaxFieldCount(); // propagate down the max field count
 		internalAnalyseCode(flowContext, flowInfo);
 	} catch (AbortType e) {
 		this.ignoreFurtherInvestigation = true;
@@ -215,9 +214,7 @@
 	if (this.ignoreFurtherInvestigation)
 		return;
 	try {
-		// propagate down the max field count
-		updateMaxFieldCount();
-		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount));
+		internalAnalyseCode(null, FlowInfo.initial(this.scope.outerMostClassScope().referenceType().maxFieldCount));
 	} catch (AbortType e) {
 		this.ignoreFurtherInvestigation = true;
 	}
@@ -237,7 +234,6 @@
 			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
 		}
 		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
-		updateMaxFieldCount(); // propagate down the max field count
 		internalAnalyseCode(flowContext, flowInfo);
 	} catch (AbortType e) {
 		this.ignoreFurtherInvestigation = true;
@@ -654,6 +650,11 @@
 				staticInitializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
 				/*}*/
 				staticFieldInfo = field.analyseCode(this.staticInitializerScope, staticInitializerContext, staticFieldInfo);
+				if (field.binding != null && this.scope.compilerOptions().includeFieldsInNullAnalysis
+						&& ((field.binding.modifiers & ClassFileConstants.AccFinal) != 0)) {
+					// we won't reset null Info for constant fields
+					staticFieldInfo.updateConstantFieldsMask(field.binding);
+				}
 				// in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
 				// branch, since the previous initializer already got the blame.
 				if (staticFieldInfo == FlowInfo.DEAD_END) {
@@ -690,7 +691,18 @@
 	}
 	if (this.methods != null) {
 		UnconditionalFlowInfo outerInfo = flowInfo.unconditionalFieldLessCopy();
-		FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
+		UnconditionalFlowInfo staticFieldUnconditionalInfo = staticFieldInfo.unconditionalInits();
+		FlowInfo constructorInfo;
+		if (this.scope.compilerOptions().includeFieldsInNullAnalysis) {
+			flowInfo.addNullInfoFrom(staticFieldUnconditionalInfo.discardNonFieldInitializations());
+			flowInfo.addConstantFieldsMask(staticFieldUnconditionalInfo);	// prevent resetting null info for constant fields inside methods
+			flowInfo.resetNullInfoForFields();	// only preserve null info for constant fields
+			constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(flowInfo);
+			constructorInfo.addConstantFieldsMask(staticFieldUnconditionalInfo); // prevent resetting null info for constant fields inside c'tor too
+		} else {
+			constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
+		}
+		
 		for (int i = 0, count = this.methods.length; i < count; i++) {
 			AbstractMethodDeclaration method = this.methods[i];
 			if (method.ignoreFurtherInvestigation)
@@ -701,7 +713,7 @@
 					((Clinit)method).analyseCode(
 						this.scope,
 						staticInitializerContext,
-						staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
+						staticFieldUnconditionalInfo.addInitializationsFrom(outerInfo));
 				} else { // constructor
 					((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode());
 				}
@@ -1045,8 +1057,6 @@
 				}
 			} while ((current = current.enclosingType()) != null);
 		}
-		// this.maxFieldCount might already be set
-		int localMaxFieldCount = 0;
 		int lastVisibleFieldID = -1;
 		boolean hasEnumConstants = false;
 		FieldDeclaration[] enumConstantsWithoutBody = null;
@@ -1056,6 +1066,38 @@
 				this.typeParameters[i].resolve(this.scope);
 			}
 		}
+		// field count from enclosing and supertypes should be included in maxFieldCount,
+		// to make field-ids unique among all fields in scope.
+		// 1.: enclosing:
+		TypeBinding original = sourceType.original();
+		int fieldAnalysisOffset = 0;
+		if (original instanceof NestedTypeBinding) {
+			// note: local types have no enclosingType in the AST but only in the binding:
+			fieldAnalysisOffset = ((NestedTypeBinding)original).enclosingType.cumulativeFieldCount;
+		}
+		// 2.: supers:
+		ReferenceBinding superClassBinding = sourceType.superclass;
+		while (superClassBinding != null) {
+			FieldBinding[] unResolvedFields = superClassBinding.unResolvedFields();
+			if (unResolvedFields != null) {
+				for (int i=unResolvedFields.length-1; i>=0; i--) {
+ 					// if the field is an initializer we do not want to update the count 
+					switch (unResolvedFields[i].kind()) {
+						case AbstractVariableDeclaration.FIELD:
+						case AbstractVariableDeclaration.ENUM_CONSTANT:
+							fieldAnalysisOffset++;
+					}
+				}
+			}
+			fieldAnalysisOffset += findFieldCountFromSuperInterfaces(superClassBinding.superInterfaces());
+			superClassBinding = superClassBinding.superclass();
+		}
+		ReferenceBinding[] superInterfacesBinding = sourceType.superInterfaces;
+		fieldAnalysisOffset += findFieldCountFromSuperInterfaces(superInterfacesBinding);
+		sourceType.cumulativeFieldCount += fieldAnalysisOffset;
+		sourceType.fieldAnalysisOffset = fieldAnalysisOffset;
+		this.maxFieldCount = sourceType.cumulativeFieldCount;
+
 		if (this.memberTypes != null) {
 			for (int i = 0, count = this.memberTypes.length; i < count; i++) {
 				this.memberTypes[i].resolve(this.scope);
@@ -1087,7 +1129,6 @@
 								&& TypeBinding.LONG == fieldBinding.type) {
 							needSerialVersion = false;
 						}
-						localMaxFieldCount++;
 						lastVisibleFieldID = field.binding.id;
 						break;
 
@@ -1098,9 +1139,6 @@
 				field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
 			}
 		}
-		if (this.maxFieldCount < localMaxFieldCount) {
-			this.maxFieldCount = localMaxFieldCount;
-		}
 		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);
@@ -1187,6 +1225,19 @@
 	}
 }
 
+private int findFieldCountFromSuperInterfaces(ReferenceBinding[] superinterfaces) {
+	int numOfFields = 0;
+	if (superinterfaces == null)
+		return numOfFields ;
+	for (int i = 0; i < superinterfaces.length; i++) {
+		FieldBinding[] unResolvedFields = superinterfaces[i].unResolvedFields();
+		// no need to check field kinds as initializer cannot occur inside interfaces
+		numOfFields += unResolvedFields != null ? unResolvedFields.length : 0;
+		numOfFields += findFieldCountFromSuperInterfaces(superinterfaces[i].superInterfaces());		
+	}
+	return numOfFields;
+}
+
 /**
  * Resolve a local type declaration
  */
@@ -1447,12 +1498,11 @@
 /**
  * MaxFieldCount's computation is necessary so as to reserve space for
  * the flow info field portions. It corresponds to the maximum amount of
- * fields this class or one of its innertypes have.
+ * accumulated fields this class or one of its innertypes have.
  *
- * During name resolution, types are traversed, and the max field count is recorded
- * on the outermost type. It is then propagated down during the flow analysis.
- *
- * This method is doing either up/down propagation.
+ * During buildFields() accumulative field counts are gather per class,
+ * which include fields of outer and super types.
+ * During resolve, the maximum of these counts is collected inside out.
  */
 void updateMaxFieldCount() {
 	if (this.binding == null)
@@ -1460,8 +1510,6 @@
 	TypeDeclaration outerMostType = this.scope.outerMostClassScope().referenceType();
 	if (this.maxFieldCount > outerMostType.maxFieldCount) {
 		outerMostType.maxFieldCount = this.maxFieldCount; // up
-	} else {
-		this.maxFieldCount = outerMostType.maxFieldCount; // down
 	}
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
index 5cb4166..5128a63 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -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
@@ -73,119 +74,118 @@
 	return this.initsWhenTrue;
 }
 
-public boolean isDefinitelyAssigned(FieldBinding field) {
+public boolean isDefinitelyAssigned(VariableBinding var) {
 
-	return this.initsWhenTrue.isDefinitelyAssigned(field)
-			&& this.initsWhenFalse.isDefinitelyAssigned(field);
+	return this.initsWhenTrue.isDefinitelyAssigned(var)
+			&& this.initsWhenFalse.isDefinitelyAssigned(var);
 }
 
-public boolean isDefinitelyAssigned(LocalVariableBinding local) {
-
-	return this.initsWhenTrue.isDefinitelyAssigned(local)
-			&& 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);
 }
 
-public boolean isPotentiallyAssigned(FieldBinding field) {
-	return this.initsWhenTrue.isPotentiallyAssigned(field)
-			|| this.initsWhenFalse.isPotentiallyAssigned(field);
+public boolean isPotentiallyAssigned(VariableBinding var) {
+	return this.initsWhenTrue.isPotentiallyAssigned(var)
+			|| this.initsWhenFalse.isPotentiallyAssigned(var);
 }
 
-public boolean isPotentiallyAssigned(LocalVariableBinding local) {
-	return this.initsWhenTrue.isPotentiallyAssigned(local)
-			|| 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);
 }
 
-public void markAsDefinitelyAssigned(FieldBinding field) {
-	this.initsWhenTrue.markAsDefinitelyAssigned(field);
-	this.initsWhenFalse.markAsDefinitelyAssigned(field);
+public void markAsDefinitelyAssigned(VariableBinding var) {
+	this.initsWhenTrue.markAsDefinitelyAssigned(var);
+	this.initsWhenFalse.markAsDefinitelyAssigned(var);
 }
 
-public void markAsDefinitelyAssigned(LocalVariableBinding local) {
-	this.initsWhenTrue.markAsDefinitelyAssigned(local);
-	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 updateConstantFieldsMask(FieldBinding field) {
+	this.initsWhenTrue.updateConstantFieldsMask(field);
+	this.initsWhenFalse.updateConstantFieldsMask(field);
+}
+
+public void addConstantFieldsMask(UnconditionalFlowInfo other) {
+	this.initsWhenTrue.addConstantFieldsMask(other);
+	this.initsWhenFalse.addConstantFieldsMask(other);
+}
+
+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 +243,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));
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
index 12b5edc..3c62413 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
@@ -34,7 +34,7 @@
 	VariableBinding[] finalVariables;
 	int assignCount;
 
-	LocalVariableBinding[] nullLocals;
+	VariableBinding[] nullVariables;
 	Expression[] nullReferences;
 	int[] nullCheckTypes;
 	int nullCount;
@@ -59,13 +59,13 @@
 		boolean complained = false; // remember if have complained on this final assignment
 		if (variable instanceof FieldBinding) {
 			// final field
-			if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) {
+			if (flowInfo.isPotentiallyAssigned(variable)) {
 				complained = true;
 				scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, this.finalAssignments[i]);
 			}
 		} else {
 			// final local variable
-			if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
+			if (flowInfo.isPotentiallyAssigned(variable)) {
 				complained = true;
 				scope.problemReporter().duplicateInitializationOfFinalLocal(
 					(LocalVariableBinding) variable,
@@ -90,29 +90,28 @@
 		for (int i = 0; i < this.nullCount; i++) {
 			if (this.nullCheckTypes[i] == ASSIGN_TO_NONNULL)
 				this.parent.recordNullityMismatch(scope, this.nullReferences[i],
-						flowInfo.nullStatus(this.nullLocals[i]), this.expectedTypes[i]);
+						flowInfo.nullStatus(this.nullVariables[i]), this.expectedTypes[i]);
 			else
-				this.parent.recordUsingNullReference(scope, this.nullLocals[i],
+				this.parent.recordUsingNullReference(scope, this.nullVariables[i],
 						this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
-
 		}
 	}
 	else { // no enclosing loop, be as precise as possible right now
 		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;
@@ -126,27 +125,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)) {
@@ -154,14 +153,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;
@@ -170,11 +169,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;
 				case ASSIGN_TO_NONNULL:
@@ -229,7 +228,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
@@ -243,14 +242,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_BY_NULLANALYSIS);
 								}
 							} 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_BY_NULLANALYSIS);
@@ -262,11 +261,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_BY_NULLANALYSIS);
@@ -274,34 +273,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_BY_NULLANALYSIS);
 									}
 									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;
@@ -313,7 +312,7 @@
 							return;
 						}
 						if (flowInfo.canOnlyBeNull(local)) {
-							scope.problemReporter().localVariableNullReference(local, reference);
+							scope.problemReporter().variableNullReference(local, reference);
 							return;
 						}
 						break;
@@ -328,14 +327,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_BY_NULLANALYSIS);
 								}
 							} 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_BY_NULLANALYSIS);
@@ -352,11 +351,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_BY_NULLANALYSIS);
@@ -364,34 +363,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_BY_NULLANALYSIS);
 									}
 									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;
@@ -400,11 +399,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)) {
@@ -436,17 +435,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,
@@ -455,7 +454,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;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index 98caf30..33fd6c5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -588,7 +588,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
 }
@@ -631,7 +631,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)) {
@@ -643,14 +643,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_BY_NULLANALYSIS);
 					}
 				} 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_BY_NULLANALYSIS);
@@ -670,11 +670,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_BY_NULLANALYSIS);
@@ -682,34 +682,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_BY_NULLANALYSIS);
 						}
 						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;
@@ -720,11 +720,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;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index b931372..422f0ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -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 {
 
@@ -52,7 +53,7 @@
 		DEAD_END = new UnconditionalFlowInfo();
 		DEAD_END.tagBits = UNREACHABLE;
 	}
-
+	
 /**
  * Add other inits to this flow info, then return this. The operation semantics
  * are to match as closely as possible the application to this flow info of all
@@ -94,39 +95,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);
 }
 
 /**
@@ -138,6 +142,7 @@
 	public static UnconditionalFlowInfo initial(int maxFieldCount) {
 		UnconditionalFlowInfo info = new UnconditionalFlowInfo();
 		info.maxFieldCount = maxFieldCount;
+		info.constantFieldsMask = 0L;
 		return info;
 	}
 
@@ -164,196 +169,202 @@
 	abstract public FlowInfo initsWhenTrue();
 
 	/**
-	 * Check status of definite assignment for a field.
+	 * Check status of definite assignment for a local or field.
 	 */
-	 abstract public boolean isDefinitelyAssigned(FieldBinding field);
+	 abstract public boolean isDefinitelyAssigned(VariableBinding var);
+
+/**
+ * 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(VariableBinding binding);
+
+/**
+ * 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(VariableBinding binding);
+
+/**
+ * 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(VariableBinding binding);
 
 	/**
-	 * Check status of definite assignment for a local.
-	 */
-	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
- */
-	public abstract boolean isDefinitelyNonNull(LocalVariableBinding local);
-
-/**
- * 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
- */
-public abstract boolean isDefinitelyNull(LocalVariableBinding local);
-
-/**
- * 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
- */
-public abstract boolean isDefinitelyUnknown(LocalVariableBinding local);
-
-	/**
-	 * Check status of potential assignment for a field.
-	 */
-	 abstract public boolean isPotentiallyAssigned(FieldBinding field);
-
-	/**
-	 * Check status of potential assignment for a local variable.
+	 * Check status of potential assignment for a local variable or a field.
 	 */
 
-	 abstract public boolean isPotentiallyAssigned(LocalVariableBinding field);
+	 abstract public boolean isPotentiallyAssigned(VariableBinding var);
 
 /**
- * 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.
+	 * Record a field or local got definitely assigned to a non-null value.
 	 */
-	abstract public void markAsDefinitelyAssigned(FieldBinding field);
+	abstract public void markAsDefinitelyNonNull(VariableBinding binding);
 
 	/**
-	 * Record a local got definitely assigned to a non-null value.
+	 * Record a field or local got definitely assigned to null.
 	 */
-	abstract public void markAsDefinitelyNonNull(LocalVariableBinding local);
+	abstract public void markAsDefinitelyNull(VariableBinding binding);
 
 	/**
-	 * Record a local got definitely assigned to null.
+	 * Reset all null-information about a given field or local.
 	 */
-	abstract public void markAsDefinitelyNull(LocalVariableBinding local);
+	abstract public void resetNullInfo(VariableBinding binding);
 
 	/**
-	 * Reset all null-information about a given local.
+	 *  variant of {@link #resetNullInfo(VariableBinding)} for resetting null info for all fields
+	 *  Note that each fields status after the reset will become def. unknown i.e. 1001
+	 *  Also this method does not reset constant fields, which are identified by {@link #constantFieldsMask}
 	 */
-	abstract public void resetNullInfo(LocalVariableBinding local);
+	abstract public void resetNullInfoForFields();
+	
+	/**
+	 * exclude a new field from being reset by {@link #resetNullInfoForFields()}
+	 */
+	abstract public void updateConstantFieldsMask(FieldBinding field);
+	
+	/**
+	 * add the constant fields info from the other flow info
+	 */
+	abstract public void addConstantFieldsMask(UnconditionalFlowInfo other);
+	
+	/**
+	 * 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 unknown (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 markPotentiallyUnknownBit(LocalVariableBinding local);
+	abstract public void markPotentiallyNullBit(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 non-null (set the bit on existing info).
 	 */
-	abstract public void markPotentiallyNullBit(LocalVariableBinding local);
+	abstract public void markPotentiallyNonNullBit(VariableBinding binding);
 
 	/**
-	 * Record a local may have got assigned to non-null (set the bit on existing info).
+	 * Record a local or field got definitely assigned.
 	 */
-	abstract public void markPotentiallyNonNullBit(LocalVariableBinding local);
-
-	/**
-	 * Record a local got definitely assigned.
-	 */
-	abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
+	abstract public void markAsDefinitelyAssigned(VariableBinding var);
 
 /**
- * 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;
@@ -601,14 +612,14 @@
  * 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);
 
 /**
  * Resets the definite and potential initialization info for the given local variable
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index cfab201..cbf63e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -48,7 +48,7 @@
 	VariableBinding finalVariables[];
 	int assignCount = 0;
 
-	LocalVariableBinding[] nullLocals;
+	VariableBinding[] nullVariables;
 	Expression[] nullReferences;
 	int[] nullCheckTypes;
 	int nullCount;
@@ -101,14 +101,14 @@
 		if (variable == null) continue;
 		boolean complained = false; // remember if have complained on this final assignment
 		if (variable instanceof FieldBinding) {
-			if (flowInfo.isPotentiallyAssigned((FieldBinding) variable)) {
+			if (flowInfo.isPotentiallyAssigned(variable)) {
 				complained = true;
 				scope.problemReporter().duplicateInitializationOfBlankFinalField(
 					(FieldBinding) variable,
 					this.finalAssignments[i]);
 			}
 		} else {
-			if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
+			if (flowInfo.isPotentiallyAssigned(variable)) {
 				complained = true;
 				scope.problemReporter().duplicateInitializationOfFinalLocal(
 					(LocalVariableBinding) variable,
@@ -145,7 +145,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]) {
@@ -155,11 +155,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;
@@ -171,11 +171,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;
@@ -184,11 +184,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;
@@ -203,27 +203,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)) {
@@ -231,14 +231,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;
@@ -248,7 +248,7 @@
 				case MAY_NULL:
 					if (flowInfo.isDefinitelyNull(local)) {
 						this.nullReferences[i] = null;
-						scope.problemReporter().localVariableNullReference(local, expression);
+						scope.problemReporter().variableNullReference(local, expression);
 						continue;
 					}
 					break;
@@ -267,7 +267,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:
@@ -275,11 +275,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;
@@ -294,27 +294,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)) {
@@ -322,14 +322,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;
@@ -339,12 +339,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;
@@ -476,27 +476,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)) {
@@ -508,14 +508,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_BY_NULLANALYSIS);
 					}
 				} 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_BY_NULLANALYSIS);
@@ -524,14 +524,14 @@
 			} 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_BY_NULLANALYSIS);
 					}
 				} 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_BY_NULLANALYSIS);
@@ -575,11 +575,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_BY_NULLANALYSIS);
@@ -587,34 +587,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_BY_NULLANALYSIS);
 						}
 						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;
@@ -633,11 +633,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);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java
index 1470795..a70fc4d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 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
@@ -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
@@ -40,6 +41,8 @@
  */
 public NullInfoRegistry(UnconditionalFlowInfo upstream) {
 	this.maxFieldCount = upstream.maxFieldCount;
+	this.constantFieldsMask = upstream.constantFieldsMask;
+	this.extraConstantFieldMask = upstream.extraConstantFieldMask;
 	if ((upstream.tagBits & NULL_FLAG_MASK) != 0) {
 		long u1, u2, u3, u4, nu2, nu3, nu4;
 		this.nullBit2 = (u1 = upstream.nullBit1)
@@ -87,6 +90,8 @@
 	this.nullBit2 |= other.nullBit2;
 	this.nullBit3 |= other.nullBit3;
 	this.nullBit4 |= other.nullBit4;
+	this.maxFieldCount = other.maxFieldCount;
+	this.addConstantFieldsMask(other);
 	if (other.extra != null) {
 		if (this.extra == null) {
 			this.extra = new long[extraLength][];
@@ -116,13 +121,21 @@
 	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 && ((local.modifiers & AccConstant) == AccConstant)) {
+	    	// non-final fields may be modified in separate threads and we cannot be sure about their
+	    	// definite nullness. Hence, marking as definitely unknown to avoid deferring null check for these fields.
+	    	this.markAsDefinitelyUnknown(local);
+	    	return;
+    	} else {
+    		position = local.getAnalysisId(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 +174,20 @@
 	}
 }
 
-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 && ((local.modifiers & AccConstant) == AccConstant)) {
+	    	// non-final fields may be modified in separate threads and we cannot be sure about their
+	    	// definite nullness. Hence, marking as definitely unknown to avoid deferring null check for these fields.
+	    	this.markAsDefinitelyUnknown(local);
+	    	return;
+    	} else {
+    		position = local.getAnalysisId(this.maxFieldCount);
+    	}
+    	if (position < BitCacheSize) { // use bits
     		// set assigned non null
     		this.nullBit3 |= (1L << position);
     		if (COVERAGE_TEST_FLAG) {
@@ -207,13 +227,21 @@
 }
 // 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 && ((local.modifiers & AccConstant) == AccConstant)) {
+    		// non-final fields may be modified in separate threads and we cannot be sure about their
+    		// definite nullness. Hence, marking as potential null.
+    		this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL);
+	    	return;
+    	} else {
+    		position = local.getAnalysisId(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 +280,13 @@
 	}
 }
 
-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;
+    	int position = local.getAnalysisId(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 +435,13 @@
  * 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) {
+    	int position = local.getAnalysisId(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 +482,12 @@
 	}
 }
 
-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) {
+		long mask;
+    	int position = local.getAnalysisId(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 +528,12 @@
 	}
 }
 
-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) {
+    	int position = local.getAnalysisId(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$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index ed1ae7a..4154cf4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -18,11 +18,13 @@
 package org.eclipse.jdt.internal.compiler.flow;
 
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 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.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
 
 /**
  * Record initialization status during definite assignment analysis
@@ -80,17 +82,20 @@
 
 	// extra segments
 	public static final int extraLength = 6;
+	// extra bit fields for larger numbers of fields/variables
+	// extra[0] holds definiteInits values, extra[1] potentialInits, etc.
+	// lifecycle is extra == null or else all extra[]'s are allocated
+	// arrays which have the same size
 	public long extra[][];
-		// extra bit fields for larger numbers of fields/variables
-		// extra[0] holds definiteInits values, extra[1] potentialInits, etc.
-		// lifecycle is extra == null or else all extra[]'s are allocated
-		// arrays which have the same size
-
+	
 	public int maxFieldCount; // limit between fields and locals
 
 	// Constants
 	public static final int BitCacheSize = 64; // 64 bits in a long.
 	public int[] nullStatusChangedInAssert; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448
+	public long constantFieldsMask; // record positions of constant fields so that they don't get reset in resetNullInfoForFields()
+	public long extraConstantFieldMask[]; // extra mask for larger number of fields
+	protected static final int AccConstant = ClassFileConstants.AccStatic|ClassFileConstants.AccFinal;
 
 public FlowInfo addInitializationsFrom(FlowInfo inits) {
 	return addInfoFrom(inits, true);
@@ -520,13 +525,13 @@
 	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) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) {
 		// use bits
 		return (
 			(~this.nullBit1
@@ -551,13 +556,13 @@
 		    & (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) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) {
 		// use bits
 		return (this.nullBit1 & this.nullBit3
 			& ((this.nullBit2 & this.nullBit4) | ~this.nullBit2)
@@ -578,13 +583,13 @@
 		    & (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) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) {
 		// use bits
 		return (this.nullBit1 & this.nullBit2
 			& (~this.nullBit3 | ~this.nullBit4)
@@ -622,6 +627,8 @@
 	}
 	copy.tagBits = this.tagBits;
 	copy.maxFieldCount = this.maxFieldCount;
+	copy.constantFieldsMask = this.constantFieldsMask;
+	copy.extraConstantFieldMask = this.extraConstantFieldMask;
 	if (this.extra != null) {
 		int length;
 		copy.extra = new long[extraLength][];
@@ -739,7 +746,7 @@
 	if ((this.tagBits & UNREACHABLE_OR_DEAD) != 0) {
 		return true;
 	}
-	return isDefinitelyAssigned(field.id);
+	return isDefinitelyAssigned(field.getAnalysisId(this.maxFieldCount));
 }
 
 final public boolean isDefinitelyAssigned(LocalVariableBinding local) {
@@ -750,7 +757,22 @@
 	return isDefinitelyAssigned(local.id + this.maxFieldCount);
 }
 
-final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
+final public boolean isDefinitelyAssigned(VariableBinding var) {
+	if (var instanceof FieldBinding) {
+		return this.isDefinitelyAssigned((FieldBinding)var);
+	} else {
+		return this.isDefinitelyAssigned((LocalVariableBinding)var);
+	}
+}
+
+final public boolean isDefinitelyNonNull(VariableBinding local) {
+	boolean isField = local instanceof FieldBinding;
+	if (isField && (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) {
@@ -760,7 +782,7 @@
 			local.constant() != Constant.NotAConstant) { // String instances
 		return true;
 	}
-	int position = local.id + this.maxFieldCount;
+	int position = local.getAnalysisId(this.maxFieldCount);
 	if (position < BitCacheSize) { // use bits
 		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
 			    & (1L << position)) != 0;
@@ -779,14 +801,21 @@
 		    & (1L << (position % BitCacheSize))) != 0;
 }
 
-final public boolean isDefinitelyNull(LocalVariableBinding local) {
+final public boolean isDefinitelyNull(VariableBinding local) {
+	boolean isField = local instanceof FieldBinding;
+	if (isField && (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 = local.getAnalysisId(this.maxFieldCount);
 	if (position < BitCacheSize) { // use bits
 		return ((this.nullBit1 & this.nullBit2
 			        & (~this.nullBit3 | ~this.nullBit4))
@@ -806,13 +835,13 @@
 		    & (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 = local.getAnalysisId(this.maxFieldCount);
 	if (position < BitCacheSize) { // use bits
 		return ((this.nullBit1 & this.nullBit4
 				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
@@ -854,7 +883,7 @@
 }
 
 final public boolean isPotentiallyAssigned(FieldBinding field) {
-	return isPotentiallyAssigned(field.id);
+	return isPotentiallyAssigned(field.getAnalysisId(this.maxFieldCount));
 }
 
 final public boolean isPotentiallyAssigned(LocalVariableBinding local) {
@@ -865,14 +894,22 @@
 	return isPotentiallyAssigned(local.id + this.maxFieldCount);
 }
 
+final public boolean isPotentiallyAssigned(VariableBinding var) {
+	if (var instanceof FieldBinding) {
+	return this.isPotentiallyAssigned((FieldBinding)var);
+	} else {
+		return this.isPotentiallyAssigned((LocalVariableBinding)var);
+	}
+}
+
 // TODO (Ayush) Check why this method does not return true for protected non null (1111)
-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) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) { // use bits
 		// use bits
 		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
 			    & (1L << position)) != 0;
@@ -892,13 +929,13 @@
 }
 
 // TODO (Ayush) Check why this method does not return true for protected null
-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) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) {
 		// use bits
 		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
 			    & (1L << position)) != 0;
@@ -917,13 +954,13 @@
 		    & (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 = local.getAnalysisId(this.maxFieldCount);
 	if (position < BitCacheSize) { // use bits
 		return (this.nullBit4
 			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
@@ -944,14 +981,13 @@
 		    & (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
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) { // use bits
 		return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0;
 	}
 	// use extra vector
@@ -969,13 +1005,13 @@
 		    & (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) {
+	int position = local.getAnalysisId(this.maxFieldCount);
+	if (position < BitCacheSize) {
 		// use bits
 		return (this.nullBit1 & this.nullBit2
 			& (this.nullBit3 ^ this.nullBit4)
@@ -1008,15 +1044,27 @@
 		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) {
+			if ((local.modifiers & AccConstant) == AccConstant) {
+				position = local.getAnalysisId(this.maxFieldCount);
+			} else {
+				// non-final fields may be modified in separate threads and we cannot be sure about their
+				// definite nullness. Hence, marking as definitely unknown to avoid deferring null check for these fields
+				this.markAsDefinitelyUnknown(local);
+				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)
@@ -1105,14 +1153,26 @@
 	}
 }
 
-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) {
+			if ((local.modifiers & AccConstant) == AccConstant) {
+				position = local.getAnalysisId(this.maxFieldCount);
+			} else {
+				// non-final fields may be modified in separate threads and we cannot be sure about their
+				// definite nullness. Hence, marking as potential null.
+				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
@@ -1233,24 +1293,31 @@
 	}
 }
 
-public void markAsDefinitelyAssigned(FieldBinding field) {
+public void markAsDefinitelyAssigned(VariableBinding var) {
 	if (this != DEAD_END)
-		markAsDefinitelyAssigned(field.id);
+		markAsDefinitelyAssigned(var.getAnalysisId(this.maxFieldCount));
 }
 
-public void markAsDefinitelyAssigned(LocalVariableBinding local) {
-	if (this != DEAD_END)
-		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;
     	// position is zero-based
-    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
+    	if (local instanceof FieldBinding) {
+			if ((local.modifiers & AccConstant) == AccConstant) {
+				position = local.getAnalysisId(this.maxFieldCount);
+			} else {
+	    		// non-final fields may be modified in separate threads and we cannot be sure about their
+	    		// definite nullness. Hence, marking as definitely unknown to avoid deferring null check for these fields.
+	    		this.markAsDefinitelyUnknown(local);
+	    		return;
+			}
+    	} else {
+    		position = local.id + this.maxFieldCount;
+    	}
+    	if (position < BitCacheSize) { // use bits
     		// set assigned non null
     		this.nullBit1 |= (mask = 1L << position);
     		this.nullBit3 |= mask;
@@ -1297,14 +1364,26 @@
 	}
 }
 
-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;
     	// position is zero-based
-    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
+    	if (local instanceof FieldBinding) {
+			if ((local.modifiers & AccConstant) == AccConstant) {
+				position = local.getAnalysisId(this.maxFieldCount);
+			} else {
+	    		// non-final fields may be modified in separate threads and we cannot be sure about their
+	    		// definite nullness. Hence, marking as potential null.
+	    		this.markNullStatus(local, FlowInfo.POTENTIALLY_NULL);
+	    		return;
+			}
+    	} else {
+    		position = local.id + this.maxFieldCount;
+    	}
+    	if (position < BitCacheSize) { // use bits
     		// mark assigned null
     		this.nullBit1 |= (mask = 1L << position);
     		this.nullBit2 |= mask;
@@ -1357,14 +1436,13 @@
  */
 // 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;
-		// position is zero-based
-		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
+		int position = local.getAnalysisId(this.maxFieldCount);
+		if (position < BitCacheSize) {
 			// use bits
 			// mark assigned null
 			this.nullBit1 |= (mask = 1L << position);
@@ -1412,12 +1490,12 @@
 	}
 }
 
-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) {
+    	int position = local.getAnalysisId(this.maxFieldCount);
+        if (position < BitCacheSize) {
             // use bits
             this.nullBit1 &= (mask = ~(1L << position));
             this.nullBit2 &= mask;
@@ -1440,17 +1518,126 @@
 	}
 }
 
+public void resetNullInfoForFields() {
+	if (this != DEAD_END) {
+		long mask = (-1L << this.maxFieldCount) | this.constantFieldsMask;
+		// first reset normal bits:
+		this.nullBit1 |= ~mask;
+		this.nullBit2 &= mask;
+		this.nullBit3 &= mask;
+		this.nullBit4 |= ~mask;
+		if (this.maxFieldCount >= BitCacheSize && this.extra != null) {
+			// use extra vector
+			int localsStartIndex = this.maxFieldCount/BitCacheSize - 1;
+			int localsStartOffset = this.maxFieldCount % BitCacheSize;
+			if (this.extraConstantFieldMask != null){
+				for (int vectorIndex = 0; vectorIndex < this.extra[2].length; vectorIndex++) {
+				    if (vectorIndex >= this.extraConstantFieldMask.length) {
+				    	// no constant fields after this, just mask all fields
+				    	if (vectorIndex == localsStartIndex) {
+				    		// some locals, some fields at this vectorIndex
+				    		mask = -1L << localsStartOffset;
+				    	} else {
+				    		// all fields here
+				    		mask = 0L;
+				    	}
+				    } else {
+				    	if (vectorIndex == localsStartIndex) {
+				    		// some locals, some fields at this vectorIndex
+				    		mask = ((-1 << localsStartOffset) | this.extraConstantFieldMask[vectorIndex]);
+				    	} else {
+				    		// all fields here
+				    		mask = 0L | this.extraConstantFieldMask[vectorIndex];
+				    	}
+				    	
+				    }
+					this.extra[2][vectorIndex]
+					    |= ~mask;
+					this.extra[3][vectorIndex] &= mask;
+					this.extra[4][vectorIndex] &= mask;
+					this.extra[5][vectorIndex] |= ~mask;
+				}
+			} else {
+				// no constant fields
+				for (int vectorIndex = 0; vectorIndex < this.extra[2].length; vectorIndex++) {
+				    if (vectorIndex == localsStartIndex) {
+				    	// some locals, some fields at this vectorIndex
+				    	mask = -1L << localsStartOffset;
+				    } else {
+				    	// all fields here
+				    	mask = 0L;
+				    }
+					this.extra[2][vectorIndex]
+					    |= ~mask;
+					this.extra[3][vectorIndex] &= mask;
+					this.extra[4][vectorIndex] &= mask;
+					this.extra[5][vectorIndex] |= ~mask;
+				}
+			}
+		}
+	}
+}
+
+public void updateConstantFieldsMask(FieldBinding field) {
+	int position = field.getAnalysisId(this.maxFieldCount);
+	long mask = 1L << (position % BitCacheSize);
+	if (position < BitCacheSize) {
+		this.constantFieldsMask |= 1L << position; // exclude this field from being reset
+    } else {
+		// use extra vector
+		int vectorIndex = (position / BitCacheSize) - 1;
+		if (this.extraConstantFieldMask == null) {
+			// extra array not created. Create constant field mask bit streams.
+			int length = vectorIndex + 1;
+			this.extraConstantFieldMask = new long[length];
+		}
+		else {
+			int oldLength; // might need to grow the arrays
+			if (vectorIndex >= (oldLength = this.extraConstantFieldMask.length)) {
+				System.arraycopy(this.extraConstantFieldMask, 0, (this.extraConstantFieldMask = new long[vectorIndex + 1]), 0, oldLength);
+			}
+		}
+		this.extraConstantFieldMask[vectorIndex] |= mask; // exclude this field from resetNullInfoForFields
+	}
+}
+
+/**
+ * All the infos originate in TypeDeclaration.analyseCode(). So making sure that this method is called for every info that is sent into
+ * methods/constructors should be sufficient
+ */
+public void addConstantFieldsMask(UnconditionalFlowInfo other) {
+	this.constantFieldsMask |= other.constantFieldsMask;
+    if (other.extraConstantFieldMask != null) {
+    	int oldLength = 0;
+    	int otherLen = other.extraConstantFieldMask.length;
+    	if (this.extraConstantFieldMask != null) {
+    		oldLength = this.extraConstantFieldMask.length;
+	    	if (otherLen >= (oldLength = this.extraConstantFieldMask.length)) {
+				System.arraycopy(this.extraConstantFieldMask, 0, (this.extraConstantFieldMask = new long[otherLen]), 0, oldLength);
+			}
+	    	for (int i = 0; i < this.extraConstantFieldMask.length; i++) {
+				this.extraConstantFieldMask[i] |= other.extraConstantFieldMask[i];
+			}
+    	} else {
+    		this.extraConstantFieldMask = new long[otherLen];
+    	}
+    	for (int i = oldLength; i < otherLen; i++) {
+			this.extraConstantFieldMask[i] = other.extraConstantFieldMask[i];
+		}
+	}
+}
+
 /**
  * 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) {
+    	int position = local.getAnalysisId(this.maxFieldCount);
+        if (position < BitCacheSize) {
             // use bits
         	mask = 1L << position;
         	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
@@ -1492,12 +1679,12 @@
 	}
 }
 
-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) {
+    	int position = local.getAnalysisId(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$
@@ -1539,12 +1726,12 @@
 	}
 }
 
-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) {
+    	int position = local.getAnalysisId(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$
@@ -1901,6 +2088,8 @@
 	copy.tagBits = this.tagBits & ~NULL_FLAG_MASK;
 	copy.maxFieldCount = this.maxFieldCount;
 	copy.nullStatusChangedInAssert = this.nullStatusChangedInAssert;
+	copy.constantFieldsMask = this.constantFieldsMask;
+	copy.extraConstantFieldMask = this.extraConstantFieldMask;
 	if (this.extra != null) {
 		int length;
 		copy.extra = new long[extraLength][];
@@ -2023,6 +2212,8 @@
 	UnconditionalFlowInfo copy = new UnconditionalFlowInfo();
 	copy.tagBits = this.tagBits;
 	copy.maxFieldCount = this.maxFieldCount;
+	copy.constantFieldsMask = this.constantFieldsMask;
+	copy.extraConstantFieldMask = this.extraConstantFieldMask;
 	int limit = this.maxFieldCount;
 	if (limit < BitCacheSize) {
 		long mask;
@@ -2077,8 +2268,8 @@
 	return this;
 }
 
-public void markedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
-	int position = local.id + this.maxFieldCount;
+public void markedAsNullOrNonNullInAssertExpression(VariableBinding binding) {
+	int position = binding.getAnalysisId(this.maxFieldCount);
 	int oldLength;
 	if (this.nullStatusChangedInAssert == null) {
 		this.nullStatusChangedInAssert = new int[position + 1];
@@ -2091,8 +2282,8 @@
 	this.nullStatusChangedInAssert[position] = 1;
 }
 
-public boolean isMarkedAsNullOrNonNullInAssertExpression(LocalVariableBinding local) {
-	int position = local.id + this.maxFieldCount;
+public boolean isMarkedAsNullOrNonNullInAssertExpression(VariableBinding binding) {
+	int position = binding.getAnalysisId(this.maxFieldCount);
 	if(this.nullStatusChangedInAssert == null || position >= this.nullStatusChangedInAssert.length) {
 		return false;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index bd0c98d..1d6cf3f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -138,6 +138,7 @@
 	public static final String OPTION_ReportTasks = "org.eclipse.jdt.core.compiler.problem.tasks"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnusedObjectAllocation = "org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation";  //$NON-NLS-1$
 	public static final String OPTION_IncludeNullInfoFromAsserts = "org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts";  //$NON-NLS-1$
+	public static final String OPTION_IncludeFieldsInNullAnalysis = "org.eclipse.jdt.core.compiler.problem.includeFieldsInNullAnalysis";  //$NON-NLS-1$
 	public static final String OPTION_ReportMethodCanBeStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic";  //$NON-NLS-1$
 	public static final String OPTION_ReportMethodCanBePotentiallyStatic = "org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic";  //$NON-NLS-1$
 	public static final String OPTION_ReportRedundantSpecificationOfTypeArguments =  "org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments"; //$NON-NLS-1$
@@ -386,6 +387,8 @@
 	public boolean ignoreMethodBodies;
 	/** Raise null related warnings for variables tainted inside an assert statement (java 1.4 and above)*/
 	public boolean includeNullInfoFromAsserts;
+	/** Specify if fields are to be included in null analysis */
+	public boolean includeFieldsInNullAnalysis;
 	/** Controls whether forced generic type problems get reported  */
 	public boolean reportUnavoidableGenericTypeProblems;
 
@@ -1058,6 +1061,7 @@
 		optionsMap.put(OPTION_ReportTasks, getSeverityString(Tasks));
 		optionsMap.put(OPTION_ReportUnusedObjectAllocation, getSeverityString(UnusedObjectAllocation));
 		optionsMap.put(OPTION_IncludeNullInfoFromAsserts, this.includeNullInfoFromAsserts ? ENABLED : DISABLED);
+		optionsMap.put(OPTION_IncludeFieldsInNullAnalysis, this.includeFieldsInNullAnalysis ? ENABLED : DISABLED);
 		optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic));
 		optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic));
 		optionsMap.put(OPTION_ReportRedundantSpecificationOfTypeArguments, getSeverityString(RedundantSpecificationOfTypeArguments));
@@ -1227,6 +1231,9 @@
 		// allow null info from asserts to be considered downstream by default
 		this.includeNullInfoFromAsserts = false;
 		
+		// null analysis for fields
+		this.includeFieldsInNullAnalysis = false;
+		
 		this.isAnnotationBasedNullAnalysisEnabled = false;
 		this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME;
 		this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
@@ -1452,6 +1459,13 @@
 				this.includeNullInfoFromAsserts = false;
 			}
 		}
+		if ((optionValue = optionsMap.get(OPTION_IncludeFieldsInNullAnalysis)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.includeFieldsInNullAnalysis = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.includeFieldsInNullAnalysis = false;
+			}
+		}
 		if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportOverridingPackageDefaultMethod)) != null) updateSeverity(OverriddenPackageDefaultMethod, optionValue);
 		if ((optionValue = optionsMap.get(OPTION_ReportDeprecation)) != null) updateSeverity(UsingDeprecatedAPI, optionValue);
@@ -1742,6 +1756,7 @@
 		buf.append("\n\t- missing @Deprecated annotation: ").append(getSeverityString(MissingDeprecatedAnnotation)); //$NON-NLS-1$
 		buf.append("\n\t- incomplete enum switch: ").append(getSeverityString(IncompleteEnumSwitch)); //$NON-NLS-1$
 		buf.append("\n\t- raise null related warnings for variables tainted in assert statements: ").append(this.includeNullInfoFromAsserts ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t- include fields in null analysis: ").append(this.includeFieldsInNullAnalysis ? ENABLED : DISABLED); //$NON-NLS-1$
 		buf.append("\n\t- suppress warnings: ").append(this.suppressWarnings ? ENABLED : DISABLED); //$NON-NLS-1$
 		buf.append("\n\t- suppress optional errors: ").append(this.suppressOptionalErrors ? ENABLED : DISABLED); //$NON-NLS-1$
 		buf.append("\n\t- unhandled warning token: ").append(getSeverityString(UnhandledWarningToken)); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 8778c6b..4d5f38e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -40,7 +40,6 @@
 	public TypeDeclaration referenceContext;
 	public TypeReference superTypeReference;
 	java.util.ArrayList deferredBoundChecks;
-
 	public ClassScope(Scope parent, TypeDeclaration context) {
 		super(Scope.CLASS_SCOPE, parent);
 		this.referenceContext = context;
@@ -81,6 +80,7 @@
 				}
 			}
 		}
+		this.referenceContext.binding.cumulativeFieldCount += outerMostMethodScope().analysisIndex;
 		connectMemberTypes();
 		buildFieldsAndMethods();
 		anonymousType.faultInTypesForFieldsAndMethods();
@@ -145,6 +145,7 @@
 		// remove duplicate fields
 		if (count != fieldBindings.length)
 			System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
+		sourceType.cumulativeFieldCount += count;
 		sourceType.tagBits &= ~(TagBits.AreFieldsSorted|TagBits.AreFieldsComplete); // in case some static imports reached already into this type
 		sourceType.setFields(fieldBindings);
 	}
@@ -227,6 +228,7 @@
 			checkParameterizedTypeBounds();
 			checkParameterizedSuperTypeCollisions();
 		}
+		this.referenceContext.binding.cumulativeFieldCount += outerMostMethodScope().analysisIndex;
 		buildFieldsAndMethods();
 		localType.faultInTypesForFieldsAndMethods();
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 2c44d5a..4c9aa8d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -275,6 +275,13 @@
 	return originalField.tagBits;
 }
 
+public int getAnalysisId(int maxFieldCount) {
+	TypeBinding original = this.declaringClass.original();
+	if (original instanceof SourceTypeBinding)
+		return ((SourceTypeBinding)original).fieldAnalysisOffset + this.id;
+	return this.id;
+}
+
 public final boolean isDefault() {
 	return !isPublic() && !isProtected() && !isPrivate();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index c7ad46f..83981f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -44,6 +44,8 @@
 	public TypeVariableBinding[] typeVariables;
 
 	public ClassScope scope;
+	public int fieldAnalysisOffset;		// an offset for ids of fields of this class (id to be used for flow analysis) 
+	public int cumulativeFieldCount;   // cumulative field count from all enclosing types, used to build unique field id's for member types.
 
 	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods
 	// if a new category is added, also increment MAX_SYNTHETICS
@@ -68,6 +70,7 @@
 	this.modifiers = scope.referenceContext.modifiers;
 	this.sourceName = scope.referenceContext.name;
 	this.scope = scope;
+	this.cumulativeFieldCount = 0;
 
 	// expect the fields & methods to be initialized correctly later
 	this.fields = Binding.UNINITIALIZED_FIELDS;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index dc39e36..273f2af 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -37,6 +37,10 @@
 		return this.constant;
 	}
 
+	public int getAnalysisId(int maxFieldCount) {
+		return this.id + maxFieldCount;
+	}
+
 	public abstract AnnotationBinding[] getAnnotations();
 
 	public final boolean isBlankFinal(){
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 49bac9d..1df2202 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -109,6 +109,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;
@@ -287,18 +288,26 @@
 			return CompilerOptions.VarargsArgumentNeedCast;
 
 		case IProblem.NullLocalVariableReference:
+		case IProblem.NullFieldReference:
 			return CompilerOptions.NullReference;
 
 		case IProblem.PotentialNullLocalVariableReference:
 		case IProblem.PotentialNullMessageSendReference:
+		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:
 		case IProblem.RedundantNullCheckOnNonNullMessageSend:
 			return CompilerOptions.RedundantNullCheck;
 
@@ -5073,110 +5082,158 @@
 	}
 }
 
-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) {
+public void variableRedundantNullAssignment (VariableBinding variable, ASTNode location) {
 	if ((location.bits & ASTNode.FirstAssignmentToLocal) != 0) // https://bugs.eclipse.org/338303 - Warning about Redundant assignment conflicts with definite assignment
 		return;
-	int severity = computeSeverity(IProblem.RedundantLocalVariableNullAssignment);
+	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) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index d05ebd2..dba1762 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -581,6 +581,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}
 
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
index 52c943d..4bdcc4d 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -126,6 +126,7 @@
 	}
 	// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
 	// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+	// see also https://bugs.eclipse.org/bugs/show_bug.cgi?id=247564#c65
 	this.codeStream.maxFieldCount = aType.scope.outerMostClassScope().referenceType().maxFieldCount;
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 5898902..8b2e896 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -1780,6 +1780,20 @@
 	 */
 	public static final String COMPILER_PB_INCLUDE_ASSERTS_IN_NULL_ANALYSIS = PLUGIN_ID + ".compiler.problem.includeNullInfoFromAsserts"; //$NON-NLS-1$
 	/**
+	 * Compiler option ID: Raise null related errors or warnings on fields.
+	 * <p>When enabled, the compiler will flag all null related errors or warnings that have been enabled by the user
+	 *    on fields, in addition to local variables.</p>
+	 * <p>When disabled, the compiler will not flag null related errors or warnings on fields.</p>
+	 * <dl>
+	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.includeFieldsInNullAnalysis"</code></dd>
+	 * <dt>Possible values:</dt><dd><code>{ "enabled", "disabled" }</code></dd>
+	 * <dt>Default:</dt><dd><code>"disabled"</code></dd>
+	 * </dl>
+	 * @since 3.8
+	 * @category CompilerOptionID
+	 */
+	public static final String COMPILER_PB_INCLUDE_FIELDS_IN_NULL_ANALYSIS = PLUGIN_ID + ".compiler.problem.includeFieldsInNullAnalysis"; //$NON-NLS-1$
+	/**
 	 * Compiler option ID: Further Determining the Effect of <code>@SuppressWarnings</code> if also
 	 * {@link #COMPILER_PB_SUPPRESS_WARNINGS} is enabled.
 	 * <p>When enabled, the <code>@SuppressWarnings</code> annotation can additionally be used to suppress