Wed, 11 May 2011 13:12:11 +0200
7041730: Regression: compiler accepts invalid cast from int to Byte
Summary: Implementation of cast conversion rules between primitive and boxed types is too liberal
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Wed May 11 13:10:57 2011 +0200 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Wed May 11 13:12:11 2011 +0200 1.3 @@ -955,7 +955,9 @@ 1.4 if (t.isPrimitive() != s.isPrimitive()) 1.5 return allowBoxing && ( 1.6 isConvertible(t, s, warn) 1.7 - || (allowObjectToPrimitiveCast && isConvertible(s, t, warn))); 1.8 + || (allowObjectToPrimitiveCast && 1.9 + s.isPrimitive() && 1.10 + isSubtype(boxedClass(s).type, t))); 1.11 if (warn != warnStack.head) { 1.12 try { 1.13 warnStack = warnStack.prepend(warn);
2.1 --- a/test/tools/javac/types/BoxingConversionTest.java Wed May 11 13:10:57 2011 +0200 2.2 +++ b/test/tools/javac/types/BoxingConversionTest.java Wed May 11 13:12:11 2011 +0200 2.3 @@ -118,7 +118,6 @@ 2.4 static final Result T = Result.OK_BOTH; 2.5 static final Result F = Result.FAIL_BOTH; 2.6 static final Result A = Result.OK_ASSIGN_ONLY; 2.7 - static final Result X = Result.FAIL_BOTH.FAIL_BOTH; 2.8 2.9 Result[][] results1 = { 2.10 //byte, short, int, long, float, double, char, bool, Byte, Short, Integer, Long, Float, Double, Character, Boolean
3.1 --- a/test/tools/javac/types/CastTest.java Wed May 11 13:10:57 2011 +0200 3.2 +++ b/test/tools/javac/types/CastTest.java Wed May 11 13:12:11 2011 +0200 3.3 @@ -42,12 +42,13 @@ 3.4 */ 3.5 public class CastTest extends TypeHarness { 3.6 3.7 - Type[] allTypes; 3.8 + Type[] types_no_boxing; 3.9 + Type[] types_boxing; 3.10 3.11 static final boolean T = true; 3.12 static final boolean F = false; 3.13 3.14 - boolean[][] cast_result = { 3.15 + boolean[][] cast_result_no_boxing = { 3.16 //byte, short, int, long, float, double, char, bool, C, +C, I, T, byte[], short[], int[], long[], float[], double[], char[], bool[], C[], +C[], I[], T[] 3.17 /*byte*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F }, 3.18 /*short*/ { T , T , T , T , T , T , T , F , F, F , F, F, F , F , F , F , F , F , F , F , F , F , F , F }, 3.19 @@ -74,6 +75,25 @@ 3.20 /*I[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , F , T , F , T , T }, 3.21 /*T[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , F , F , F , F , F , F , T , T , T , T }}; 3.22 3.23 + boolean[][] cast_result_boxing = { 3.24 + //byte, short, int, long, float, double, char, bool, Byte, Short, Integer, Long, Float, Double, Character, Boolean, Object 3.25 + /*byte*/ { T , T , T , T , T , T , T , F , T , F , F , F , F , F , F , F , T }, 3.26 + /*short*/ { T , T , T , T , T , T , T , F , F , T , F , F , F , F , F , F , T }, 3.27 + /*int*/ { T , T , T , T , T , T , T , F , F , F , T , F , F , F , F , F , T }, 3.28 + /*long*/ { T , T , T , T , T , T , T , F , F , F , F , T , F , F , F , F , T }, 3.29 + /*float*/ { T , T , T , T , T , T , T , F , F , F , F , F , T , F , F , F , T }, 3.30 + /*double*/ { T , T , T , T , T , T , T , F , F , F , F , F , F , T , F , F , T }, 3.31 + /*char*/ { T , T , T , T , T , T , T , F , F , F , F , F , F , F , T , F , T }, 3.32 + /*bool*/ { F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , T , T }, 3.33 + /*Byte*/ { T , T , T , T , T , T , F , F , T , F , F , F , F , F , F , F , T }, 3.34 + /*Short*/ { F , T , T , T , T , T , F , F , F , T , F , F , F , F , F , F , T }, 3.35 + /*Integer*/ { F , F , T , T , T , T , F , F , F , F , T , F , F , F , F , F , T }, 3.36 + /*Long*/ { F , F , F , T , T , T , F , F , F , F , F , T , F , F , F , F , T }, 3.37 + /*Float*/ { F , F , F , F , T , T , F , F , F , F , F , F , T , F , F , F , T }, 3.38 + /*Double*/ { F , F , F , F , F , T , F , F , F , F , F , F , F , T , F , F , T }, 3.39 + /*Character*/ { F , F , T , T , T , T , T , F , F , F , F , F , F , F , T , F , T }, 3.40 + /*Boolean*/ { F , F , F , F , F , F , F , T , F , F , F , F , F , F , F , T , T }, 3.41 + /*Object*/ { T , T , T , T , T , T , T , T , T , T , T , T , T , T , T , T , T }}; 3.42 CastTest() { 3.43 Type[] primitiveTypes = { 3.44 predef.byteType, 3.45 @@ -85,6 +105,15 @@ 3.46 predef.charType, 3.47 predef.booleanType }; 3.48 3.49 + Type[] boxedTypes = new Type[primitiveTypes.length + 1]; 3.50 + for (int i = 0 ; i < primitiveTypes.length ; i++) { 3.51 + boxedTypes[i] = box(primitiveTypes[i]); 3.52 + } 3.53 + 3.54 + boxedTypes[primitiveTypes.length] = predef.objectType; 3.55 + 3.56 + types_boxing = join(Type.class, primitiveTypes, boxedTypes); 3.57 + 3.58 Type[] referenceTypes = { 3.59 fac.Class(), 3.60 fac.Class(FINAL), 3.61 @@ -97,17 +126,22 @@ 3.62 arrayTypes[idx++] = fac.Array(t); 3.63 } 3.64 3.65 - allTypes = join(Type.class, primitiveTypes, referenceTypes, arrayTypes); 3.66 + types_no_boxing = join(Type.class, primitiveTypes, referenceTypes, arrayTypes); 3.67 } 3.68 3.69 - void test() { 3.70 - for (int i = 0; i < allTypes.length ; i++) { 3.71 - for (int j = 0; j < allTypes.length ; j++) { 3.72 - assertCastable(allTypes[i], allTypes[j], cast_result[i][j]); 3.73 + void test(Type[] all_types, boolean[][] cast_result) { 3.74 + for (int i = 0; i < all_types.length ; i++) { 3.75 + for (int j = 0; j < all_types.length ; j++) { 3.76 + assertCastable(all_types[i], all_types[j], cast_result[i][j]); 3.77 } 3.78 } 3.79 } 3.80 3.81 + void runTests() { 3.82 + test(types_no_boxing, cast_result_no_boxing); 3.83 + test(types_boxing, cast_result_boxing); 3.84 + } 3.85 + 3.86 @SuppressWarnings("unchecked") 3.87 <T> T[] join(Class<T> type, T[]... args) { 3.88 int totalLength = 0; 3.89 @@ -124,6 +158,6 @@ 3.90 } 3.91 3.92 public static void main(String[] args) { 3.93 - new CastTest().test(); 3.94 + new CastTest().runTests(); 3.95 } 3.96 }