blob: bd910a09d62b163340a524e7cc780cbfc6cf5ed3 [file] [log] [blame]
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;
}