From ad81bf2d4aef678b9457c982c7221fda625f00ef Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 31 Jul 2018 02:23:54 +0700 Subject: [PATCH] ControlFlowAnalyzer: add missing boxing on loop unrolling when necessary --- .../com/intellij/codeInspection/dataFlow/CFGBuilder.java | 2 +- .../codeInspection/dataFlow/ControlFlowAnalyzer.java | 6 +++--- .../codeInspection/dataFlow/value/DfaExpressionFactory.java | 2 +- .../codeInspection/dataFlow/value/DfaValueFactory.java | 4 ++-- .../dataFlow/fixture/ForeachCollectionElement.java | 5 +++++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java index 17456a2ea826..ffd8d3bcd849 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java @@ -721,7 +721,7 @@ public class CFGBuilder { ConditionalGotoInstruction condGoto = new ConditionalGotoInstruction(null, false, null); condGoto.setOffset(myAnalyzer.getInstructionCount()); myBranches.add(() -> pushUnknown().add(condGoto)); - assign(targetVariable, factory.createCommonValue(expressions)); + assign(targetVariable, factory.createCommonValue(expressions, targetVariable.getVariableType())); } else { push(factory.getConstFactory().getSentinel()); for (PsiExpression expression : expressions) { 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 6713b7eeb980..87a287b337cf 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 @@ -485,7 +485,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { finishElement(statement); } - private DfaValue getIteratedElement(PsiExpression iteratedValue) { + private DfaValue getIteratedElement(PsiType type, PsiExpression iteratedValue) { PsiExpression[] expressions = null; if (iteratedValue instanceof PsiNewExpression) { PsiArrayInitializerExpression initializer = ((PsiNewExpression)iteratedValue).getArrayInitializer(); @@ -502,7 +502,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { if (iteratedValue instanceof PsiMethodCallExpression && LIST_INITIALIZER.test((PsiMethodCallExpression)iteratedValue)) { expressions = ((PsiMethodCallExpression)iteratedValue).getArgumentList().getExpressions(); } - return expressions == null ? DfaUnknownValue.getInstance() : getFactory().createCommonValue(expressions); + return expressions == null ? DfaUnknownValue.getInstance() : getFactory().createCommonValue(expressions, type); } @Override public void visitForeachStatement(PsiForeachStatement statement) { @@ -539,7 +539,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { ControlFlowOffset offset = myCurrentFlow.getNextOffset(); DfaVariableValue dfaVariable = myFactory.getVarFactory().createVariableValue(parameter); - new CFGBuilder(this).assignAndPop(dfaVariable, getIteratedElement(iteratedValue)); + new CFGBuilder(this).assignAndPop(dfaVariable, getIteratedElement(parameter.getType(), iteratedValue)); if (!hasSizeCheck) { pushUnknown(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java index 98bc6fd1807a..e4b42b0b2ef7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java @@ -322,7 +322,7 @@ public class DfaExpressionFactory { .orElse(DfaUnknownValue.getInstance()); } - private DfaValue boxUnbox(DfaValue value, PsiType type) { + DfaValue boxUnbox(DfaValue value, PsiType type) { if (TypeConversionUtil.isPrimitiveWrapper(type)) { if (value instanceof DfaConstValue || value instanceof DfaUnboxedValue || (value instanceof DfaVariableValue && TypeConversionUtil.isPrimitiveAndNotNull(((DfaVariableValue)value).getVariableType()))) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java index 31775a2efe15..904668446d91 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java @@ -262,7 +262,7 @@ public class DfaValueFactory { public DfaExpressionFactory getExpressionFactory() { return myExpressionFactory;} @NotNull - public DfaValue createCommonValue(@NotNull PsiExpression[] expressions) { + public DfaValue createCommonValue(@NotNull PsiExpression[] expressions, PsiType targetType) { DfaValue loopElement = null; for (PsiExpression expression : expressions) { DfaValue expressionValue = createValue(expression); @@ -272,7 +272,7 @@ public class DfaValueFactory { loopElement = loopElement == null ? expressionValue : loopElement.union(expressionValue); if (loopElement == DfaUnknownValue.getInstance()) break; } - return loopElement == null ? DfaUnknownValue.getInstance() : loopElement; + return loopElement == null ? DfaUnknownValue.getInstance() : getExpressionFactory().boxUnbox(loopElement, targetType); } private static class ClassInitializationInfo { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ForeachCollectionElement.java b/java/java-tests/testData/inspection/dataFlow/fixture/ForeachCollectionElement.java index cbbca3596151..19729b27f3b2 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ForeachCollectionElement.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ForeachCollectionElement.java @@ -26,4 +26,9 @@ class ForeachCollectionElement { } } } + + void test4() { + for(Integer x : Arrays.asList(1)) { + } + } }