public DfaInstructionState[] visitNot( NotInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { DfaValue dfaValue = memState.pop(); dfaValue = dfaValue.createNegated(); memState.push(dfaValue); return nextInstruction(instruction, runner, memState); }
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("for boxed values which can't be compared by ==") private Integer getOrCreateEqClassIndex(@NotNull DfaValue dfaValue) { int i = getEqClassIndex(dfaValue); if (i != -1) return i; if (!canBeInRelation(dfaValue) || !canBeReused(dfaValue) && !(((DfaBoxedValue) dfaValue).getWrappedValue() instanceof DfaConstValue)) { return null; } int freeIndex = myEqClasses.indexOf(null); int resultIndex = freeIndex >= 0 ? freeIndex : myEqClasses.size(); EqClass aClass = new EqClass(myFactory); aClass.add(dfaValue.getID()); if (freeIndex >= 0) { myEqClasses.set(freeIndex, aClass); } else { myEqClasses.add(aClass); } addToMap(dfaValue.getID(), resultIndex); return resultIndex; }
private int getEqClassIndex(@NotNull final DfaValue dfaValue) { final int id = unwrap(dfaValue).getID(); int[] classes = myIdToEqClassesIndices.get(id); int result = -1; if (classes != null) { for (int index : classes) { EqClass aClass = myEqClasses.get(index); if (!aClass.contains(dfaValue.getID())) continue; if (!canBeReused(dfaValue) && aClass.size() > 1) break; result = index; break; } } return result; }
private boolean checkCompareWithBooleanLiteral( DfaValue dfaLeft, DfaValue dfaRight, boolean negated) { if (dfaRight instanceof DfaConstValue) { Object constVal = ((DfaConstValue) dfaRight).getValue(); if (constVal instanceof Boolean) { DfaConstValue negVal = myFactory .getConstFactory() .createFromValue(!((Boolean) constVal).booleanValue(), PsiType.BOOLEAN, null); if (!applyRelation(dfaLeft, negVal, !negated)) { return false; } if (!applyRelation(dfaLeft.createNegated(), negVal, negated)) { return false; } } } return true; }
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; }