Vararg in constructor isn't loaded correctly from bytecode

#KT-3251 Fixed
This commit is contained in:
Natalia.Ukhorskaya
2013-01-16 16:13:55 +04:00
parent 6574eca393
commit 37b12bff2e
10 changed files with 88 additions and 47 deletions
@@ -127,6 +127,51 @@ public class AsmUtil {
}
}
public static boolean isAbstract(FunctionDescriptor functionDescriptor, OwnerKind kind) {
return (functionDescriptor.getModality() == Modality.ABSTRACT
|| isInterface(functionDescriptor.getContainingDeclaration()))
&& !isStatic(kind)
&& kind != OwnerKind.TRAIT_IMPL;
}
public static boolean isStatic(OwnerKind kind) {
return kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind;
}
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
boolean isStatic = isStatic(kind);
boolean isAbstract = isAbstract(functionDescriptor, kind);
int flags = getCommonCallableFlags(functionDescriptor);
if (functionDescriptor.getModality() == Modality.FINAL) {
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
if (!(containingDeclaration instanceof ClassDescriptor) ||
((ClassDescriptor) containingDeclaration).getKind() != ClassKind.TRAIT) {
flags |= ACC_FINAL;
}
}
if (isStatic || kind == OwnerKind.TRAIT_IMPL) {
flags |= ACC_STATIC;
}
if (isAbstract) flags |= ACC_ABSTRACT;
return flags;
}
public static int getConstructorAsmFlags(FunctionDescriptor functionDescriptor) {
return getCommonCallableFlags(functionDescriptor);
}
private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) {
int flags = getVisibilityAccessFlag(functionDescriptor);
flags |= getVarargsFlag(functionDescriptor);
flags |= getDeprecatedAccessFlag(functionDescriptor);
return flags;
}
//TODO: move mapping logic to front-end java
public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) {
Integer specialCase = specialCaseVisibility(descriptor);
@@ -175,6 +220,15 @@ public class AsmUtil {
return 0;
}
private static int getVarargsFlag(FunctionDescriptor functionDescriptor) {
if (!functionDescriptor.getValueParameters().isEmpty()
&& functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1)
.getVarargElementType() != null) {
return ACC_VARARGS;
}
return 0;
}
@Nullable
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
@@ -338,50 +338,6 @@ public class FunctionCodegen extends GenerationStateAware {
iv.areturn(asmMethod.getReturnType());
}
private static boolean isAbstract(FunctionDescriptor functionDescriptor, OwnerKind kind) {
return (functionDescriptor.getModality() == Modality.ABSTRACT
|| isInterface(functionDescriptor.getContainingDeclaration())
)
&& !isStatic(kind)
&& kind != OwnerKind.TRAIT_IMPL;
}
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
boolean isStatic = isStatic(kind);
boolean isAbstract = isAbstract(functionDescriptor, kind);
int flags = getVisibilityAccessFlag(functionDescriptor);
if (!functionDescriptor.getValueParameters().isEmpty()
&& functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1)
.getVarargElementType() != null) {
flags |= ACC_VARARGS;
}
if (functionDescriptor.getModality() == Modality.FINAL) {
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
if (!(containingDeclaration instanceof ClassDescriptor) ||
((ClassDescriptor) containingDeclaration).getKind() != ClassKind.TRAIT) {
flags |= ACC_FINAL;
}
}
if (isStatic || kind == OwnerKind.TRAIT_IMPL) {
flags |= ACC_STATIC;
}
if (isAbstract) flags |= ACC_ABSTRACT;
if (KotlinBuiltIns.getInstance().isDeprecated(functionDescriptor)) {
flags |= ACC_DEPRECATED;
}
return flags;
}
private static boolean isStatic(OwnerKind kind) {
return kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind;
}
public static void genJetAnnotations(
@NotNull GenerationState state,
@NotNull FunctionDescriptor functionDescriptor,
@@ -629,7 +629,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final String desc = "()" + componentType.getDescriptor();
MethodVisitor mv = v.newMethod(myClass,
FunctionCodegen.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
AsmUtil.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
function.getName().getName(),
desc,
null, null);
@@ -654,7 +654,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JvmMethodSignature methodSignature = typeMapper.mapSignature(function.getName(), function);
final String methodDesc = methodSignature.getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(myClass, FunctionCodegen.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
MethodVisitor mv = v.newMethod(myClass, AsmUtil.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
function.getName().getName(), methodDesc,
null, null);
@@ -931,7 +931,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JvmMethodSignature constructorMethod = callableMethod.getSignature();
assert constructorDescriptor != null;
int flags = getVisibilityAccessFlag(constructorDescriptor);
int flags = getConstructorAsmFlags(constructorDescriptor);
final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(),
constructorMethod.getGenericsSignature(), null);
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
@@ -0,0 +1,3 @@
class A(vararg s: String) {
}
@@ -0,0 +1,5 @@
fun main(args: Array<String>) {
A()
A("a")
A("a", "b")
}
@@ -0,0 +1,3 @@
package test
class A(vararg a: Int) {}
@@ -0,0 +1,5 @@
package test
internal final class A {
/*primary*/ public constructor A(/*0*/ vararg a : jet.Int /*jet.IntArray*/)
}
@@ -38,6 +38,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
doTest("compiler/testData/compileKotlinAgainstKotlin/ClassObjectMember.A.kt");
}
@TestMetadata("ConstructorVararg.A.kt")
public void testConstructorVararg_A() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/ConstructorVararg.A.kt");
}
@TestMetadata("DefaultConstructor.A.kt")
public void testDefaultConstructor_A() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/DefaultConstructor.A.kt");
@@ -269,6 +269,11 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT
doTest("compiler/testData/loadKotlin/constructor/ConstructorCollectionParameter.kt");
}
@TestMetadata("ConstructorVararg.kt")
public void testConstructorVararg() throws Exception {
doTest("compiler/testData/loadKotlin/constructor/ConstructorVararg.kt");
}
@TestMetadata("ConstructorWithTwoDefArgs.kt")
public void testConstructorWithTwoDefArgs() throws Exception {
doTest("compiler/testData/loadKotlin/constructor/ConstructorWithTwoDefArgs.kt");
@@ -271,6 +271,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
doTestCheckingPrimaryConstructors("compiler/testData/loadKotlin/constructor/ConstructorCollectionParameter.kt");
}
@TestMetadata("ConstructorVararg.kt")
public void testConstructorVararg() throws Exception {
doTestCheckingPrimaryConstructors("compiler/testData/loadKotlin/constructor/ConstructorVararg.kt");
}
@TestMetadata("ConstructorWithTwoDefArgs.kt")
public void testConstructorWithTwoDefArgs() throws Exception {
doTestCheckingPrimaryConstructors("compiler/testData/loadKotlin/constructor/ConstructorWithTwoDefArgs.kt");