@NotNull private static DfaMemoryStateImpl createClosureState(@NotNull DfaMemoryState memState) { DfaMemoryStateImpl copy = (DfaMemoryStateImpl) memState.createCopy(); copy.flushFields(); Set<DfaVariableValue> vars = new HashSet<DfaVariableValue>(copy.getVariableStates().keySet()); for (DfaVariableValue value : vars) { copy.flushDependencies(value); } copy.emptyStack(); return copy; }
public DfaInstructionState[] visitConditionalGoto( ConditionalGotoInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { DfaValue cond = memState.pop(); DfaValue condTrue; DfaValue condFalse; if (instruction.isNegated()) { condFalse = cond; condTrue = cond.createNegated(); } else { condTrue = cond; condFalse = cond.createNegated(); } if (condTrue == runner.getFactory().getConstFactory().getTrue()) { markBranchReachable(instruction, true); return new DfaInstructionState[] { new DfaInstructionState(runner.getInstruction(instruction.getOffset()), memState) }; } if (condFalse == runner.getFactory().getConstFactory().getTrue()) { markBranchReachable(instruction, false); return nextInstruction(instruction, runner, memState); } ArrayList<DfaInstructionState> result = new ArrayList<DfaInstructionState>(); DfaMemoryState thenState = memState.createCopy(); DfaMemoryState elseState = memState.createCopy(); if (thenState.applyCondition(condTrue)) { result.add( new DfaInstructionState(runner.getInstruction(instruction.getOffset()), thenState)); markBranchReachable(instruction, true); } if (elseState.applyCondition(condFalse)) { result.add( new DfaInstructionState(runner.getInstruction(instruction.getIndex() + 1), elseState)); markBranchReachable(instruction, false); } return result.toArray(new DfaInstructionState[result.size()]); }
@Nullable private DfaInstructionState[] handleRelationBinop( BinopInstruction instruction, DataFlowRunner runner, DfaMemoryState memState, DfaValue dfaRight, DfaValue dfaLeft) { DfaValueFactory factory = runner.getFactory(); final Instruction next = runner.getInstruction(instruction.getIndex() + 1); DfaRelationValue dfaRelation = factory .getRelationFactory() .createRelation(dfaLeft, dfaRight, instruction.getOperationSign(), false); if (dfaRelation == null) { return null; } myCanBeNullInInstanceof.add(instruction); ArrayList<DfaInstructionState> states = new ArrayList<DfaInstructionState>(); final DfaMemoryState trueCopy = memState.createCopy(); if (trueCopy.applyCondition(dfaRelation)) { trueCopy.push(factory.getConstFactory().getTrue()); instruction.setTrueReachable(); states.add(new DfaInstructionState(next, trueCopy)); } //noinspection UnnecessaryLocalVariable DfaMemoryState falseCopy = memState; if (falseCopy.applyCondition(dfaRelation.createNegated())) { falseCopy.push(factory.getConstFactory().getFalse()); instruction.setFalseReachable(); states.add(new DfaInstructionState(next, falseCopy)); if (instruction instanceof InstanceofInstruction && !falseCopy.isNull(dfaLeft)) { myUsefulInstanceofs.add((InstanceofInstruction) instruction); } } return states.toArray(new DfaInstructionState[states.size()]); }
private List<DfaMemoryState> addContractResults( DfaValue[] argValues, MethodContract contract, List<DfaMemoryState> states, MethodCallInstruction instruction, DfaValueFactory factory, Set<DfaMemoryState> finalStates) { DfaConstValue.Factory constFactory = factory.getConstFactory(); List<DfaMemoryState> falseStates = ContainerUtil.newArrayList(); for (int i = 0; i < argValues.length; i++) { DfaValue argValue = argValues[i]; MethodContract.ValueConstraint constraint = contract.arguments[i]; DfaConstValue expectedValue = constraint.getComparisonValue(factory); if (expectedValue == null) continue; boolean invertCondition = constraint.shouldUseNonEqComparison(); DfaValue condition = factory .getRelationFactory() .createRelation(argValue, expectedValue, EQEQ, invertCondition); if (condition == null) { if (!(argValue instanceof DfaConstValue)) { for (DfaMemoryState state : states) { falseStates.add(state.createCopy()); } continue; } condition = constFactory.createFromValue( (argValue == expectedValue) != invertCondition, PsiType.BOOLEAN, null); } List<DfaMemoryState> nextStates = ContainerUtil.newArrayList(); for (DfaMemoryState state : states) { boolean unknownVsNull = expectedValue == constFactory.getNull() && argValue instanceof DfaVariableValue && ((DfaMemoryStateImpl) state) .getVariableState((DfaVariableValue) argValue) .getNullability() == Nullness.UNKNOWN; DfaMemoryState falseCopy = state.createCopy(); if (state.applyCondition(condition)) { if (unknownVsNull && !invertCondition) { state.markEphemeral(); } nextStates.add(state); } if (falseCopy.applyCondition(condition.createNegated())) { if (unknownVsNull && invertCondition) { falseCopy.markEphemeral(); } falseStates.add(falseCopy); } } states = nextStates; } for (DfaMemoryState state : states) { state.push(getDfaContractReturnValue(contract, instruction, factory)); finalStates.add(state); } return falseStates; }