Fixed narrowing cast from 'int' to 'Byte' / 'Short'

master
Dmitry Cherniachenko 8 years ago committed by Egor.Ushakov
parent 5db9ad29c8
commit aa78b7df28
  1. 17
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  2. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java
  3. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java
  4. 2
      src/org/jetbrains/java/decompiler/struct/gen/VarType.java
  5. BIN
      testData/classes/pkg/TestPrimitives.class
  6. 601
      testData/results/TestPrimitives.dec
  7. 69
      testData/src/pkg/TestPrimitives.java

@ -877,10 +877,20 @@ public class ExprProcessor implements CodeConstants {
castAlways || castAlways ||
(!leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT)) || (!leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT)) ||
(castNull && rightType.type == CodeConstants.TYPE_NULL && !UNDEFINED_TYPE_STRING.equals(getTypeName(leftType))) || (castNull && rightType.type == CodeConstants.TYPE_NULL && !UNDEFINED_TYPE_STRING.equals(getTypeName(leftType))) ||
(castNarrowing && isIntConstant(exprent) && VarType.VARTYPE_INT.isStrictSuperset(leftType)); (castNarrowing && isIntConstant(exprent) && isNarrowedIntType(leftType));
boolean quote = cast && exprent.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST); boolean quote = cast && exprent.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST);
// cast instead to 'byte' / 'short' when int constant is used as a value for 'Byte' / 'Short'
if (castNarrowing && exprent.type == Exprent.EXPRENT_CONST) {
if (leftType.equals(VarType.VARTYPE_BYTE_OBJ)) {
leftType = VarType.VARTYPE_BYTE;
}
else if (leftType.equals(VarType.VARTYPE_SHORT_OBJ)) {
leftType = VarType.VARTYPE_SHORT;
}
}
if (cast) buffer.append('(').append(getCastTypeName(leftType)).append(')'); if (cast) buffer.append('(').append(getCastTypeName(leftType)).append(')');
if (quote) buffer.append('('); if (quote) buffer.append('(');
@ -910,4 +920,9 @@ public class ExprProcessor implements CodeConstants {
return false; return false;
} }
private static boolean isNarrowedIntType(VarType type) {
return VarType.VARTYPE_INT.isStrictSuperset(type) ||
type.equals(VarType.VARTYPE_BYTE_OBJ) || type.equals(VarType.VARTYPE_SHORT_OBJ);
}
} }

