diff --git a/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java b/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java new file mode 100644 index 000000000000..5fbf4c3aa5bf --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +import com.intellij.codeInsight.daemon.GroupNames; +import com.intellij.codeInsight.daemon.JavaErrorMessages; +import com.intellij.codeInspection.ex.BaseLocalInspectionTool; +import com.intellij.openapi.util.Key; +import com.intellij.psi.*; +import com.intellij.psi.util.ConstantEvaluationOverflowException; +import com.intellij.psi.util.TypeConversionUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +/** + * User: cdr + */ +public class NumericOverflowInspection extends BaseLocalInspectionTool { + private static final Key HAS_OVERFLOW_IN_CHILD = Key.create("HAS_OVERFLOW_IN_CHILD"); + + @Nls + @NotNull + @Override + public String getGroupDisplayName() { + return GroupNames.NUMERIC_GROUP_NAME; + } + + @Nls + @NotNull + @Override + public String getDisplayName() { + return "Numeric overflow"; + } + + @NotNull + @Override + public String getShortName() { + return "NumericOverflow"; + } + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { + return new JavaElementVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + visitExpression(expression); + } + + @Override + public void visitExpression(PsiExpression expression) { + boolean info = hasOverflow(expression); + if (info) { + holder.registerProblem(expression, JavaErrorMessages.message("numeric.overflow.in.expression"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + } + } + }; + } + + private static boolean hasOverflow(PsiExpression expr) { + if (!TypeConversionUtil.isNumericType(expr.getType())) return false; + boolean overflow = false; + try { + if (expr.getUserData(HAS_OVERFLOW_IN_CHILD) == null) { + JavaPsiFacade.getInstance(expr.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr, true); + } + else { + overflow = true; + } + } + catch (ConstantEvaluationOverflowException e) { + overflow = true; + } + finally { + PsiElement parent = expr.getParent(); + if (overflow && parent instanceof PsiExpression) { + parent.putUserData(HAS_OVERFLOW_IN_CHILD, ""); + } + } + + return overflow; + } + +} diff --git a/java/java-tests/testData/inspection/numericOverflow/simple/expected.xml b/java/java-tests/testData/inspection/numericOverflow/simple/expected.xml new file mode 100644 index 000000000000..197b87606e12 --- /dev/null +++ b/java/java-tests/testData/inspection/numericOverflow/simple/expected.xml @@ -0,0 +1,656 @@ + + + + Foo.java + 87 + Numeric overflow in expression + + + + + + Foo.java + 16 + Numeric overflow in expression + + + + + + Foo.java + 17 + + Numeric overflow in expression + + + + + + Foo.java + 17 + + Numeric overflow in expression + + + + + + Foo.java + 18 + + Numeric overflow in expression + + + + + + Foo.java + 18 + + Numeric overflow in expression + + + + + + Foo.java + 19 + + Numeric overflow in expression + + + + + + Foo.java + 19 + + Numeric overflow in expression + + + + + + Foo.java + 25 + + Numeric overflow in expression + + + + + + Foo.java + 27 + + Numeric overflow in expression + + + + + + Foo.java + 27 + + Numeric overflow in expression + + + + + + Foo.java + 28 + + Numeric overflow in expression + + + + + + Foo.java + 28 + + Numeric overflow in expression + + + + + + Foo.java + 29 + + Numeric overflow in expression + + + + + + Foo.java + 29 + + Numeric overflow in expression + + + + + + Foo.java + 30 + + Numeric overflow in expression + + + + + + Foo.java + 30 + + Numeric overflow in expression + + + + + + Foo.java + 34 + + Numeric overflow in expression + + + + + + Foo.java + 35 + + Numeric overflow in expression + + + + + + Foo.java + 35 + + Numeric overflow in expression + + + + + + Foo.java + 36 + + Numeric overflow in expression + + + + + + Foo.java + 36 + + Numeric overflow in expression + + + + + + Foo.java + 37 + + Numeric overflow in expression + + + + + + Foo.java + 37 + + Numeric overflow in expression + + + + + + Foo.java + 38 + + Numeric overflow in expression + + + + + + Foo.java + 38 + + Numeric overflow in expression + + + + + + Foo.java + 39 + + Numeric overflow in expression + + + + + + Foo.java + 39 + + Numeric overflow in expression + + + + + + Foo.java + 43 + + Numeric overflow in expression + + + + + + Foo.java + 43 + + Numeric overflow in expression + + + + + + Foo.java + 44 + + Numeric overflow in expression + + + + + + Foo.java + 44 + + Numeric overflow in expression + + + + + + Foo.java + 45 + + Numeric overflow in expression + + + + + + Foo.java + 45 + + Numeric overflow in expression + + + + + + Foo.java + 47 + + Numeric overflow in expression + + + + + + Foo.java + 47 + + Numeric overflow in expression + + + + + + Foo.java + 48 + + Numeric overflow in expression + + + + + + Foo.java + 48 + + Numeric overflow in expression + + + + + + Foo.java + 51 + + Numeric overflow in expression + + + + + + Foo.java + 52 + + Numeric overflow in expression + + + + + + Foo.java + 52 + + Numeric overflow in expression + + + + + + Foo.java + 53 + + Numeric overflow in expression + + + + + + Foo.java + 53 + + Numeric overflow in expression + + + + + + Foo.java + 54 + + Numeric overflow in expression + + + + + + Foo.java + 54 + + Numeric overflow in expression + + + + + + Foo.java + 55 + + Numeric overflow in expression + + + + + + Foo.java + 55 + + Numeric overflow in expression + + + + + + Foo.java + 56 + + Numeric overflow in expression + + + + + + Foo.java + 56 + + Numeric overflow in expression + + + + + + Foo.java + 60 + + Numeric overflow in expression + + + + + + Foo.java + 60 + + Numeric overflow in expression + + + + + + Foo.java + 62 + + Numeric overflow in expression + + + + + + Foo.java + 62 + + Numeric overflow in expression + + + + + + Foo.java + 63 + + Numeric overflow in expression + + + + + + Foo.java + 63 + + Numeric overflow in expression + + + + + + Foo.java + 64 + + Numeric overflow in expression + + + + + + Foo.java + 64 + + Numeric overflow in expression + + + + + + Foo.java + 65 + + Numeric overflow in expression + + + + + + Foo.java + 65 + + Numeric overflow in expression + + + + + + Foo.java + 67 + + Numeric overflow in expression + + + + + + Foo.java + 67 + + Numeric overflow in expression + + + + + + Foo.java + 68 + + Numeric overflow in expression + + + + + + Foo.java + 68 + + Numeric overflow in expression + + + + + + Foo.java + 69 + + Numeric overflow in expression + + + + + + Foo.java + 69 + + Numeric overflow in expression + + + + + + Foo.java + 71 + + Numeric overflow in expression + + + + + + Foo.java + 71 + + Numeric overflow in expression + + + + + + Foo.java + 72 + + Numeric overflow in expression + + + + + + Foo.java + 72 + + Numeric overflow in expression + + + + + + Foo.java + 72 + + Numeric overflow in expression + + + + + + Foo.java + 72 + + Numeric overflow in expression + + + + + + Foo.java + 73 + + Numeric overflow in expression + + + + + + Foo.java + 73 + + Numeric overflow in expression + + + diff --git a/java/java-tests/testData/inspection/numericOverflow/simple/src/Foo.java b/java/java-tests/testData/inspection/numericOverflow/simple/src/Foo.java new file mode 100644 index 000000000000..153606c89b08 --- /dev/null +++ b/java/java-tests/testData/inspection/numericOverflow/simple/src/Foo.java @@ -0,0 +1,88 @@ +// overflows in const expressions + + +class c { + // @*#$& ! references do not work in JRE + static final long LONG_MIN_VALUE = 0x8000000000000000L; + static final long LONG_MAX_VALUE = 0x7fffffffffffffffL; + static final int INTEGER_MIN_VALUE = 0x80000000; + static final int INTEGER_MAX_VALUE = 0x7fffffff; + static final float FLOAT_MIN_VALUE = 1.4e-45f; + static final float FLOAT_MAX_VALUE = 3.4028235e+38f; + static final double DOUBLE_MIN_VALUE = 4.9e-324; + static final double DOUBLE_MAX_VALUE = 1.7976931348623157e+308; + + void f() { + float f1 = 1.0f / 0.0f; + f1 = FLOAT_MAX_VALUE + FLOAT_MAX_VALUE; + f1 = FLOAT_MAX_VALUE * 2; + f1 = 2 / FLOAT_MIN_VALUE; + f1 = FLOAT_MIN_VALUE + 1; + f1 = - FLOAT_MIN_VALUE; + f1 = -FLOAT_MAX_VALUE; + System.out.println(f1); + + double d1 = DOUBLE_MAX_VALUE - -DOUBLE_MAX_VALUE; + d1 = DOUBLE_MAX_VALUE + 1; + d1 = 2 * DOUBLE_MAX_VALUE; + d1 = 2 / DOUBLE_MIN_VALUE; + d1 = 2 / 0.0d; + d1 = 2 / 0.0; + System.out.println(d1); + + + int i1 = INTEGER_MAX_VALUE + 1; + i1 = INTEGER_MAX_VALUE - 1 + 2; + i1 = INTEGER_MAX_VALUE - INTEGER_MIN_VALUE; + i1 = -INTEGER_MIN_VALUE; + i1 = INTEGER_MIN_VALUE - 1; + i1 = INTEGER_MIN_VALUE - INTEGER_MAX_VALUE; + i1 = INTEGER_MIN_VALUE + INTEGER_MAX_VALUE; + i1 = - INTEGER_MAX_VALUE; + i1 = - -INTEGER_MAX_VALUE; + i1 = INTEGER_MIN_VALUE * -1; + i1 = INTEGER_MIN_VALUE * 2; + i1 = INTEGER_MAX_VALUE * -2; + i1 = INTEGER_MAX_VALUE * -1; + i1 = 2 / 0; + i1 = INTEGER_MIN_VALUE / -1; + System.out.println(i1); + + long l1 = LONG_MAX_VALUE + 1; + l1 = LONG_MAX_VALUE - 1 + 2; + l1 = LONG_MAX_VALUE - LONG_MIN_VALUE; + l1 = -LONG_MIN_VALUE; + l1 = LONG_MIN_VALUE - 1; + l1 = LONG_MIN_VALUE - LONG_MAX_VALUE; + l1 = LONG_MIN_VALUE + LONG_MAX_VALUE; + l1 = - LONG_MAX_VALUE; + l1 = - -LONG_MAX_VALUE; + l1 = -INTEGER_MIN_VALUE; + l1 = -1L + INTEGER_MIN_VALUE; + l1 = LONG_MIN_VALUE * INTEGER_MIN_VALUE; + l1 = LONG_MIN_VALUE * -1; + l1 = LONG_MIN_VALUE * 2; + l1 = LONG_MAX_VALUE * -2; + l1 = INTEGER_MIN_VALUE * -1L; + l1 = 2 / 0L; + l1 = 2 % 0L; + l1 = LONG_MIN_VALUE / -1; + + l1 = 30 * 24 * 60 * 60 * 1000; + l1 = 30000000 * 243232323 + * (LONG_MAX_VALUE +3) / 5; + System.out.println(l1); + + + + } + + private static final long MILLIS_PER_DAY = 24 * 3600 * 1000; + private static final long _7DAYS = 7 * MILLIS_PER_DAY; + private static final long _30DAYS = 30 * MILLIS_PER_DAY; + private static final long _1000DAYS = 1000 * MILLIS_PER_DAY; + { + System.out.println(_1000DAYS + _30DAYS + _7DAYS); + } + int iii = 2 % 0; +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NumericOverflowTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/NumericOverflowTest.java new file mode 100644 index 000000000000..ced6335b068a --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/NumericOverflowTest.java @@ -0,0 +1,21 @@ +package com.intellij.codeInspection; + +import com.intellij.JavaTestUtil; +import com.intellij.codeInspection.defUse.DefUseInspection; +import com.intellij.testFramework.InspectionTestCase; + +public class NumericOverflowTest extends InspectionTestCase { + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath() + "/inspection"; + } + + private void doTest() throws Exception { + doTest("numericOverflow/" + getTestName(false), new NumericOverflowInspection()); + } + + + public void testSimple() throws Exception { + doTest(); + } +} diff --git a/resources-en/src/inspectionDescriptions/NumericOverflow.html b/resources-en/src/inspectionDescriptions/NumericOverflow.html new file mode 100644 index 000000000000..aa4306acc0b2 --- /dev/null +++ b/resources-en/src/inspectionDescriptions/NumericOverflow.html @@ -0,0 +1,9 @@ + + +This inspection checks for expressions which overflow during computation, i.e.:
+ +     a = 1.0/0.0; + +
+ +