import org.checkerframework.checker.nullness.qual.*; import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; /* * Miscellaneous tests based on problems found when checking Daikon. */ public class DaikonTests { // Based on a problem found in PPtSlice. class Bug1 { @Nullable Object field; public void cond1() { if (this.hashCode() > 6 && Bug1Other.field != null) { // spurious dereference error Bug1Other.field.toString(); } } public void cond1(Bug1 p) { if (this.hashCode() > 6 && p.field != null) { // works p.field.toString(); } } public void cond2() { if (Bug1Other.field != null && this.hashCode() > 6) { // works Bug1Other.field.toString(); } } } // Based on problem found in PptCombined. // Not yet able to reproduce the problem :-( class Bug2Data { Bug2Data(Bug2Super o) {} } class Bug2Super { public @MonotonicNonNull Bug2Data field; } class Bug2 extends Bug2Super { private void m() { field = new Bug2Data(this); field.hashCode(); } } // Based on problem found in FloatEqual. class Bug3 { @EnsuresNonNullIf(expression = "derived", result = true) public boolean isDerived() { return (derived != null); } @Nullable Object derived; void good1(Bug3 v1) { if (!v1.isDerived() || !(5 > 9)) { return; } v1.derived.hashCode(); } // TODO: this is currently not supported // void good2(Bug3 v1) { // if (!(v1.isDerived() && (5 > 9))) // return; // v1.derived.hashCode(); // } void good3(Bug3 v1) { if (!v1.isDerived() || !(v1 instanceof Bug3)) { return; } Object o = (Object) v1.derived; o.hashCode(); } } // Based on problem found in PrintInvariants. // Not yet able to reproduce the problem :-( class Bug4 { @MonotonicNonNull Object field; void m(Bug4 p) { if (false && p.field != null) { p.field.hashCode(); } } } // Based on problem found in chicory.Runtime: class Bug5 { @Nullable Object clazz; @EnsuresNonNull("clazz") void init() { clazz = new Object(); } void test(Bug5 b) { if (b.clazz == null) { b.init(); } // The problem is: // In the "then" branch, we have in "nnExpr" that "clazz" is non-null. // In the "else" branch, we have in "annos" that the variable is non-null. // However, as these are facts in two different representations, the merge keeps neither! // // no error message expected b.clazz.hashCode(); } } // From LimitedSizeSet. The following initialization of the values array // has caused a NullPointerException. class Bug6<T> { protected @Nullable T @Nullable [] values; public Bug6() { //:: warning: [unchecked] unchecked cast @Nullable T[] new_values_array = (@Nullable T[]) new @Nullable Object[4]; values = new_values_array; } } } class Bug1Other { static @Nullable Object field; }