Skip to content

Commit a422d31

Browse files
committed
Fixed Primitive classes literals, fixed short, byte and char cast to int.
1 parent 971f1f3 commit a422d31

File tree

7 files changed

+281
-4
lines changed

7 files changed

+281
-4
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ buildscript {
1818
}
1919

2020
group 'com.github.jonathanxd'
21-
version '3.0.3-hotfix2'
21+
version '3.0.3-hotfix3'
2222

2323
apply from: project(":CodeAPI").file("gradle/common.gradle")
2424

src/main/kotlin/com/github/jonathanxd/codeapi/bytecode/util/CodeTypeUtil.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,23 @@ object CodeTypeUtil {
227227
var opcode = -1
228228

229229
if (!from.isArray && !to.isArray && from.isPrimitive && to.isPrimitive) {
230-
val fromTypeChar = Character.toUpperCase(from.canonicalName[0])
230+
var fromTypeChar = Character.toUpperCase(from.canonicalName[0])
231231
val toTypeChar = Character.toUpperCase(to.canonicalName[0])
232232

233+
// Fixes Short, Byte & Char conversion to int
234+
if(fromTypeChar == 'S' || fromTypeChar == 'B' || fromTypeChar == 'C') {
235+
if(toTypeChar == 'I')
236+
return
237+
else
238+
fromTypeChar = 'I'
239+
}
240+
233241
opcode = this.getOpcode(fromTypeChar, toTypeChar)
234242

235243
if (opcode == -1) {
244+
if(this.getOpcode(fromTypeChar, 'I') == -1 || this.getOpcode('I', toTypeChar) == -1) {
245+
throw IllegalArgumentException("Can't cast from '$from' to '$to'.")
246+
}
236247
CodeTypeUtil.convertToPrimitive(from, Types.INT, mv)
237248
CodeTypeUtil.convertToPrimitive(Types.INT, to, mv)
238249
return

src/main/kotlin/com/github/jonathanxd/codeapi/bytecode/util/LiteralUtil.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,16 @@ object LiteralUtil {
8686

8787
} else if (num.type.`is`(Types.CODE_TYPE)) {
8888

89-
val type = Type.getType((num.value as CodeType).javaSpecName)
89+
val type = num.value as CodeType
9090

91-
mv.visitLdcInsn(type)
91+
if(type.isPrimitive) {
92+
val wrapperTypeSpec = CodeTypeUtil.codeTypeToBinaryName(type.wrapperType ?: throw IllegalArgumentException("Primitive type '$type' has no wrapper version."))
93+
val classType = CodeTypeUtil.toTypeDesc(Types.CLASS)
94+
95+
mv.visitFieldInsn(Opcodes.GETSTATIC, wrapperTypeSpec, "TYPE", classType)
96+
} else {
97+
mv.visitLdcInsn(type)
98+
}
9299
} else {
93100
throw IllegalArgumentException("Cannot handle literal: $num")
94101
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* CodeAPI-BytecodeWriter - Framework to generate Java code and Bytecode code. <https://github.com/JonathanxD/CodeAPI-BytecodeWriter>
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 TheRealBuggy/JonathanxD (https://github.com/JonathanxD/ & https://github.com/TheRealBuggy/) <[email protected]>
7+
* Copyright (c) contributors
8+
*
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
package com.github.jonathanxd.codeapi.test.asm;
29+
30+
import com.github.jonathanxd.codeapi.CodeAPI;
31+
import com.github.jonathanxd.codeapi.CodeSource;
32+
import com.github.jonathanxd.codeapi.Types;
33+
import com.github.jonathanxd.codeapi.base.TypeDeclaration;
34+
import com.github.jonathanxd.codeapi.bytecode.BytecodeClass;
35+
import com.github.jonathanxd.codeapi.bytecode.classloader.CodeClassLoader;
36+
import com.github.jonathanxd.codeapi.bytecode.gen.BytecodeGenerator;
37+
import com.github.jonathanxd.codeapi.common.CodeParameter;
38+
import com.github.jonathanxd.codeapi.helper.Predefined;
39+
40+
import org.junit.Test;
41+
42+
import java.util.EnumSet;
43+
44+
import static com.github.jonathanxd.codeapi.CodeAPI.parameter;
45+
import static com.github.jonathanxd.codeapi.CodeAPI.sourceOfParts;
46+
import static com.github.jonathanxd.codeapi.Types.VOID;
47+
import static com.github.jonathanxd.codeapi.common.CodeModifier.PUBLIC;
48+
import static com.github.jonathanxd.codeapi.factory.ClassFactory.aClass;
49+
import static com.github.jonathanxd.codeapi.factory.MethodFactory.method;
50+
import static com.github.jonathanxd.codeapi.factory.VariableFactory.variable;
51+
import static com.github.jonathanxd.codeapi.literal.Literals.STRING;
52+
53+
public class CastBugTest {
54+
55+
56+
@Test
57+
public void castBugTest() throws Throwable {
58+
CodeSource source = sourceOfParts(
59+
method(EnumSet.of(PUBLIC), "test", VOID, new CodeParameter[]{
60+
parameter(Short.TYPE, "s"),
61+
},
62+
sourceOfParts(
63+
Predefined.invokePrintln(CodeAPI.cast(Short.TYPE, Integer.TYPE, CodeAPI.accessLocalVariable(Short.TYPE, "s")))
64+
)
65+
)
66+
);
67+
68+
TypeDeclaration decl = aClass(EnumSet.of(PUBLIC), "com.MyClass", source);
69+
70+
BytecodeGenerator bytecodeGenerator = new BytecodeGenerator();
71+
72+
BytecodeClass[] gen = bytecodeGenerator.gen(decl);
73+
74+
ResultSaver.save(this.getClass(), gen);
75+
76+
CodeClassLoader codeClassLoader = new CodeClassLoader();
77+
78+
Class<?> define = codeClassLoader.define(gen);
79+
80+
define.getDeclaredMethod("test", Short.TYPE).invoke(define.newInstance(), (short) 55);
81+
82+
83+
}
84+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* CodeAPI-BytecodeWriter - Framework to generate Java code and Bytecode code. <https://github.com/JonathanxD/CodeAPI-BytecodeWriter>
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 TheRealBuggy/JonathanxD (https://github.com/JonathanxD/ & https://github.com/TheRealBuggy/) <[email protected]>
7+
* Copyright (c) contributors
8+
*
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
package com.github.jonathanxd.codeapi.test.asm;
29+
30+
import com.github.jonathanxd.codeapi.CodeSource;
31+
import com.github.jonathanxd.codeapi.base.TypeDeclaration;
32+
import com.github.jonathanxd.codeapi.bytecode.BytecodeClass;
33+
import com.github.jonathanxd.codeapi.bytecode.classloader.CodeClassLoader;
34+
import com.github.jonathanxd.codeapi.bytecode.gen.BytecodeGenerator;
35+
import com.github.jonathanxd.codeapi.common.CodeParameter;
36+
import com.github.jonathanxd.codeapi.helper.Predefined;
37+
import com.github.jonathanxd.codeapi.literal.Literals;
38+
39+
import org.junit.Test;
40+
41+
import java.util.EnumSet;
42+
43+
import static com.github.jonathanxd.codeapi.CodeAPI.sourceOfParts;
44+
import static com.github.jonathanxd.codeapi.Types.VOID;
45+
import static com.github.jonathanxd.codeapi.common.CodeModifier.PUBLIC;
46+
import static com.github.jonathanxd.codeapi.factory.ClassFactory.aClass;
47+
import static com.github.jonathanxd.codeapi.factory.MethodFactory.method;
48+
49+
public class TypeBugTest {
50+
51+
52+
@Test
53+
public void typeBugTest() throws Throwable {
54+
CodeSource source = sourceOfParts(
55+
method(EnumSet.of(PUBLIC), "test", VOID, new CodeParameter[]{},
56+
sourceOfParts(
57+
Predefined.invokePrintln(Literals.CLASS(Integer.TYPE))
58+
)
59+
)
60+
);
61+
62+
TypeDeclaration decl = aClass(EnumSet.of(PUBLIC), "com.MyClass", source);
63+
64+
BytecodeGenerator bytecodeGenerator = new BytecodeGenerator();
65+
66+
BytecodeClass[] gen = bytecodeGenerator.gen(decl);
67+
68+
ResultSaver.save(this.getClass(), gen);
69+
70+
CodeClassLoader codeClassLoader = new CodeClassLoader();
71+
72+
Class<?> define = codeClassLoader.define(gen);
73+
74+
define.getDeclaredMethod("test").invoke(define.newInstance());
75+
76+
77+
}
78+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
md5: 9b20acc784c06e9a126c1f05a261f5d9
2+
3+
version: Java 8 (52)
4+
access: ACC_PUBLIC (33)
5+
6+
source: MyClass.cai
7+
8+
public class com.MyClass extends java.lang.Object {
9+
10+
!access: ACC_PUBLIC (1)
11+
public void test(short) {
12+
desc: (S)V
13+
maxStack: 4, maxLocals: 2
14+
Label_0:
15+
getstatic java.lang.System.out (type: java.io.PrintStream)
16+
new java.lang.Integer
17+
dup
18+
iload 1
19+
invokespecial java.lang.Integer.<init>(int)void (ownerIsInterface: false)
20+
checkcast java.lang.Object
21+
invokevirtual java.io.PrintStream.println(java.lang.Object)void (ownerIsInterface: false)
22+
return
23+
Label_1:
24+
LocalVariables {
25+
index: 1, name: s, start: Label_0, end: Label_1, type: short, signature: null
26+
index: 0, name: this, start: Label_0, end: Label_1, type: com.MyClass, signature: null
27+
}
28+
}
29+
30+
!access: ACC_PUBLIC (1)
31+
public void <init>() {
32+
desc: ()V
33+
maxStack: 1, maxLocals: 1
34+
Label_0:
35+
aload 0
36+
invokespecial java.lang.Object.<init>()void (ownerIsInterface: false)
37+
return
38+
Label_1:
39+
LocalVariables {
40+
index: 0, name: this, start: Label_0, end: Label_1, type: com.MyClass, signature: null
41+
}
42+
}
43+
44+
!access: PACKAGE_PRIVATE, ACC_STATIC (8)
45+
static void <clinit>() {
46+
desc: ()V
47+
maxStack: 0, maxLocals: 0
48+
return
49+
}
50+
51+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
md5: 787ca4156ea1a63b75ef08881ab8ecc7
2+
3+
version: Java 8 (52)
4+
access: ACC_PUBLIC (33)
5+
6+
source: MyClass.cai
7+
8+
public class com.MyClass extends java.lang.Object {
9+
10+
!access: ACC_PUBLIC (1)
11+
public void test() {
12+
desc: ()V
13+
maxStack: 2, maxLocals: 1
14+
Label_0:
15+
getstatic java.lang.System.out (type: java.io.PrintStream)
16+
getstatic java.lang.Integer.TYPE (type: java.lang.Class)
17+
invokevirtual java.io.PrintStream.println(java.lang.Object)void (ownerIsInterface: false)
18+
return
19+
Label_1:
20+
LocalVariables {
21+
index: 0, name: this, start: Label_0, end: Label_1, type: com.MyClass, signature: null
22+
}
23+
}
24+
25+
!access: ACC_PUBLIC (1)
26+
public void <init>() {
27+
desc: ()V
28+
maxStack: 1, maxLocals: 1
29+
Label_0:
30+
aload 0
31+
invokespecial java.lang.Object.<init>()void (ownerIsInterface: false)
32+
return
33+
Label_1:
34+
LocalVariables {
35+
index: 0, name: this, start: Label_0, end: Label_1, type: com.MyClass, signature: null
36+
}
37+
}
38+
39+
!access: PACKAGE_PRIVATE, ACC_STATIC (8)
40+
static void <clinit>() {
41+
desc: ()V
42+
maxStack: 0, maxLocals: 0
43+
return
44+
}
45+
46+
}

0 commit comments

Comments
 (0)