[java-dfa] Flush mutable values from stack on call

GitOrigin-RevId: 64af8932d62f74966222a24cdb87472091f8a661
This commit is contained in:
Tagir Valeev
2021-10-07 09:38:19 +00:00
committed by intellij-monorepo-bot
parent cdb88b5255
commit c79166e1bb
6 changed files with 39 additions and 2 deletions
@@ -239,8 +239,16 @@ public class MethodCallInstruction extends ExpressionPushingInstruction {
DfaValue[] args = callArguments.toArray();
for (DfaMemoryState state : finalStates) {
ContractValue.flushContractTempVariables(state);
boolean keepNonFlushed = state.peek() instanceof DfaVariableValue;
DfaValue tos = null;
if (keepNonFlushed) {
tos = state.pop();
}
callArguments.flush(state, factory, realMethod);
pushResult(interpreter, state, state.pop(), args);
if (!keepNonFlushed) {
tos = state.pop();
}
pushResult(interpreter, state, tos, args);
result[i++] = nextState(interpreter, state);
}
return result;
@@ -6,6 +6,10 @@ class Doo {
@Nullable
Object getMethod() {return null;}
@Nullable
@Contract(pure=true)
Object getMethodPure() {return null;}
boolean isSomething() { return false;}
@Contract(pure=true)
@@ -24,7 +28,16 @@ class Doo {
if (getMethod() == null && !pureSomething()) {
return;
} else {
System.out.println(getMethod().<warning descr="Method invocation 'hashCode' may produce 'NullPointerException'">hashCode</warning>());
// still not sure about nullability as getMethod() is not pure
System.out.println(getMethod().hashCode());
}
}
public void main4() {
if (getMethodPure() == null && !pureSomething()) {
return;
} else {
System.out.println(getMethodPure().<warning descr="Method invocation 'hashCode' may produce 'NullPointerException'">hashCode</warning>());
}
}
@@ -3,6 +3,7 @@ import java.util.*;
public class PrimitiveGetters {
interface Xyz {
@Contract(pure = true)
boolean isFoo();
}
@@ -0,0 +1,11 @@
public class StringBuilderLengthReturn {
private static StringBuilder update(StringBuilder sb) {
sb.append("xyz");
return sb;
}
void test(StringBuilder sb) {
// No 'always zero' warning
int diff = sb.length() - update(sb).length();
}
}
@@ -714,4 +714,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testEnumOrdinal() { doTest(); }
public void testThisInEnumSubclass() { doTest(); }
public void testVarargConstructorNoArgs() { doTest(); }
public void testStringBuilderLengthReturn() { doTest(); }
}
@@ -1322,6 +1322,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
!dv.isStable() && qualifierStatusMap.shouldFlush(val, dv.isCall()))) {
return myFactory.fromDfType(type.getBasicType());
}
if (val instanceof DfaVariableValue && qualifierStatusMap.shouldFlush((DfaVariableValue)val)) {
return myFactory.fromDfType(type);
}
return val;
});
}