예제 #1
0
  private boolean applyEquivalenceRelation(
      @NotNull DfaRelationValue dfaRelation, DfaValue dfaLeft, DfaValue dfaRight) {
    boolean isNegated = dfaRelation.isNonEquality();
    if (!isNegated && !dfaRelation.isEquality()) {
      return true;
    }

    final boolean containsCalls =
        dfaLeft instanceof DfaVariableValue && ((DfaVariableValue) dfaLeft).containsCalls();

    // track "x" property state only inside "if (getX() != null) ..."
    if (containsCalls && !isNotNull(dfaLeft) && isNull(dfaRight) && !isNegated) {
      return true;
    }

    if (dfaLeft == dfaRight) {
      return containsCalls || !isNegated;
    }

    if (isNull(dfaLeft) && isNotNull(dfaRight) || isNull(dfaRight) && isNotNull(dfaLeft)) {
      return isNegated;
    }

    if (!isNegated) {
      if (dfaLeft instanceof DfaVariableValue) {
        updateVarStateOnComparison((DfaVariableValue) dfaLeft, dfaRight);
      }
      if (dfaRight instanceof DfaVariableValue) {
        updateVarStateOnComparison((DfaVariableValue) dfaRight, dfaLeft);
      }
    }

    if (!applyRelation(dfaLeft, dfaRight, isNegated)) {
      return false;
    }
    if (!checkCompareWithBooleanLiteral(dfaLeft, dfaRight, isNegated)) {
      return false;
    }
    if (dfaLeft instanceof DfaVariableValue) {
      if (!applyUnboxedRelation((DfaVariableValue) dfaLeft, dfaRight, isNegated)) {
        return false;
      }
      if (!applyBoxedRelation((DfaVariableValue) dfaLeft, dfaRight, isNegated)) {
        return false;
      }
    }

    return true;
  }
예제 #2
0
  @Override
  public boolean applyInstanceofOrNull(@NotNull DfaRelationValue dfaCond) {
    DfaValue left = unwrap(dfaCond.getLeftOperand());

    if (!(left instanceof DfaVariableValue)) return true;

    DfaVariableValue dfaVar = (DfaVariableValue) left;
    DfaTypeValue dfaType = (DfaTypeValue) dfaCond.getRightOperand();

    if (isUnknownState(dfaVar) || isNull(dfaVar)) return true;
    DfaVariableState newState = getVariableState(dfaVar).withInstanceofValue(dfaType);
    if (newState != null) {
      setVariableState(dfaVar, newState);
      return true;
    }
    return false;
  }
  @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()]);
  }
  @Nullable
  private static DfaInstructionState[] handleConstantComparison(
      BinopInstruction instruction,
      DataFlowRunner runner,
      DfaMemoryState memState,
      DfaValue dfaRight,
      DfaValue dfaLeft,
      IElementType opSign) {
    if (dfaRight instanceof DfaConstValue && dfaLeft instanceof DfaVariableValue) {
      Object value = ((DfaConstValue) dfaRight).getValue();
      if (value instanceof Number) {
        DfaInstructionState[] result =
            checkComparingWithConstant(
                instruction,
                runner,
                memState,
                (DfaVariableValue) dfaLeft,
                opSign,
                ((Number) value).doubleValue());
        if (result != null) {
          return result;
        }
      }
    }
    if (dfaRight instanceof DfaVariableValue && dfaLeft instanceof DfaConstValue) {
      return handleConstantComparison(
          instruction,
          runner,
          memState,
          dfaLeft,
          dfaRight,
          DfaRelationValue.getSymmetricOperation(opSign));
    }

    if (EQEQ != opSign && NE != opSign) {
      return null;
    }

    if (dfaLeft instanceof DfaConstValue && dfaRight instanceof DfaConstValue
        || dfaLeft == runner.getFactory().getConstFactory().getContractFail()
        || dfaRight == runner.getFactory().getConstFactory().getContractFail()) {
      boolean negated =
          (NE == opSign)
              ^ (DfaMemoryStateImpl.isNaN(dfaLeft) || DfaMemoryStateImpl.isNaN(dfaRight));
      if (dfaLeft == dfaRight ^ negated) {
        return alwaysTrue(instruction, runner, memState);
      }
      return alwaysFalse(instruction, runner, memState);
    }

    return null;
  }
예제 #5
0
  private boolean applyRelationCondition(@NotNull DfaRelationValue dfaRelation) {
    DfaValue dfaLeft = dfaRelation.getLeftOperand();
    DfaValue dfaRight = dfaRelation.getRightOperand();
    if (dfaLeft instanceof DfaUnknownValue || dfaRight instanceof DfaUnknownValue) return true;

    boolean isNegated = dfaRelation.isNegated();
    if (dfaLeft instanceof DfaTypeValue
        && ((DfaTypeValue) dfaLeft).isNotNull()
        && dfaRight == myFactory.getConstFactory().getNull()) {
      return isNegated;
    }

    if (dfaRight instanceof DfaTypeValue) {
      if (dfaLeft instanceof DfaVariableValue) {
        DfaVariableValue dfaVar = (DfaVariableValue) dfaLeft;
        if (isUnknownState(dfaVar)) return true;

        if (!dfaRelation.isInstanceOf()) {
          if (((DfaTypeValue) dfaRight).isNotNull() && isNull(dfaVar)) {
            return isNegated;
          }
          return true;
        }

        if (isNegated) {
          DfaVariableState newState =
              getVariableState(dfaVar).withNotInstanceofValue((DfaTypeValue) dfaRight);
          if (newState != null) {
            setVariableState(dfaVar, newState);
            return true;
          }
          return !getVariableState(dfaVar).isNotNull()
              && applyRelation(dfaVar, myFactory.getConstFactory().getNull(), false);
        }
        if (applyRelation(dfaVar, myFactory.getConstFactory().getNull(), true)) {
          DfaVariableState newState =
              getVariableState(dfaVar).withInstanceofValue((DfaTypeValue) dfaRight);
          if (newState != null) {
            setVariableState(dfaVar, newState);
            return true;
          }
        }
        return false;
      }
      return true;
    }

    if (isEffectivelyNaN(dfaLeft) || isEffectivelyNaN(dfaRight)) {
      applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
      return isNegated;
    }
    if (canBeNaN(dfaLeft) && canBeNaN(dfaRight)) {
      if (dfaLeft == dfaRight
          && dfaLeft instanceof DfaVariableValue
          && !(((DfaVariableValue) dfaLeft).getVariableType() instanceof PsiPrimitiveType)) {
        return !isNegated;
      }

      applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
      return true;
    }

    return applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
  }