This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 65ce840a7c GROOVY-11348: STC: check loss of precision for `(short) 
1234` literals
65ce840a7c is described below

commit 65ce840a7cde7460637e52b716d20741cf1d2f77
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Tue Jul 9 12:33:01 2024 -0500

    GROOVY-11348: STC: check loss of precision for `(short) 1234` literals
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 105 ++++++++++-----------
 .../groovy/transform/stc/STCAssignmentTest.groovy  |  80 ++++++++++------
 2 files changed, 101 insertions(+), 84 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 4714beb24e..286283a4ec 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -767,74 +767,65 @@ public abstract class StaticTypeCheckingSupport {
         return (node.getCompileUnit() != null);
     }
 
-    @Deprecated(forRemoval = true, since = "3.0.0")
-    static boolean checkPossibleLooseOfPrecision(final ClassNode left, final 
ClassNode right, final Expression rightExpr) {
-        return checkPossibleLossOfPrecision(left, right, rightExpr);
-    }
-
     static boolean checkPossibleLossOfPrecision(final ClassNode left, final 
ClassNode right, final Expression rightExpr) {
         if (left == right || left.equals(right)) return false; // identical 
types
         int leftIndex = NUMBER_TYPES.get(left);
         int rightIndex = NUMBER_TYPES.get(right);
         if (leftIndex >= rightIndex) return false;
-        // here we must check if the right number is short enough to fit in 
the left type
-        if (rightExpr instanceof ConstantExpression) {
-            Object value = ((ConstantExpression) rightExpr).getValue();
-            if (!(value instanceof Number)) return true;
+
+        // check if the right number will fit in the left type
+        Expression valueExpr = rightExpr;
+        if (valueExpr instanceof CastExpression) // "(short) 1234"
+            valueExpr = ((CastExpression) valueExpr).getExpression();
+        if (valueExpr instanceof ConstantExpression) {
+            Object value = ((ConstantExpression) valueExpr).getValue();
+            if (!(value instanceof Number)) return true; // null or ...
             Number number = (Number) value;
             switch (leftIndex) {
-                case 0: { // byte
-                    byte val = number.byteValue();
-                    if (number instanceof Short) {
-                        return !Short.valueOf(val).equals(number);
-                    }
-                    if (number instanceof Integer) {
-                        return !Integer.valueOf(val).equals(number);
-                    }
-                    if (number instanceof Long) {
-                        return !Long.valueOf(val).equals(number);
-                    }
-                    if (number instanceof Float) {
-                        return !Float.valueOf(val).equals(number);
-                    }
-                    return !Double.valueOf(val).equals(number);
+              case 0: // byte
+                switch (rightIndex) {
+                  case 1:
+                    return Short  .compare(number.byteValue(), number. 
shortValue()) != 0;
+                  case 2:
+                    return Integer.compare(number.byteValue(), number.   
intValue()) != 0;
+                  case 3:
+                    return Long   .compare(number.byteValue(), number.  
longValue()) != 0;
+                  case 4:
+                    return Float  .compare(number.byteValue(), number. 
floatValue()) != 0;
+                  default:
+                    return Double .compare(number.byteValue(), 
number.doubleValue()) != 0;
                 }
-                case 1: { // short
-                    short val = number.shortValue();
-                    if (number instanceof Integer) {
-                        return !Integer.valueOf(val).equals(number);
-                    }
-                    if (number instanceof Long) {
-                        return !Long.valueOf(val).equals(number);
-                    }
-                    if (number instanceof Float) {
-                        return !Float.valueOf(val).equals(number);
-                    }
-                    return !Double.valueOf(val).equals(number);
+              case 1: // short
+                switch (rightIndex) {
+                  case 2:
+                    return Integer.compare(number.shortValue(), number.   
intValue()) != 0;
+                  case 3:
+                    return Long   .compare(number.shortValue(), number.  
longValue()) != 0;
+                  case 4:
+                    return Float  .compare(number.shortValue(), number. 
floatValue()) != 0;
+                  default:
+                    return Double .compare(number.shortValue(), 
number.doubleValue()) != 0;
                 }
-                case 2: { // integer
-                    int val = number.intValue();
-                    if (number instanceof Long) {
-                        return !Long.valueOf(val).equals(number);
-                    }
-                    if (number instanceof Float) {
-                        return !Float.valueOf(val).equals(number);
-                    }
-                    return !Double.valueOf(val).equals(number);
-                }
-                case 3: { // long
-                    long val = number.longValue();
-                    if (number instanceof Float) {
-                        return !Float.valueOf(val).equals(number);
-                    }
-                    return !Double.valueOf(val).equals(number);
+              case 2: // int
+                switch (rightIndex) {
+                  case 3:
+                    return Long  .compare(number.intValue(), number.  
longValue()) != 0;
+                  case 4:
+                    return Float .compare(number.intValue(), number. 
floatValue()) != 0;
+                  default:
+                    return Double.compare(number.intValue(), 
number.doubleValue()) != 0;
                 }
-                case 4: { // float
-                    float val = number.floatValue();
-                    return !Double.valueOf(val).equals(number);
+              case 3: // long
+                switch (rightIndex) {
+                  case 4:
+                    return Float .compare(number.longValue(), number. 
floatValue()) != 0;
+                  default:
+                    return Double.compare(number.longValue(), 
number.doubleValue()) != 0;
                 }
-                default: // double
-                    return false; // no possible loss here
+              case 4: // float
+                return Double.compare(number.floatValue(), 
number.doubleValue()) != 0;
+              default: // double
+                return false; // no possible loss here
             }
         }
         return true; // possible loss of precision
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy 
b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index db6e5e1bbd..8df0dec4ae 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -107,6 +107,30 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase 
{
         '''
     }
 
+    void testAssignmentToNumbers() {
+        for (type in ['byte','short','int','long','float','double',
+            'java.lang.Byte','java.lang.Short','java.lang.Integer',
+            'java.lang.Long','java.lang.Float','java.lang.Double']) {
+            boolean primitive = !type.contains('.')
+            shouldFailWithMessages """
+                $type x = 0
+                x = (byte)1
+                x = (char)2 // cannot assign
+                x =(short)3 // possible loss -- GROOVY-11348
+                x = 4
+                x = 5L
+                x = 6f
+                x = 7d
+                x = 8g      // cannot assign
+              //x = 9.0g    // okay for float and double
+                x = (Number)10
+            """,
+            "Cannot assign value of type ${primitive ? 'char' : 
'java.lang.Character'} to variable of type $type",
+            "Cannot assign value of type java.math.BigInteger to variable of 
type $type",
+            "Cannot assign value of type java.lang.Number to variable of type 
$type"
+        }
+    }
+
     void testAssignmentToBoolean() {
         assertScript '''
             boolean b = new Object()
@@ -219,70 +243,72 @@ class STCAssignmentTest extends 
StaticTypeCheckingTestCase {
     }
 
     void testPossibleLossOfPrecision1() {
-        shouldFailWithMessages '''
-            long a = Long.MAX_VALUE
-            int b = a
-        ''',
-        'Possible loss of precision from long to int'
-    }
-
-    void testPossibleLossOfPrecision2() {
-        assertScript '''
-            int b = 0L
-        '''
-    }
-
-    void testPossibleLossOfPrecision3() {
         assertScript '''
             byte b = 127
         '''
     }
 
-    void testPossibleLossOfPrecision4() {
+    void testPossibleLossOfPrecision2() {
         shouldFailWithMessages '''
             byte b = 128 // will not fit in a byte
         ''',
         'Possible loss of precision from int to byte'
     }
 
-    void testPossibleLossOfPrecision5() {
+    void testPossibleLossOfPrecision3() {
         assertScript '''
-            short b = 128
+            short s = 128
         '''
     }
 
-    void testPossibleLossOfPrecision6() {
+    void testPossibleLossOfPrecision4() {
         shouldFailWithMessages '''
-            short b = 32768 // will not fit in a short
+            short s = 32768 // will not fit in a short
         ''',
         'Possible loss of precision from int to short'
     }
 
-    void testPossibleLossOfPrecision7() {
+    void testPossibleLossOfPrecision5() {
         assertScript '''
-            int b = 32768L // mark it as a long, but it fits into an int
+            int i = 32768L // mark it as a long, but it fits into an int
         '''
     }
 
-    void testPossibleLossOfPrecision8() {
+    void testPossibleLossOfPrecision6() {
         assertScript '''
-            int b = 32768.0f // mark it as a float, but it fits into an int
+            int i = 32768f // mark it as a float, but it fits into an int
         '''
     }
 
-    void testPossibleLossOfPrecision9() {
+    void testPossibleLossOfPrecision7() {
         assertScript '''
-            int b = 32768.0d // mark it as a double, but it fits into an int
+            int i = 32768d // mark it as a double, but it fits into an int
         '''
     }
 
-    void testPossibleLossOfPrecision10() {
+    void testPossibleLossOfPrecision8() {
         shouldFailWithMessages '''
-            int b = 32768.1d
+            int i = 32768.1d
         ''',
         'Possible loss of precision from double to int'
     }
 
+    void testPossibleLossOfPrecision9() {
+        shouldFailWithMessages '''
+            int i = Long.MAX_VALUE
+        ''',
+        'Possible loss of precision from long to int'
+    }
+
+    void testPossibleLossOfPrecision10() {
+        assertScript '''
+            byte  b = 0L
+            short s = 0L
+            int   i = 0L
+            float f = 0L
+        '''
+    }
+
     
//--------------------------------------------------------------------------
 
     void testPlusEqualsOnInt() {

Reply via email to