FIR DFA: fix handling of equality operation

This commit is contained in:
Tianyu Geng
2021-07-23 22:56:56 -07:00
committed by teamcityserver
parent 0026560bd7
commit e495c722c7
4 changed files with 44 additions and 20 deletions
@@ -483,26 +483,50 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
}
// propagating facts for (... == true) and (... == false)
if (const.kind == ConstantValueKind.Boolean) {
val constValue = const.value as Boolean
val shouldInvert = isEq xor constValue
when (const.kind) {
ConstantValueKind.Boolean -> {
val constValue = const.value as Boolean
val shouldInvert = isEq xor constValue
logicSystem.translateVariableFromConditionInStatements(
flow,
operandVariable,
expressionVariable,
shouldRemoveOriginalStatements = operandVariable.isSynthetic()
) {
when (it.condition.operation) {
Operation.EqNull, Operation.NotEqNull -> {
(expressionVariable eq isEq) implies (it.effect)
}
Operation.EqTrue, Operation.EqFalse -> {
if (shouldInvert) (it.condition.invert()) implies (it.effect)
else it
logicSystem.translateVariableFromConditionInStatements(
flow,
operandVariable,
expressionVariable,
shouldRemoveOriginalStatements = operandVariable.isSynthetic()
) {
when (it.condition.operation) {
// Whatever the result is after comparing operandVariable with `true` or `false` cannot let you imply effects that apply
// when the operandVariable is null. Hence we return null here.
Operation.EqNull -> null
Operation.NotEqNull -> {
(expressionVariable eq isEq) implies (it.effect)
}
Operation.EqTrue, Operation.EqFalse -> {
if (shouldInvert) (it.condition.invert()) implies (it.effect)
else it
}
}
}
}
ConstantValueKind.Null -> {
logicSystem.translateVariableFromConditionInStatements(
flow,
operandVariable,
expressionVariable,
shouldRemoveOriginalStatements = operandVariable.isSynthetic()
) {
when (it.condition.operation) {
Operation.EqNull -> (expressionVariable eq isEq) implies (it.effect)
Operation.NotEqNull -> (expressionVariable eq !isEq) implies (it.effect)
// Whatever the result is after comparing operandVariable with `null` cannot let you imply effects that apply when the
// operandVariable is true or false.
Operation.EqTrue, Operation.EqFalse -> null
}
}
}
else -> {
// Inconclusive if the user code compares with other constants.
}
}
}
@@ -47,7 +47,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
newVariable: DataFlowVariable,
shouldRemoveOriginalStatements: Boolean,
filter: (Implication) -> Boolean = { true },
transform: (Implication) -> Implication = { it },
transform: (Implication) -> Implication? = { it },
)
abstract fun approveStatementsInsideFlow(
@@ -297,11 +297,11 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
newVariable: DataFlowVariable,
shouldRemoveOriginalStatements: Boolean,
filter: (Implication) -> Boolean,
transform: (Implication) -> Implication
transform: (Implication) -> Implication?
) {
with(flow) {
val statements = logicStatements[originalVariable]?.takeIf { it.isNotEmpty() } ?: return
val newStatements = statements.filter(filter).map {
val newStatements = statements.filter(filter).mapNotNull {
val newStatement = OperationStatement(newVariable, it.condition.operation) implies it.effect
transform(newStatement)
}.toPersistentList()
@@ -116,7 +116,7 @@ fun case_5(value_1: Number?, value_2: String?) {
fun case_6(value_1: Number, value_2: String?, value_3: Any?) {
when (value_3.case_6(value_1, value_2)) {
true -> {
println(value_3.equals(""))
println(value_3<!UNSAFE_CALL!>.<!>equals(""))
println(value_2<!UNSAFE_CALL!>.<!>length)
}
false -> {