From 8aa936dc004f8dd6cd1c4e3f1dbaab048b210420 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 20 Feb 2019 16:35:45 +0700 Subject: [PATCH] Flush canonicalized variable if requested one not found Fixes IDEA-207441 False-positive "variable is always null" on linked-list like data structure --- .../dataFlow/DfaMemoryStateImpl.java | 7 ++- .../fixture/HashMapImplementation.java | 45 +++++++++++++++++++ .../DataFlowInspection8Test.java | 1 + 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/HashMapImplementation.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index 29dc00a6a58b..41fb5c77f196 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -1530,7 +1530,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState { private void removeEquivalence(DfaValue var) { int varID = var.getID(); Integer varClassIndex = myIdToEqClassesIndices.get(varID); - if (varClassIndex == null) return; + if (varClassIndex == null) { + var = canonicalize(var); + varID = var.getID(); + varClassIndex = myIdToEqClassesIndices.get(varID); + if (varClassIndex == null) return; + } EqClass varClass = myEqClasses.get(varClassIndex); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/HashMapImplementation.java b/java/java-tests/testData/inspection/dataFlow/fixture/HashMapImplementation.java new file mode 100644 index 000000000000..8d4b3f99f30c --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/HashMapImplementation.java @@ -0,0 +1,45 @@ +import org.jetbrains.annotations.Nullable; + +class IntHashMap { + + public void minTest() { + initEntries(); + + for (Entry entry : table) { + if (entry != null) { + Entry tmp = entry; + Entry tmpNext; + + while (tmp != null) { + tmpNext = tmp.next; + tmp.next = null; + tmp = tmpNext; + System.out.println("tmpNext " + ((tmpNext == null) ? "is null" : "is not null")); + } + } + } + } + + private Entry[] table = new Entry[16]; + + private class Entry { + @Nullable Entry next; + } + + + private void initEntries() { + table[0] = new Entry(); + table[0].next = new Entry(); + + table[1] = new Entry(); + + table[3] = new Entry(); + + table[5] = new Entry(); + table[5].next = new Entry(); + } + public static void main(String[] args) { + IntHashMap map = new IntHashMap(); + map.minTest(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java index 28aada0591c5..fd8d0644bc29 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -214,6 +214,7 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { public void testPrimitiveGetters() { doTest(); } public void testUnknownOnStack() { doTest(); } public void testMapUpdateInlining() { doTestWithCustomAnnotations(); } + public void testHashMapImplementation() { doTest(); } public void testOptionalTooComplex() { doTest(); }