mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
[java-dfa] Do not preserve long variable when downcasting to int
The have incompatible DfType, so strange things may happen GitOrigin-RevId: 54af1bcbfa7d0de67cac9c02b02fadbefb004a72
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b044a6eb2b
commit
c6f8b35d04
@@ -3,8 +3,10 @@ package com.intellij.codeInspection.dataFlow.lang.ir.inst;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
|
||||
import com.intellij.codeInspection.dataFlow.jvm.JvmPsiRangeSetUtil;
|
||||
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeBinOp;
|
||||
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfIntegralType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfIntType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfLongType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfPrimitiveType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfType;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaBinOpValue;
|
||||
@@ -13,6 +15,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -34,13 +37,13 @@ public class PrimitiveConversionInstruction extends EvalInstruction {
|
||||
DfaValue value = arguments[0];
|
||||
PsiPrimitiveType type = myTargetType;
|
||||
if (value instanceof DfaBinOpValue) {
|
||||
value = ((DfaBinOpValue)value).tryReduceOnCast(state, type);
|
||||
value = tryReduceOnCast(((DfaBinOpValue)value), state, type);
|
||||
}
|
||||
|
||||
DfType dfType = state.getDfType(value);
|
||||
if (value instanceof DfaVariableValue && dfType instanceof DfIntegralType) {
|
||||
if (value instanceof DfaVariableValue && dfType instanceof DfIntType) {
|
||||
LongRangeSet set = JvmPsiRangeSetUtil.typeRange(type);
|
||||
if (set != null && !LongRangeSet.all().equals(set) && ((DfIntegralType)dfType).meetRange(set).equals(dfType)) {
|
||||
if (set != null && !LongRangeSet.all().equals(set) && ((DfIntType)dfType).meetRange(set).equals(dfType)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -54,4 +57,20 @@ public class PrimitiveConversionInstruction extends EvalInstruction {
|
||||
public String toString() {
|
||||
return "CONVERT_PRIMITIVE " + myTargetType.getPresentableText();
|
||||
}
|
||||
|
||||
private static @NotNull DfaValue tryReduceOnCast(@NotNull DfaBinOpValue value,
|
||||
@NotNull DfaMemoryState state,
|
||||
@NotNull PsiPrimitiveType type) {
|
||||
if (!TypeConversionUtil.isIntegralNumberType(type)) return value;
|
||||
LongRangeBinOp operation = value.getOperation();
|
||||
if ((operation == LongRangeBinOp.PLUS || operation == LongRangeBinOp.MINUS) &&
|
||||
JvmPsiRangeSetUtil.castTo(DfLongType.extractRange(state.getDfType(value.getRight())), type).equals(LongRangeSet.point(0))) {
|
||||
return value.getLeft();
|
||||
}
|
||||
if (operation == LongRangeBinOp.PLUS &&
|
||||
JvmPsiRangeSetUtil.castTo(DfLongType.extractRange(state.getDfType(value.getLeft())), type).equals(LongRangeSet.point(0))) {
|
||||
return value.getRight();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
package com.intellij.codeInspection.dataFlow.value;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
|
||||
import com.intellij.codeInspection.dataFlow.jvm.JvmPsiRangeSetUtil;
|
||||
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeBinOp;
|
||||
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
|
||||
import com.intellij.codeInspection.dataFlow.types.*;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfConstantType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfIntegralType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfTypes;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -96,20 +96,6 @@ public final class DfaBinOpValue extends DfaValue {
|
||||
return myLeft + delimiter + myRight;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaValue tryReduceOnCast(DfaMemoryState state, PsiPrimitiveType type) {
|
||||
if (!TypeConversionUtil.isIntegralNumberType(type)) return this;
|
||||
if ((myOp == LongRangeBinOp.PLUS || myOp == LongRangeBinOp.MINUS) &&
|
||||
JvmPsiRangeSetUtil.castTo(DfLongType.extractRange(state.getDfType(myRight)), type).equals(LongRangeSet.point(0))) {
|
||||
return myLeft;
|
||||
}
|
||||
if (myOp == LongRangeBinOp.PLUS &&
|
||||
JvmPsiRangeSetUtil.castTo(DfLongType.extractRange(state.getDfType(myLeft)), type).equals(LongRangeSet.point(0))) {
|
||||
return myRight;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static long extractLong(DfaTypeValue right) {
|
||||
return Objects.requireNonNull(right.getDfType().getConstantOfType(Number.class)).longValue();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.util.*;
|
||||
|
||||
public class ArrayAccessWithCastInCountedLoop {
|
||||
void aioobe(int[] arr) {
|
||||
for (long i = 0; i < arr.length; i++) {
|
||||
System.out.println(arr[(int) i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,4 +80,5 @@ public class DataFlowRangeAnalysisTest extends DataFlowInspectionTestCase {
|
||||
public void testCollectionAddRemove() { doTest(); }
|
||||
public void testRelationsOnAddition() { doTest(); }
|
||||
public void testModSpecialCase() { doTest(); }
|
||||
public void testArrayAccessWithCastInCountedLoop() { doTest(); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user