### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.core
Index: compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java,v
retrieving revision 1.91
diff -u -r1.91 Assignment.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 31 Aug 2010 14:58:05 -0000 1.91
+++ compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 9 Sep 2010 13:22:33 -0000
@@ -53,34 +53,9 @@
.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
.unconditionalInits();
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
- switch(nullStatus) {
- case FlowInfo.NULL :
- flowInfo.markAsDefinitelyNull(local);
- break;
- case FlowInfo.NON_NULL :
- flowInfo.markAsDefinitelyNonNull(local);
- break;
- case FlowInfo.POTENTIALLY_NULL :
- flowInfo.markAsPotentiallyNull(local);
- break;
- default:
- flowInfo.markAsDefinitelyUnknown(local);
- }
- if (flowContext.initsOnFinally != null) {
- switch(nullStatus) {
- case FlowInfo.NULL :
- flowContext.initsOnFinally.markAsDefinitelyNull(local);
- break;
- case FlowInfo.NON_NULL :
- flowContext.initsOnFinally.markAsDefinitelyNonNull(local);
- break;
- case FlowInfo.POTENTIALLY_NULL :
- flowContext.initsOnFinally.markAsPotentiallyNull(local);
- break;
- default:
- flowContext.initsOnFinally.markAsDefinitelyUnknown(local);
- }
- }
+ flowInfo.markNullStatus(local, nullStatus);
+ if (flowContext.initsOnFinally != null)
+ flowContext.initsOnFinally.markNullStatus(local, nullStatus);
}
return flowInfo;
}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java,v
retrieving revision 1.96
diff -u -r1.96 ConditionalExpression.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java 1 Sep 2010 15:43:21 -0000 1.96
+++ compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java 9 Sep 2010 13:22:33 -0000
@@ -319,20 +319,19 @@
if (ifTrueNullStatus == ifFalseNullStatus) {
return ifTrueNullStatus;
}
- // is there a chance of null? -> potentially null
+ // is there a chance of null (or non-null)? -> potentially null etc.
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=133125
- switch (ifTrueNullStatus) {
- case FlowInfo.NULL:
- case FlowInfo.POTENTIALLY_NULL:
- return FlowInfo.POTENTIALLY_NULL;
- }
- switch (ifFalseNullStatus) {
- case FlowInfo.NULL:
- case FlowInfo.POTENTIALLY_NULL:
- return FlowInfo.POTENTIALLY_NULL;
- }
+ int status = 0;
+ int combinedStatus = ifTrueNullStatus|ifFalseNullStatus;
+ if ((combinedStatus & (FlowInfo.NULL|FlowInfo.POTENTIALLY_NULL)) != 0)
+ status |= FlowInfo.POTENTIALLY_NULL;
+ if ((combinedStatus & (FlowInfo.NON_NULL|FlowInfo.POTENTIALLY_NON_NULL)) != 0)
+ status |= FlowInfo.POTENTIALLY_NON_NULL;
+ if ((combinedStatus & (FlowInfo.UNKNOWN|FlowInfo.POTENTIALLY_UNKNOWN)) != 0)
+ status |= FlowInfo.POTENTIALLY_UNKNOWN;
+ if (status > 0)
+ return status;
return FlowInfo.UNKNOWN;
- // cannot decide which branch to take, and they disagree
}
public Constant optimizedBooleanConstant() {
Index: compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java,v
retrieving revision 1.129
diff -u -r1.129 Expression.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 31 Aug 2010 14:58:05 -0000 1.129
+++ compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 9 Sep 2010 13:22:33 -0000
@@ -837,15 +837,8 @@
return FlowInfo.NON_NULL; // constant expression cannot be null
LocalVariableBinding local = localVariableBinding();
- if (local != null) {
- if (flowInfo.isDefinitelyNull(local))
- return FlowInfo.NULL;
- if (flowInfo.isDefinitelyNonNull(local))
- return FlowInfo.NON_NULL;
- if (flowInfo.isPotentiallyNull(local))
- return FlowInfo.POTENTIALLY_NULL;
- return FlowInfo.UNKNOWN;
- }
+ if (local != null)
+ return flowInfo.nullStatus(local);
return FlowInfo.NON_NULL;
}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java,v
retrieving revision 1.73
diff -u -r1.73 LocalDeclaration.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 31 Aug 2010 14:58:05 -0000 1.73
+++ compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 9 Sep 2010 13:22:33 -0000
@@ -57,19 +57,7 @@
}
flowInfo.markAsDefinitelyAssigned(this.binding);
if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
- switch(nullStatus) {
- case FlowInfo.NULL :
- flowInfo.markAsDefinitelyNull(this.binding);
- break;
- case FlowInfo.NON_NULL :
- flowInfo.markAsDefinitelyNonNull(this.binding);
- break;
- case FlowInfo.POTENTIALLY_NULL :
- flowInfo.markAsPotentiallyNull(this.binding);
- break;
- default:
- flowInfo.markAsDefinitelyUnknown(this.binding);
- }
+ flowInfo.markNullStatus(this.binding, nullStatus);
// no need to inform enclosing try block since its locals won't get
// known by the finally block
}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java,v
retrieving revision 1.118
diff -u -r1.118 SingleNameReference.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 31 Aug 2010 14:58:05 -0000 1.118
+++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 9 Sep 2010 13:22:33 -0000
@@ -770,15 +770,8 @@
return FlowInfo.UNKNOWN;
case Binding.LOCAL : // reading a local variable
LocalVariableBinding local = (LocalVariableBinding) this.binding;
- if (local != null) {
- if (flowInfo.isDefinitelyNull(local))
- return FlowInfo.NULL;
- if (flowInfo.isDefinitelyNonNull(local))
- return FlowInfo.NON_NULL;
- if (flowInfo.isPotentiallyNull(local))
- return FlowInfo.POTENTIALLY_NULL;
- return FlowInfo.UNKNOWN;
- }
+ if (local != null)
+ return flowInfo.nullStatus(local);
}
return FlowInfo.NON_NULL; // never get there
}
Index: compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java,v
retrieving revision 1.31
diff -u -r1.31 ConditionalFlowInfo.java
--- compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 31 Aug 2010 14:58:05 -0000 1.31
+++ compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 9 Sep 2010 13:22:33 -0000
@@ -157,16 +157,31 @@
this.initsWhenFalse.markAsDefinitelyNull(local);
}
+public void resetNullInfo(LocalVariableBinding local) {
+ this.initsWhenTrue.resetNullInfo(local);
+ this.initsWhenFalse.resetNullInfo(local);
+}
+
public void markAsPotentiallyNull(LocalVariableBinding local) {
this.initsWhenTrue.markAsPotentiallyNull(local);
this.initsWhenFalse.markAsPotentiallyNull(local);
}
+public void markAsPotentiallyNonNull(LocalVariableBinding local) {
+ this.initsWhenTrue.markAsPotentiallyNonNull(local);
+ this.initsWhenFalse.markAsPotentiallyNonNull(local);
+}
+
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
this.initsWhenTrue.markAsDefinitelyUnknown(local);
this.initsWhenFalse.markAsDefinitelyUnknown(local);
}
+public void markAsPotentiallyUnknown(LocalVariableBinding local) {
+ this.initsWhenTrue.markAsPotentiallyUnknown(local);
+ this.initsWhenFalse.markAsPotentiallyUnknown(local);
+}
+
public FlowInfo setReachMode(int reachMode) {
if (reachMode == REACHABLE) {
this.tagBits &= ~UNREACHABLE;
Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java,v
retrieving revision 1.43
diff -u -r1.43 FlowInfo.java
--- compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 31 Aug 2010 14:58:05 -0000 1.43
+++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 9 Sep 2010 13:22:33 -0000
@@ -23,10 +23,12 @@
public final static int UNREACHABLE = 1;
public final static int NULL_FLAG_MASK = 2;
- public final static int UNKNOWN = 0;
- public final static int NULL = 1;
- public final static int NON_NULL = -1;
- public final static int POTENTIALLY_NULL = 2;
+ public final static int UNKNOWN = 1;
+ public final static int NULL = 2;
+ public final static int NON_NULL = 4;
+ public final static int POTENTIALLY_UNKNOWN = 8;
+ public final static int POTENTIALLY_NULL = 16;
+ public final static int POTENTIALLY_NON_NULL = 32;
public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
static {
@@ -248,13 +250,28 @@
* Record a local got definitely assigned to null.
*/
abstract public void markAsDefinitelyNull(LocalVariableBinding local);
-
+
/**
- * Record a local may have got assigned to null.
+ * Reset all null-information about a given local.
+ */
+ abstract public void resetNullInfo(LocalVariableBinding local);
+
+ /**
+ * Record a local may have got assigned to unknown (merging with existing info).
+ */
+ abstract public void markAsPotentiallyUnknown(LocalVariableBinding local);
+
+ /**
+ * Record a local may have got assigned to null (merging with existing info).
*/
abstract public void markAsPotentiallyNull(LocalVariableBinding local);
/**
+ * Record a local may have got assigned to non-null (merging with existing info).
+ */
+ abstract public void markAsPotentiallyNonNull(LocalVariableBinding local);
+
+ /**
* Record a local got definitely assigned.
*/
abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
@@ -265,6 +282,61 @@
abstract public void markAsDefinitelyUnknown(LocalVariableBinding local);
/**
+ * Mark the null status of the given local according to the given status
+ * @param local
+ * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
+ */
+public void markNullStatus(LocalVariableBinding local, int nullStatus) {
+ switch(nullStatus) {
+ // definite status?
+ case UNKNOWN :
+ markAsDefinitelyUnknown(local);
+ break;
+ case NULL :
+ markAsDefinitelyNull(local);
+ break;
+ case NON_NULL :
+ markAsDefinitelyNonNull(local);
+ break;
+ default:
+ // collect potential status:
+ resetNullInfo(local);
+ if ((nullStatus & POTENTIALLY_UNKNOWN) != 0)
+ markAsPotentiallyUnknown(local);
+ if ((nullStatus & POTENTIALLY_NULL) != 0)
+ markAsPotentiallyNull(local);
+ if ((nullStatus & POTENTIALLY_NON_NULL) != 0)
+ markAsPotentiallyNonNull(local);
+ if ((nullStatus & (POTENTIALLY_NULL|POTENTIALLY_NON_NULL|POTENTIALLY_UNKNOWN)) == 0)
+ markAsDefinitelyUnknown(local);
+ }
+}
+
+/**
+ * Answer the null status of the given local
+ * @param local
+ * @return bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
+ */
+public int nullStatus(LocalVariableBinding local) {
+ if (isDefinitelyUnknown(local))
+ return UNKNOWN;
+ if (isDefinitelyNull(local))
+ return NULL;
+ if (isDefinitelyNonNull(local))
+ return NON_NULL;
+ int status = 0;
+ if (isPotentiallyUnknown(local))
+ status |= POTENTIALLY_UNKNOWN;
+ if (isPotentiallyNull(local))
+ status |= POTENTIALLY_NULL;
+ if (isPotentiallyNonNull(local))
+ status |= POTENTIALLY_NON_NULL;
+ if (status > 0)
+ return status;
+ return UNKNOWN;
+}
+
+/**
* Merge branches using optimized boolean conditions
*/
public static UnconditionalFlowInfo mergedOptimizedBranches(
Index: compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java,v
retrieving revision 1.67
diff -u -r1.67 UnconditionalFlowInfo.java
--- compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 31 Aug 2010 14:58:05 -0000 1.67
+++ compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 9 Sep 2010 13:22:33 -0000
@@ -24,10 +24,8 @@
* No caching of pre-allocated instances.
*/
public class UnconditionalFlowInfo extends FlowInfo {
- // Coverage tests
/**
- * Exception raised when unexpected behavior is detected during coverage
- * tests.
+ * Exception raised when unexpected behavior is detected.
*/
public static class AssertionFailedException extends RuntimeException {
private static final long serialVersionUID = 1827352841030089703L;
@@ -976,7 +974,20 @@
& (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex])
& (1L << (position % BitCacheSize))) != 0;
}
-
+/** Asserts that the given boolean is true
. If this
+ * is not the case, some kind of unchecked exception is thrown.
+ * The given message is included in that exception, to aid debugging.
+ *
+ * @param expression the outcome of the check
+ * @param message the message to include in the exception
+ * @return true
if the check passes (does not return
+ * if the check fails)
+ */
+private static boolean isTrue(boolean expression, String message) {
+ if (!expression)
+ throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$
+ return expression;
+}
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
// protected from non-object locals in calling methods
if (this != DEAD_END) {
@@ -1330,6 +1341,64 @@
}
}
+public void resetNullInfo(LocalVariableBinding local) {
+ if (this != DEAD_END) {
+ this.tagBits |= NULL_FLAG_MASK;
+ int position;
+ long mask;
+ if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
+ // use bits
+ this.nullBit1 &= (mask = ~(1L << position));
+ this.nullBit2 &= mask;
+ this.nullBit3 &= mask;
+ this.nullBit4 &= mask;
+ } else {
+ // use extra vector
+ int vectorIndex ;
+ this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
+ &= (mask = ~(1L << (position % BitCacheSize)));
+ this.extra[3][vectorIndex] &= mask;
+ this.extra[4][vectorIndex] &= mask;
+ this.extra[5][vectorIndex] &= mask;
+ }
+ }
+}
+
+/**
+ * Mark a local as potentially having been assigned to an unknown value.
+ * @param local the local to mark
+ */
+public void markAsPotentiallyUnknown(LocalVariableBinding 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) {
+ // use bits
+ mask = 1L << position;
+ isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
+ this.nullBit4 |= mask;
+ if (COVERAGE_TEST_FLAG) {
+ if(CoverageTestId == 46) {
+ this.nullBit4 = ~0;
+ }
+ }
+ } else {
+ // use extra vector
+ int vectorIndex = (position / BitCacheSize) - 1;
+ mask = 1L << (position % BitCacheSize);
+ isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
+ this.extra[5][vectorIndex] |= mask;
+ if (COVERAGE_TEST_FLAG) {
+ if(CoverageTestId == 47) {
+ this.extra[5][vectorIndex] = ~0;
+ }
+ }
+ }
+ }
+}
+
public void markAsPotentiallyNull(LocalVariableBinding local) {
if (this != DEAD_END) {
this.tagBits |= NULL_FLAG_MASK;
@@ -1337,10 +1406,9 @@
long mask;
if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
// use bits
- this.nullBit1 &= ~(mask = 1L << position);
+ mask = 1L << position;
+ isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
this.nullBit2 |= mask;
- this.nullBit3 &= ~mask;
- this.nullBit4 &= ~mask;
if (COVERAGE_TEST_FLAG) {
if(CoverageTestId == 40) {
this.nullBit4 = ~0;
@@ -1348,12 +1416,10 @@
}
} else {
// use extra vector
- int vectorIndex ;
- this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
- &= ~(mask = 1L << (position % BitCacheSize));
+ int vectorIndex = (position / BitCacheSize) - 1;
+ mask = 1L << (position % BitCacheSize);
this.extra[3][vectorIndex] |= mask;
- this.extra[4][vectorIndex] &= (mask = ~mask);
- this.extra[5][vectorIndex] &= mask;
+ isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
if (COVERAGE_TEST_FLAG) {
if(CoverageTestId == 41) {
this.extra[5][vectorIndex] = ~0;
@@ -1363,6 +1429,36 @@
}
}
+public void markAsPotentiallyNonNull(LocalVariableBinding local) {
+ if (this != DEAD_END) {
+ this.tagBits |= NULL_FLAG_MASK;
+ int position;
+ long mask;
+ if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
+ // use bits
+ mask = 1L << position;
+ isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
+ this.nullBit3 |= mask;
+ if (COVERAGE_TEST_FLAG) {
+ if(CoverageTestId == 42) {
+ this.nullBit4 = ~0;
+ }
+ }
+ } else {
+ // use extra vector
+ int vectorIndex = (position / BitCacheSize) - 1;
+ mask = 1L << (position % BitCacheSize);
+ isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
+ this.extra[4][vectorIndex] |= mask;
+ if (COVERAGE_TEST_FLAG) {
+ if(CoverageTestId == 43) {
+ this.extra[5][vectorIndex] = ~0;
+ }
+ }
+ }
+ }
+}
+
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) {
if (COVERAGE_TEST_FLAG) {
#P org.eclipse.jdt.core.tests.compiler
Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java,v
retrieving revision 1.101
diff -u -r1.101 NullReferenceTest.java
--- src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 1 Sep 2010 15:43:25 -0000 1.101
+++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 9 Sep 2010 13:22:34 -0000
@@ -35,7 +35,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[] { "testBug320414" };
+// TESTS_NAMES = new String[] { "testBug292478g" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -13222,4 +13222,132 @@
"Potential null pointer access: The variable y may be null at this location\n" +
"----------\n");
}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292478 - Report potentially null across variable assignment
+// test regression reported in comment 8
+public void testBug292478e() {
+ this.runConformTest(
+ new String[] {
+ "Test.java",
+ "public class Test {\n" +
+ " Object foo(int i, boolean b1, boolean b2) {\n" +
+ " Object o1 = null;\n" +
+ " done : while (true) { \n" +
+ " switch (i) {\n" +
+ " case 1 :\n" +
+ " Object o2 = null;\n" +
+ " if (b2)\n" +
+ " o2 = new Object();\n" +
+ " o1 = o2;\n" +
+ " break;\n" +
+ " case 2 :\n" +
+ " break done;\n" +
+ " }\n" +
+ " } \n" +
+ " if (o1 != null)\n" +
+ " return o1;\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292478 - Report potentially null across variable assignment
+// variant where regression occurred inside the while-switch structure
+public void testBug292478f() {
+ this.runConformTest(
+ new String[] {
+ "Test.java",
+ "public class Test {\n" +
+ " Object foo(int i, boolean b1, boolean b2) {\n" +
+ " Object o1 = null;\n" +
+ " done : while (true) { \n" +
+ " switch (i) {\n" +
+ " case 1 :\n" +
+ " Object o2 = null;\n" +
+ " if (b2)\n" +
+ " o2 = new Object();\n" +
+ " o1 = o2;\n" +
+ " if (o1 != null)\n" +
+ " return o1;\n" +
+ " break;\n" +
+ " case 2 :\n" +
+ " break done;\n" +
+ " }\n" +
+ " } \n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292478 - Report potentially null across variable assignment
+// variant for transfering state potentially unknown
+public void testBug292478g() {
+ this.runConformTest(
+ new String[] {
+ "Test.java",
+ "public class Test {\n" +
+ " Object foo(int i, boolean b1, boolean b2, Object o2) {\n" +
+ " Object o1 = null;\n" +
+ " done : while (true) { \n" +
+ " switch (i) {\n" +
+ " case 1 :\n" +
+ " if (b2)\n" +
+ " o2 = bar();\n" +
+ " o1 = o2;\n" +
+ " if (o1 != null)\n" +
+ " return o1;\n" +
+ " break;\n" +
+ " case 2 :\n" +
+ " break done;\n" +
+ " }\n" +
+ " } \n" +
+ " return null;\n" +
+ " }\n" +
+ " Object bar() { return null; }\n" +
+ "}\n"
+ });
+}
+
+// Bug 324762 - Compiler thinks there is deadcode and removes it!
+// regression caused by the fix for bug 133125
+// ternary is non-null or null
+public void testBug324762() {
+ this.runConformTest(
+ new String[] {
+ "Test.java",
+ "public class Test {\n" +
+ " void zork(boolean b1) {\n" +
+ " Object satisfied = null;\n" +
+ " if (b1) {\n" +
+ " String[] s = new String[] { \"a\", \"b\" };\n" +
+ " for (int k = 0; k < s.length && satisfied == null; k++)\n" +
+ " satisfied = s.length > 1 ? new Object() : null;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ });
+}
+
+// Bug 324762 - Compiler thinks there is deadcode and removes it!
+// regression caused by the fix for bug 133125
+// ternary is unknown or null
+public void testBug324762a() {
+ this.runConformTest(
+ new String[] {
+ "Test.java",
+ "public class Test {\n" +
+ " void zork(boolean b1) {\n" +
+ " Object satisfied = null;\n" +
+ " if (b1) {\n" +
+ " String[] s = new String[] { \"a\", \"b\" };\n" +
+ " for (int k = 0; k < s.length && satisfied == null; k++)\n" +
+ " satisfied = s.length > 1 ? bar() : null;\n" +
+ " }\n" +
+ " }\n" +
+ " Object bar() { return null; }\n" +
+ "}\n"
+ });
+}
}
\ No newline at end of file