You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/01/11 18:32:15 UTC
[groovy] 01/01: GROOVY-9336: integer target type for shift RHS in
constant initializer
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-9336
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit b1c65ef23efa7b3039a306d84bea60358004c55b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Jan 11 12:23:47 2020 -0600
GROOVY-9336: integer target type for shift RHS in constant initializer
---
.../apache/groovy/ast/tools/ExpressionUtils.java | 52 +++++++++-------------
src/test/groovy/bugs/Groovy9336.groovy | 42 +++++++++++++++++
2 files changed, 64 insertions(+), 30 deletions(-)
diff --git a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
index 349e469..648a295 100644
--- a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
@@ -33,7 +33,7 @@ import org.codehaus.groovy.runtime.typehandling.NumberMath;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
+import java.util.Arrays;
import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
import static org.codehaus.groovy.syntax.Types.BITWISE_OR;
@@ -48,20 +48,13 @@ import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT;
import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
public class ExpressionUtils {
- private static ArrayList<Integer> handledTypes = new ArrayList<Integer>();
- static {
- handledTypes.add(PLUS);
- handledTypes.add(MINUS);
- handledTypes.add(MULTIPLY);
- handledTypes.add(DIVIDE);
- handledTypes.add(LEFT_SHIFT);
- handledTypes.add(RIGHT_SHIFT);
- handledTypes.add(RIGHT_SHIFT_UNSIGNED);
- handledTypes.add(BITWISE_OR);
- handledTypes.add(BITWISE_AND);
- handledTypes.add(BITWISE_XOR);
- handledTypes.add(POWER);
- }
+
+ // NOTE: values are sorted in ascending order
+ private static final int[] HANDLED_TYPES = {
+ PLUS, MINUS, MULTIPLY, DIVIDE, POWER,
+ LEFT_SHIFT, RIGHT_SHIFT, RIGHT_SHIFT_UNSIGNED,
+ BITWISE_OR, BITWISE_AND, BITWISE_XOR,
+ };
private ExpressionUtils() {
}
@@ -74,22 +67,22 @@ public class ExpressionUtils {
* @param targetType the type of the result
* @return the transformed expression or the original if no transformation was performed
*/
- public static ConstantExpression transformBinaryConstantExpression(BinaryExpression be, ClassNode targetType) {
+ public static ConstantExpression transformBinaryConstantExpression(final BinaryExpression be, final ClassNode targetType) {
ClassNode wrapperType = ClassHelper.getWrapper(targetType);
if (isTypeOrArrayOfType(targetType, ClassHelper.STRING_TYPE, false)) {
if (be.getOperation().getType() == PLUS) {
Expression left = transformInlineConstants(be.getLeftExpression(), targetType);
Expression right = transformInlineConstants(be.getRightExpression(), targetType);
if (left instanceof ConstantExpression && right instanceof ConstantExpression) {
- return configure(be, new ConstantExpression((String) ((ConstantExpression) left).getValue() +
- ((ConstantExpression) right).getValue()));
+ return configure(be, new ConstantExpression((String) ((ConstantExpression) left).getValue() + ((ConstantExpression) right).getValue()));
}
}
} else if (isNumberOrArrayOfNumber(wrapperType, false)) {
int type = be.getOperation().getType();
- if (handledTypes.contains(type)) {
+ if (Arrays.binarySearch(HANDLED_TYPES, type) >= 0) {
+ boolean isShift = (type >= LEFT_SHIFT && type <= RIGHT_SHIFT_UNSIGNED);
Expression leftX = transformInlineConstants(be.getLeftExpression(), targetType);
- Expression rightX = transformInlineConstants(be.getRightExpression(), targetType);
+ Expression rightX = transformInlineConstants(be.getRightExpression(), isShift ? ClassHelper.int_TYPE : targetType);
if (leftX instanceof ConstantExpression && rightX instanceof ConstantExpression) {
Number left = safeNumber((ConstantExpression) leftX);
Number right = safeNumber((ConstantExpression) rightX);
@@ -157,13 +150,13 @@ public class ExpressionUtils {
return null;
}
- private static Number safeNumber(ConstantExpression constX) {
+ private static Number safeNumber(final ConstantExpression constX) {
Object value = constX.getValue();
if (value instanceof Number) return (Number) value;
return null;
}
- private static ConstantExpression configure(Expression origX, ConstantExpression newX) {
+ private static ConstantExpression configure(final Expression origX, final ConstantExpression newX) {
newX.setSourcePosition(origX);
return newX;
}
@@ -176,7 +169,7 @@ public class ExpressionUtils {
* @param recurse true if we can have multi-dimension arrays; should be false for annotation member types
* @return true if the type equals the targetType or array thereof
*/
- public static boolean isTypeOrArrayOfType(ClassNode targetType, ClassNode type, boolean recurse) {
+ public static boolean isTypeOrArrayOfType(final ClassNode targetType, final ClassNode type, final boolean recurse) {
if (targetType == null) return false;
return type.equals(targetType) ||
(targetType.isArray() && recurse
@@ -191,7 +184,7 @@ public class ExpressionUtils {
* @param recurse true if we can have multi-dimension arrays; should be false for annotation member types
* @return true if the type equals the targetType or array thereof
*/
- public static boolean isNumberOrArrayOfNumber(ClassNode targetType, boolean recurse) {
+ public static boolean isNumberOrArrayOfNumber(final ClassNode targetType, final boolean recurse) {
if (targetType == null) return false;
return targetType.isDerivedFrom(ClassHelper.Number_TYPE) ||
(targetType.isArray() && recurse
@@ -271,7 +264,7 @@ public class ExpressionUtils {
* @param attrType the target type
* @return the transformed list or the original if nothing was changed
*/
- public static Expression transformListOfConstants(ListExpression origList, ClassNode attrType) {
+ public static Expression transformListOfConstants(final ListExpression origList, final ClassNode attrType) {
ListExpression newList = new ListExpression();
boolean changed = false;
for (Expression e : origList.getExpressions()) {
@@ -336,11 +329,10 @@ public class ExpressionUtils {
return exp;
}
- private static Expression findConstant(FieldNode fn) {
- if (fn != null && !fn.isEnum() && fn.isStatic() && fn.isFinal()) {
- if (fn.getInitialValueExpression() instanceof ConstantExpression) {
- return fn.getInitialValueExpression();
- }
+ private static Expression findConstant(final FieldNode fn) {
+ if (fn != null && !fn.isEnum() && fn.isStatic() && fn.isFinal()
+ && fn.getInitialValueExpression() instanceof ConstantExpression) {
+ return fn.getInitialValueExpression();
}
return null;
}
diff --git a/src/test/groovy/bugs/Groovy9336.groovy b/src/test/groovy/bugs/Groovy9336.groovy
new file mode 100644
index 0000000..5aa837e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9336.groovy
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9336 {
+
+ @Test
+ void testShiftInStaticFieldInitializer() {
+ assertScript '''
+ class Groovy9336 {
+ // initializer evaluated like (2 as double) << ((16 - 1) as double); need int on RHS
+ public static double N = 2 << 16 - 1
+
+ static main(args) {
+ assert N == 65536.0d
+ }
+ }
+ '''
+ }
+}