[java-dfa] Avoid canonicalizing when flushing from LVA

GitOrigin-RevId: f1ba8fc87ede4835e98ed2aceaa792f66a9a529b
This commit is contained in:
Tagir Valeev
2021-03-22 11:11:33 +00:00
committed by intellij-monorepo-bot
parent f737dd9f3a
commit c6f29339aa
5 changed files with 37 additions and 6 deletions
@@ -144,8 +144,21 @@ public interface DfaMemoryState {
void flushFields();
/**
* Flush given variable (forget any knowledge about it). Equivalent to {@code flushVariable(variable, true)}
* @param variable to flush
*/
void flushVariable(@NotNull DfaVariableValue variable);
/**
* Flush given variable (forget any knowledge about it)
* @param variable to flush
* @param canonicalize whether to canonicalize the variable before flushing. Flushing canonical variable allows to forget
* about all known aliases as well. Flushing without canonicalization could be necessary only
* to simplify memory state, if it's known that given variable is never used anymore.
*/
void flushVariable(@NotNull DfaVariableValue variable, boolean canonicalize);
/**
* Mark this state as ephemeral. See {@link #isEphemeral()} for details.
*/
@@ -1323,11 +1323,16 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public void flushVariable(@NotNull DfaVariableValue variable) {
flushVariable(variable, false);
flushVariable(variable, true, false);
}
protected void flushVariable(@NotNull DfaVariableValue variable, boolean shouldMarkFlushed) {
DfaVariableValue canonical = canonicalize(variable);
@Override
public void flushVariable(@NotNull DfaVariableValue variable, boolean canonicalize) {
flushVariable(variable, canonicalize, false);
}
protected void flushVariable(@NotNull DfaVariableValue variable, boolean canonicalize, boolean shouldMarkFlushed) {
DfaVariableValue canonical = canonicalize ? canonicalize(variable) : variable;
EqClass eqClass = canonical.getDependentVariables().isEmpty() ? null : getEqClass(canonical);
DfaVariableValue newCanonical =
eqClass == null ? null : StreamEx.of(eqClass.iterator()).without(canonical).min(EqClass.CANONICAL_VARIABLE_COMPARATOR)
@@ -131,10 +131,10 @@ final class NullParameterConstraintChecker extends DataFlowRunner {
}
@Override
protected void flushVariable(@NotNull DfaVariableValue variable, boolean shouldMarkFlushed) {
protected void flushVariable(@NotNull DfaVariableValue variable, boolean canonicalize, boolean shouldMarkFlushed) {
final PsiModifierListOwner psi = variable.getPsiVariable();
if (psi instanceof PsiParameter && myPossiblyViolatedParameters.contains(psi)) return;
super.flushVariable(variable, shouldMarkFlushed);
super.flushVariable(variable, canonicalize, shouldMarkFlushed);
}
@NotNull
@@ -26,7 +26,7 @@ public class FinishElementInstruction extends Instruction {
public DfaInstructionState[] accept(DataFlowRunner runner, DfaMemoryState state, InstructionVisitor visitor) {
if (!myVarsToFlush.isEmpty()) {
for (DfaVariableValue value : myVarsToFlush) {
state.flushVariable(value);
state.flushVariable(value, false);
}
}
return nextInstruction(runner, state);
@@ -5,6 +5,19 @@ import java.util.Set;
import org.jetbrains.annotations.Contract;
public class StringToCharArray {
final String field;
final int[] bogus = new int[128];
StringToCharArray(String s) {
if (s.isEmpty()) throw new IllegalArgumentException();
field = s;
char[] chars = field.toCharArray();
if (<warning descr="Condition 'chars.length != field.length()' is always 'false'">chars.length != field.length()</warning>) {}
if (<warning descr="Condition 's.isEmpty()' is always 'false'">s.isEmpty()</warning>) {
}
}
void test(String s) {
if (s.startsWith("--")) {
char[] arr = s.toCharArray();