@ -360,11 +360,7 @@ public class InvocationExprent extends Exprent {
TextBuffer buff = new TextBuffer(); TextBuffer buff = new TextBuffer();
boolean ambiguous = setAmbiguousParameters.get(i); boolean ambiguous = setAmbiguousParameters.get(i);
Exprent param = lstParameters.get(i); Exprent param = unboxIfNeeded(lstParameters.get(i));
// "unbox" invocation parameters, e.g. 'byteSet.add((byte)123)' or 'new ShortContainer((short)813)'
if (param.type == Exprent.EXPRENT_INVOCATION && ((InvocationExprent)param).isBoxingCall()) {
param = ((InvocationExprent)param).lstParameters.get(0);
}
// 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter
ExprProcessor.getCastedExprent(param, descriptor.params[i], buff, indent, true, ambiguous, true, tracer); ExprProcessor.getCastedExprent(param, descriptor.params[i], buff, indent, true, ambiguous, true, tracer);
@ -385,6 +381,14 @@ public class InvocationExprent extends Exprent {
return buf; return buf;
} }
public static Exprent unboxIfNeeded(Exprent param) {
// "unbox" invocation parameters, e.g. 'byteSet.add((byte)123)' or 'new ShortContainer((short)813)'
if (param.type == Exprent.EXPRENT_INVOCATION && ((InvocationExprent)param).isBoxingCall()) {
param = ((InvocationExprent)param).lstParameters.get(0);
}
return param;
}
private boolean isVarArgCall() { private boolean isVarArgCall() {
StructClass cl = DecompilerContext.getStructContext().getClass(classname); StructClass cl = DecompilerContext.getStructContext().getClass(classname);
if (cl != null) { if (cl != null) {

@ -326,7 +326,7 @@ public class NewExprent extends Exprent {
boolean firstParam = true; boolean firstParam = true;
for (int i = start; i < lstParameters.size(); i++) { for (int i = start; i < lstParameters.size(); i++) {
if (sigFields == null || sigFields.get(i) == null) { if (sigFields == null || sigFields.get(i) == null) {
Exprent expr = lstParameters.get(i); Exprent expr = InvocationExprent.unboxIfNeeded(lstParameters.get(i));
VarType leftType = constructor.getDescriptor().params[i]; VarType leftType = constructor.getDescriptor().params[i];
if (i == lstParameters.size() - 1 && expr.getExprType() == VarType.VARTYPE_NULL) { if (i == lstParameters.size() - 1 && expr.getExprType() == VarType.VARTYPE_NULL) {

@ -40,6 +40,8 @@ public class VarType { // TODO: optimize switch
public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object"); public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object");
public static final VarType VARTYPE_INTEGER = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Integer"); public static final VarType VARTYPE_INTEGER = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Integer");
public static final VarType VARTYPE_CHARACTER = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Character"); public static final VarType VARTYPE_CHARACTER = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Character");
public static final VarType VARTYPE_BYTE_OBJ = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Byte");
public static final VarType VARTYPE_SHORT_OBJ = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Short");
public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID); public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID);
public final int type; public final int type;

@ -10,87 +10,133 @@ public class TestPrimitives {
this.printFloat(1.23F);// 11 this.printFloat(1.23F);// 11
this.printDouble(1.23D);// 12 this.printDouble(1.23D);// 12
this.printChar('Z');// 13 this.printChar('Z');// 13
this.printIntBoxed(40000);// 15 this.printBooleanBoxed(true);// 15
String.format("%b, %d, %d, %d, %c, %d", true, 1, 213, 40000, 'c', 42L);// 17 this.printByteBoxed((byte)123);// 16
System.out.println(String.format("%b, %d, %d, %d", this.getBoolean(), this.getByte(), this.getShort(), this.getInt()));// 18 this.printShortBoxed((short)257);// 17
}// 19 this.printIntBoxed(1);// 18
this.printIntBoxed(40000);// 19
this.printLongBoxed(123L);// 20
this.printFloatBoxed(1.23F);// 21
this.printDoubleBoxed(1.23D);// 22
this.printCharBoxed('Z');// 23
System.out.printf("%b, %d, %d, %d, %c, %d", true, 1, 213, 40000, 'c', 42L);// 25
System.out.printf("%b, %d, %d, %d", this.getBoolean(), this.getByte(), this.getShort(), this.getInt());// 26
new TestPrimitives(false, (byte)123, (short)257, 40000, 123L, 3.14F, 1.618D, 'A');// 28
new TestPrimitives('A', 1.618D, 3.14F, 123L, 40000, (short)257, (byte)123, false);// 29
}// 30
private TestPrimitives(boolean bool, byte b, short s, int i, long l, float f, double d, char c) {
System.out.printf("%b, %d, %d, %d, %d, %.2f, %.2f, %c", bool, b, s, i, l, f, d, c);// 33
}// 34
private TestPrimitives(Character c, Double d, Float f, Long l, Integer i, Short s, Byte b, Boolean bool) {
System.out.printf("%b, %d, %d, %d, %d, %.2f, %.2f, %c", bool, b, s, i, l, f, d, c);// 37
}// 38
public void printBoolean(boolean b) { public void printBoolean(boolean b) {
System.out.println(String.format("%b", b));// 22 System.out.printf("%b", b);// 41
}// 23 }// 42
public void printByte(byte b) { public void printByte(byte b) {
System.out.println(String.format("%d", b));// 26 System.out.printf("%d", b);// 45
}// 27 }// 46
public void printShort(short s) { public void printShort(short s) {
System.out.println(String.format("%d", s));// 30 System.out.printf("%d", s);// 49
}// 31 }// 50
public void printInt(int i) { public void printInt(int i) {
System.out.println(String.format("%d", i));// 34 System.out.printf("%d", i);// 53
}// 35 }// 54
public void printLong(long l) { public void printLong(long l) {
System.out.println(String.format("%d", l));// 38 System.out.printf("%d", l);// 57
}// 39 }// 58
public void printFloat(float f) { public void printFloat(float f) {
System.out.println(String.format("%f", f));// 42 System.out.printf("%f", f);// 61
}// 43 }// 62
public void printDouble(double d) { public void printDouble(double d) {
System.out.println(String.format("%f", d));// 46 System.out.printf("%f", d);// 65
}// 47 }// 66
public void printChar(char c) { public void printChar(char c) {
System.out.println(String.format("%c", c));// 50 System.out.printf("%c", c);// 69
}// 51 }// 70
public void printBooleanBoxed(Boolean b) {
System.out.printf("%b", b);// 74
}// 75
public void printByteBoxed(Byte b) {
System.out.printf("%d", b);// 78
}// 79
public void printShortBoxed(Short s) {
System.out.printf("%d", s);// 82
}// 83
public void printIntBoxed(Integer i) { public void printIntBoxed(Integer i) {
System.out.println(String.format("%d", i));// 55 System.out.printf("%d", i);// 86
}// 56 }// 87
public void printLongBoxed(Long l) {
System.out.printf("%d", l);// 90
}// 91
public void printFloatBoxed(Float f) {
System.out.printf("%f", f);// 94
}// 95
public void printDoubleBoxed(Double d) {
System.out.printf("%f", d);// 98
}// 99
public void printCharBoxed(Character c) {
System.out.printf("%c", c);// 102
}// 103
public boolean getBoolean() { public boolean getBoolean() {
return false;// 60 return false;// 107
} }
public byte getByte() { public byte getByte() {
return -128;// 64 return -128;// 111
} }
public short getShort() { public short getShort() {
return -32768;// 68 return -32768;// 115
} }
public int getInt() { public int getInt() {
return 42;// 72 return 42;// 119
} }
public void printNarrowed() { public void printNarrowed() {
this.printByte((byte)this.getInt());// 76 this.printByte((byte)this.getInt());// 123
this.printShort((short)this.getInt());// 77 this.printShort((short)this.getInt());// 124
}// 78 }// 125
public void constructor() { public void constructor() {
new Byte((byte)1);// 81 new Byte((byte)1);// 128
}// 82 }// 129
private boolean compare(char c) { private boolean compare(char c) {
boolean res = c > -1;// 85 boolean res = c > -1;// 132
res = c > 0;// 86 res = c > 0;// 133
res = c > 1;// 87 res = c > 1;// 134
res = c > '\b';// 88 res = c > '\b';// 135
res = c > '\t';// 89 res = c > '\t';// 136
res = c > '\n';// 90 res = c > '\n';// 137
res = c > '\f';// 91 res = c > '\f';// 138
res = c > '\r';// 92 res = c > '\r';// 139
res = c > ' ';// 93 res = c > ' ';// 140
res = c > 'a';// 94 res = c > 'a';// 141
res = c > 'Z';// 95 res = c > 'Z';// 142
res = c > 127;// 96 res = c > 127;// 143
res = c > 255;// 97 res = c > 255;// 144
return res;// 98 return res;// 145
} }
} }
@ -113,191 +159,285 @@ class 'pkg/TestPrimitives' {
2d 11 2d 11
2f 11 2f 11
33 12 33 12
38 12 37 12
3b 13 3b 13
44 13 40 13
45 13 44 14
4b 13 4a 14
4c 13 4e 15
52 13 52 15
55 13 56 16
5b 13 5b 16
5d 13 5f 17
63 13 65 17
65 13 69 18
6b 13 6e 18
6e 13 72 19
72 13 78 19
76 14 7c 20
79 14 81 20
82 14 84 21
85 14 87 21
8c 14 90 21
8f 14 91 21
96 14 97 21
99 14 98 21
a0 14 9e 21
a3 14 a1 21
a7 14 a7 21
aa 14 a9 21
ad 15 af 21
b1 21
b7 21
ba 21
be 21
c2 22
c5 22
ce 22
d1 22
d8 22
db 22
e2 22
e5 22
ec 22
ef 22
f3 22
fb 23
fc 23
fe 23
101 23
103 23
106 23
108 23
10b 23
115 24
11a 24
120 24
125 24
12b 24
130 24
136 24
13b 24
143 25
}
method '<init> (ZBSIJFDC)V' {
4 28
7 28
11 28
18 28
1f 28
27 28
2f 28
37 28
40 28
49 28
4d 28
51 29
}
method '<init> (Ljava/lang/Character;Ljava/lang/Double;Ljava/lang/Float;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Short;Ljava/lang/Byte;Ljava/lang/Boolean;)V' {
4 32
7 32
35 32
39 33
} }
method 'printBoolean (Z)V' { method 'printBoolean (Z)V' {
0 18 0 36
3 18 3 36
c 18 c 36
10 18 10 36
13 18 14 37
16 19
} }
method 'printByte (B)V' { method 'printByte (B)V' {
0 22 0 40
3 22 3 40
c 22 c 40
10 22 10 40
13 22 14 41
16 23
} }
method 'printShort (S)V' { method 'printShort (S)V' {
0 26 0 44
3 26 3 44
c 26 c 44
10 26 10 44
13 26 14 45
16 27
} }
method 'printInt (I)V' { method 'printInt (I)V' {
0 30 0 48
3 30 3 48
c 30 c 48
10 30 10 48
13 30 14 49
16 31
} }
method 'printLong (J)V' { method 'printLong (J)V' {
0 34 0 52
3 34 3 52
c 34 c 52
10 34 10 52
13 34 14 53
16 35
} }
method 'printFloat (F)V' { method 'printFloat (F)V' {
0 38 0 56
3 38 3 56
c 38 c 56
10 38 10 56
13 38 14 57
16 39
} }
method 'printDouble (D)V' { method 'printDouble (D)V' {
0 42 0 60
3 42 3 60
c 42 c 60
10 42 10 60
13 42 14 61
16 43
} }
method 'printChar (C)V' { method 'printChar (C)V' {
0 46 0 64
3 46 3 64
c 46 c 64
10 46 10 64
13 46 14 65
16 47 }
method 'printBooleanBoxed (Ljava/lang/Boolean;)V' {
0 68
3 68
d 68
11 69
}
method 'printByteBoxed (Ljava/lang/Byte;)V' {
0 72
3 72
d 72
11 73
}
method 'printShortBoxed (Ljava/lang/Short;)V' {
0 76
3 76
d 76
11 77
} }
method 'printIntBoxed (Ljava/lang/Integer;)V' { method 'printIntBoxed (Ljava/lang/Integer;)V' {
0 50 0 80
3 50 3 80
d 50 d 80
10 50 11 81
13 51 }
method 'printLongBoxed (Ljava/lang/Long;)V' {
0 84
3 84
d 84
11 85
}
method 'printFloatBoxed (Ljava/lang/Float;)V' {
0 88
3 88
d 88
11 89
}
method 'printDoubleBoxed (Ljava/lang/Double;)V' {
0 92
3 92
d 92
11 93
}
method 'printCharBoxed (Ljava/lang/Character;)V' {
0 96
3 96
d 96
11 97
} }
method 'getBoolean ()Z' { method 'getBoolean ()Z' {
0 54 0 100
1 54 1 100
} }
method 'getByte ()B' { method 'getByte ()B' {
0 58 0 104
2 58 2 104
} }
method 'getShort ()S' { method 'getShort ()S' {
0 62 0 108
3 62 3 108
} }
method 'getInt ()I' { method 'getInt ()I' {
0 66 0 112
2 66 2 112
} }
method 'printNarrowed ()V' { method 'printNarrowed ()V' {
2 70 2 116
5 70 5 116
6 70 6 116
b 71 b 117
e 71 e 117
f 71 f 117
12 72 12 118
} }
method 'constructor ()V' { method 'constructor ()V' {
4 75 4 121
9 76 9 122
} }
method 'compare (C)Z' { method 'compare (C)Z' {
1 79 1 125
2 79 2 125
a 79 a 125
c 80 c 126
14 80 14 126
16 81 16 127
17 81 17 127
1f 81 1f 127
21 82 21 128
23 82 23 128
2b 82 2b 128
2d 83 2d 129
2f 83 2f 129
37 83 37 129
39 84 39 130
3b 84 3b 130
43 84 43 130
45 85 45 131
47 85 47 131
4f 85 4f 131
51 86 51 132
53 86 53 132
5b 86 5b 132
5d 87 5d 133
5f 87 5f 133
67 87 67 133
69 88 69 134
6b 88 6b 134
73 88 73 134
75 89 75 135
77 89 77 135
7f 89 7f 135
81 90 81 136
83 90 83 136
8b 90 8b 136
8d 91 8d 137
90 91 90 137
98 91 98 137
9a 92 9a 138
} }
} }
@ -311,47 +451,78 @@ Lines mapping:
12 <-> 11 12 <-> 11
13 <-> 12 13 <-> 12
15 <-> 13 15 <-> 13
17 <-> 14 16 <-> 14
18 <-> 15 17 <-> 15
19 <-> 16 18 <-> 16
22 <-> 19 19 <-> 17
23 <-> 20 20 <-> 18
21 <-> 19
22 <-> 20
23 <-> 21
25 <-> 22
26 <-> 23 26 <-> 23
27 <-> 24 28 <-> 24
30 <-> 27 29 <-> 25
31 <-> 28 30 <-> 26
34 <-> 31 33 <-> 29
35 <-> 32 34 <-> 30
38 <-> 35 37 <-> 33
39 <-> 36 38 <-> 34
42 <-> 39 41 <-> 37
43 <-> 40 42 <-> 38
46 <-> 43 45 <-> 41
47 <-> 44 46 <-> 42
50 <-> 47 49 <-> 45
51 <-> 48 50 <-> 46
55 <-> 51 53 <-> 49
56 <-> 52 54 <-> 50
60 <-> 55 57 <-> 53
64 <-> 59 58 <-> 54
68 <-> 63 61 <-> 57
72 <-> 67 62 <-> 58
76 <-> 71 65 <-> 61
77 <-> 72 66 <-> 62
69 <-> 65
70 <-> 66
74 <-> 69
75 <-> 70
78 <-> 73 78 <-> 73
81 <-> 76 79 <-> 74
82 <-> 77 82 <-> 77
85 <-> 80 83 <-> 78
86 <-> 81 86 <-> 81
87 <-> 82 87 <-> 82
88 <-> 83
89 <-> 84
90 <-> 85 90 <-> 85
91 <-> 86 91 <-> 86
92 <-> 87
93 <-> 88
94 <-> 89 94 <-> 89
95 <-> 90 95 <-> 90
96 <-> 91
97 <-> 92
98 <-> 93 98 <-> 93
99 <-> 94
102 <-> 97
103 <-> 98
107 <-> 101
111 <-> 105
115 <-> 109
119 <-> 113
123 <-> 117
124 <-> 118
125 <-> 119
128 <-> 122
129 <-> 123
132 <-> 126
133 <-> 127
134 <-> 128
135 <-> 129
136 <-> 130
137 <-> 131
138 <-> 132
139 <-> 133
140 <-> 134
141 <-> 135
142 <-> 136
143 <-> 137
144 <-> 138
145 <-> 139
Not mapped:
32
36

@ -12,47 +12,94 @@ public class TestPrimitives {
printDouble(1.23); printDouble(1.23);
printChar('Z'); printChar('Z');
printBooleanBoxed(true);
printByteBoxed((byte) 123);
printShortBoxed((short) 257);
printIntBoxed(1);
printIntBoxed(40_000); printIntBoxed(40_000);
printLongBoxed(123L);
printFloatBoxed(1.23F);
printDoubleBoxed(1.23);
printCharBoxed('Z');
String.format("%b, %d, %d, %d, %c, %d", true, 1, 213, 40_000, 'c', 42L); System.out.printf("%b, %d, %d, %d, %c, %d", true, 1, 213, 40_000, 'c', 42L);
System.out.println(String.format("%b, %d, %d, %d", getBoolean(), getByte(), getShort(), getInt())); System.out.printf("%b, %d, %d, %d", getBoolean(), getByte(), getShort(), getInt());
new TestPrimitives(false, (byte) 123, (short) 257, 40_000, 123L, 3.14f, 1.618, 'A');
new TestPrimitives('A', 1.618, 3.14f, 123L, 40_000, (short) 257, (byte) 123, false);
}
private TestPrimitives(boolean bool, byte b, short s, int i, long l, float f, double d, char c) {
System.out.printf("%b, %d, %d, %d, %d, %.2f, %.2f, %c", bool, b, s, i, l, f, d, c);
}
private TestPrimitives(Character c, Double d, Float f, Long l, Integer i, Short s, Byte b, Boolean bool) {
System.out.printf("%b, %d, %d, %d, %d, %.2f, %.2f, %c", bool, b, s, i, l, f, d, c);
} }
public void printBoolean(boolean b) { public void printBoolean(boolean b) {
System.out.println(String.format("%b", b)); System.out.printf("%b", b);
} }
public void printByte(byte b) { public void printByte(byte b) {
System.out.println(String.format("%d", b)); System.out.printf("%d", b);
} }
public void printShort(short s) { public void printShort(short s) {
System.out.println(String.format("%d", s)); System.out.printf("%d", s);
} }
public void printInt(int i) { public void printInt(int i) {
System.out.println(String.format("%d", i)); System.out.printf("%d", i);
} }
public void printLong(long l) { public void printLong(long l) {
System.out.println(String.format("%d", l)); System.out.printf("%d", l);
} }
public void printFloat(float f) { public void printFloat(float f) {
System.out.println(String.format("%f", f)); System.out.printf("%f", f);
} }
public void printDouble(double d) { public void printDouble(double d) {
System.out.println(String.format("%f", d)); System.out.printf("%f", d);
} }
public void printChar(char c) { public void printChar(char c) {
System.out.println(String.format("%c", c)); System.out.printf("%c", c);
} }
public void printBooleanBoxed(Boolean b) {
System.out.printf("%b", b);
}
public void printByteBoxed(Byte b) {
System.out.printf("%d", b);
}
public void printShortBoxed(Short s) {
System.out.printf("%d", s);
}
public void printIntBoxed(Integer i) { public void printIntBoxed(Integer i) {
System.out.println(String.format("%d", i)); System.out.printf("%d", i);
}
public void printLongBoxed(Long l) {
System.out.printf("%d", l);
}
public void printFloatBoxed(Float f) {
System.out.printf("%f", f);
}
public void printDoubleBoxed(Double d) {
System.out.printf("%f", d);
}
public void printCharBoxed(Character c) {
System.out.printf("%c", c);
} }

Loading…
Cancel
Save