From bf9726c4ed9e39e0662935d374a4fd9465fde0a9 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 26 Jan 2021 15:30:29 +0700 Subject: [PATCH] [java-dfa] Avoid extra unboxing in prefix inc/dec operation Fixes IDEA-260267 Integer equality not properly evaluated after auto-increment GitOrigin-RevId: 981901b35969c900ae17a362a74dd53884518295 --- .../dataFlow/ControlFlowAnalyzer.java | 28 ++++++++++--------- .../dataFlow/fixture/BoxingIncrement.java | 17 +++++++++++ .../DataFlowInspectionTest.java | 1 + 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/BoxingIncrement.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 54edf6e294e8..3435ab637fb6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1941,26 +1941,28 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } else { operand.accept(this); - PsiType type = expression.getType(); - PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type); - generateBoxingUnboxingInstructionFor(operand, unboxed == null ? type : unboxed); if (PsiUtil.isIncrementDecrementOperation(expression)) { if (!processIncrementDecrement(expression, operand)) { pushUnknown(); addInstruction(new AssignInstruction(operand, null, myFactory.createValue(operand))); } } - else if (expression.getOperationTokenType() == JavaTokenType.EXCL) { - addInstruction(new NotInstruction(expression)); - } - else if (expression.getOperationTokenType() == JavaTokenType.MINUS && (PsiType.INT.equals(type) || PsiType.LONG.equals(type))) { - addInstruction(new PushValueInstruction(DfTypes.defaultValue(type))); - addInstruction(new SwapInstruction()); - addInstruction(new BinopInstruction(expression.getOperationTokenType(), expression, type)); - } else { - addInstruction(new PopInstruction()); - pushUnknown(); + PsiType type = expression.getType(); + PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type); + generateBoxingUnboxingInstructionFor(operand, unboxed == null ? type : unboxed); + if (expression.getOperationTokenType() == JavaTokenType.EXCL) { + addInstruction(new NotInstruction(expression)); + } + else if (expression.getOperationTokenType() == JavaTokenType.MINUS && (PsiType.INT.equals(type) || PsiType.LONG.equals(type))) { + addInstruction(new PushValueInstruction(DfTypes.defaultValue(type))); + addInstruction(new SwapInstruction()); + addInstruction(new BinopInstruction(expression.getOperationTokenType(), expression, type)); + } + else { + addInstruction(new PopInstruction()); + pushUnknown(); + } } } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/BoxingIncrement.java b/java/java-tests/testData/inspection/dataFlow/fixture/BoxingIncrement.java new file mode 100644 index 000000000000..e2430bbbc5fe --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/BoxingIncrement.java @@ -0,0 +1,17 @@ +class X { + void test() { + Integer integer = 0; + ++integer; + if (integer == 1) { + System.out.println("Line to be printed"); + } + } + + void test2() { + Integer integer = 0; + integer++; + if (integer == 1) { + System.out.println("Line to be printed"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index f6534018bbcc..5a47fdcc1cc4 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -679,6 +679,7 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testProtobufNotNullGetters() { doTest(); } public void testAIOOBETransfer() { doTest(); } public void testBoxingShortByte() { doTest(); } + public void testBoxingIncrement() { doTest(); } public void testUnboxingWithConversionCalls() { doTest(); } public void testNullableAliasing() { doTest(); } public void testReapplyTypeArguments() { doTest(); }