import org.checkerframework.dataflow.qual.Deterministic;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.framework.test.*;
import testlib.util.*;
// various tests about keeping information in the store about pure method calls
class StorePure {
String f1, f2;
// various pure methods
@Pure
String pure1() {
return null;
}
@Pure
String pure1b() {
return null;
}
@Deterministic
String pure1c() {
return null;
}
@Pure
String pure2(int i) {
return null;
}
@Pure
String pure3(boolean b) {
return null;
}
@Pure
String pure4(String o) {
return null;
}
void nonpure() {}
void t1(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure1() == p1) {
@Odd String l1 = pure1();
l0 = "a"; // does not remove information
@Odd String l1b = pure1();
//:: error: (assignment.type.incompatible)
@Odd String l2 = pure1b();
nonpure(); // non-pure method call might change the return value of pure1
//:: error: (assignment.type.incompatible)
@Odd String l3 = pure1();
}
}
// check that it only works for deterministic methods
void t1b(@Odd String p1, String p2, boolean b1) {
if (pure1c() == p1) {
@Odd String l1 = pure1c();
}
}
void t2(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure1() == p1) {
@Odd String l1 = pure1();
l0 = "a"; // does not remove information
@Odd String l1b = pure1();
//:: error: (assignment.type.incompatible)
@Odd String l2 = pure1b();
f1 = ""; // field update might change the return value of pure1
//:: error: (assignment.type.incompatible)
@Odd String l3 = pure1();
}
}
void t3(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure2(1) == p1) {
//:: error: (assignment.type.incompatible)
@Odd String l4 = pure2(0);
@Odd String l1 = pure2(1);
l0 = "a"; // does not remove information
@Odd String l1b = pure2(1);
nonpure(); // non-pure method call might change the return value of pure2
//:: error: (assignment.type.incompatible)
@Odd String l3 = pure2(1);
}
}
void t4(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure2(1) == p1) {
//:: error: (assignment.type.incompatible)
@Odd String l4 = pure2(0);
@Odd String l1 = pure2(1);
l0 = "a"; // does not remove information
@Odd String l1b = pure2(1);
f1 = ""; // field update might change the return value of pure2
//:: error: (assignment.type.incompatible)
@Odd String l3 = pure2(1);
}
}
void t5(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure3(true) == p1) {
//:: error: (assignment.type.incompatible)
@Odd String l4 = pure3(false);
@Odd String l1 = pure3(true);
l0 = "a"; // does not remove information
@Odd String l1b = pure3(true);
nonpure(); // non-pure method call might change the return value of pure2
//:: error: (assignment.type.incompatible)
@Odd String l3 = pure3(true);
}
}
void t6(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure3(true) == p1) {
//:: error: (assignment.type.incompatible)
@Odd String l4 = pure3(false);
@Odd String l1 = pure3(true);
l0 = "a"; // does not remove information
@Odd String l1b = pure3(true);
f1 = ""; // field update might change the return value of pure2
//:: error: (assignment.type.incompatible)
@Odd String l3 = pure3(true);
}
}
// local variable as argument
void t7(@Odd String p1, String p2, boolean b1) {
String l0 = "";
if (pure4(l0) == p1) {
//:: error: (assignment.type.incompatible)
@Odd String l4 = pure4("jk");
@Odd String l1 = pure4(l0);
l0 = "a"; // remove information (!)
//:: error: (assignment.type.incompatible)
@Odd String l1b = pure4(l0);
}
}
}