From 7e678abdaf398d775c55ed61bfe429785675b5d2 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 9 Aug 2021 17:48:26 +0700 Subject: [PATCH] [java-dfa] Properly meet two inverted ranges when excluded parts don't intersect Fixes IDEA-275487 Incorrect warning when using consecutive expressions to determine the unordered numbers GitOrigin-RevId: 14c0dd4e81b7b399ff5e5aac7dd036312ea8d9ad --- .../dataFlow/types/DfDoubleRangeType.java | 16 +++++++++++++--- .../dataFlow/types/DfFloatRangeType.java | 16 +++++++++++++--- .../dataFlow/fixture/FloatingPointRanges.java | 4 ++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfDoubleRangeType.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfDoubleRangeType.java index 4988b7b13f34..d607ad226b4c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfDoubleRangeType.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfDoubleRangeType.java @@ -172,9 +172,19 @@ class DfDoubleRangeType implements DfDoubleType { if (!range.myInvert) { return range.meet(this); } else { - double from = Math.min(myFrom, range.myFrom); - double to = Math.max(myTo, range.myTo); - return create(from, to, true, nan); + // both inverted + if (myTo >= Math.nextDown(range.myFrom) && range.myTo >= Math.nextDown(myFrom)) { + // excluded ranges intersect or touch each other: we can exclude their union + double from = Math.min(myFrom, range.myFrom); + double to = Math.max(myTo, range.myTo); + return create(from, to, true, nan); + } + // excluded ranges don't intersect: we cannot encode this case + // just keep one of the ranges (with lesser from, for stability) + if (myFrom < range.myFrom) { + return create(myFrom, myTo, true, nan); + } + return create(range.myFrom, range.myTo, true, nan); } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfFloatRangeType.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfFloatRangeType.java index 0816d030dffe..4c57e9e51fbb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfFloatRangeType.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/types/DfFloatRangeType.java @@ -172,9 +172,19 @@ class DfFloatRangeType implements DfFloatType { if (!range.myInvert) { return range.meet(this); } else { - float from = Math.min(myFrom, range.myFrom); - float to = Math.max(myTo, range.myTo); - return create(from, to, true, nan); + // both inverted + if (myTo >= Math.nextDown(range.myFrom) && range.myTo >= Math.nextDown(myFrom)) { + // excluded ranges intersect or touch each other: we can exclude their union + float from = Math.min(myFrom, range.myFrom); + float to = Math.max(myTo, range.myTo); + return create(from, to, true, nan); + } + // excluded ranges don't intersect: we cannot encode this case + // just keep one of the ranges (with lesser from, for stability) + if (myFrom < range.myFrom) { + return create(myFrom, myTo, true, nan); + } + return create(range.myFrom, range.myTo, true, nan); } } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FloatingPointRanges.java b/java/java-tests/testData/inspection/dataFlow/fixture/FloatingPointRanges.java index e5c20ab8f64e..3b81fdc0a06d 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/FloatingPointRanges.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FloatingPointRanges.java @@ -1,6 +1,10 @@ import java.util.*; public class FloatingPointRanges { + public static boolean isSpecial(double value) { + return value == 1.0 || value == -1.0 || value == 0.0; + } + void testSimple(double d) { if (d > Double.POSITIVE_INFINITY) {} if (d < Double.NEGATIVE_INFINITY) {}