From e652cc3b6f01551ea19193f884814a5a9a7b82b0 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 14 Jan 2019 09:41:26 +0700 Subject: [PATCH] DFA: support of arithmetic no-ops (*1, /1, >>0, etc.) --- .../dataFlow/value/DfaBinOpValue.java | 10 +++++++ .../dataFlow/fixture/ArithmeticNoOp.java | 27 +++++++++++++++++++ .../DataFlowRangeAnalysisTest.java | 1 + 3 files changed, 38 insertions(+) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/ArithmeticNoOp.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java index 18a4762c144a..9e9a4a471496 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java @@ -95,6 +95,16 @@ public class DfaBinOpValue extends DfaValue { } LongRangeSet leftRange = state.getValueFact(left, DfaFactType.RANGE); LongRangeSet rightRange = state.getValueFact(right, DfaFactType.RANGE); + if (tokenType.equals(JavaTokenType.ASTERISK)) { + if (LongRangeSet.point(1).equals(leftRange)) return right; + if (LongRangeSet.point(1).equals(rightRange)) return left; + } + if (tokenType.equals(JavaTokenType.DIV)) { + if (LongRangeSet.point(1).equals(rightRange)) return left; + } + if (tokenType.equals(JavaTokenType.GTGT) || tokenType.equals(JavaTokenType.LTLT) || tokenType.equals(JavaTokenType.GTGTGT)) { + if (LongRangeSet.point(0).equals(rightRange)) return left; + } if (leftRange != null && rightRange != null) { LongRangeSet result = leftRange.binOpFromToken(tokenType, rightRange, isLong); return myFactory.getFactValue(DfaFactType.RANGE, result); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ArithmeticNoOp.java b/java/java-tests/testData/inspection/dataFlow/fixture/ArithmeticNoOp.java new file mode 100644 index 000000000000..b47f94a27111 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ArithmeticNoOp.java @@ -0,0 +1,27 @@ +import java.util.*; + +public class ArithmeticNoOp { + void test(long x, int y) { + if(y == 1) { + long z = x * y; + long t = x / y; + long u = y / z; + long w = y * z; + if (z == x) {} + if (t == x) {} + if (w == x) {} + if (u == x) {} + } + if(y == 0) { + long a = x >> y; + long b = x << y; + long c = x >>> y; + long d = y >>> x; + if (a == x) {} + if (b == x) {} + if (c == x) {} + if (d == x) {} + if (d == y) {} + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowRangeAnalysisTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowRangeAnalysisTest.java index 640ade8ae1fb..6b9b93268f1b 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowRangeAnalysisTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowRangeAnalysisTest.java @@ -60,4 +60,5 @@ public class DataFlowRangeAnalysisTest extends DataFlowInspectionTestCase { public void testTwoArraysDiff() { doTest(); } public void testModRange() { doTest(); } public void testBackPropagationMod() { doTest(); } + public void testArithmeticNoOp() { doTest(); } }