From 120c344f11c9cd9349b06ed75bf80d70df9c9a49 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 2 Dec 2014 14:31:46 +0300 Subject: [PATCH] Fix access to private static native functions --- .../AccessorForFunctionDescriptor.java | 5 ++- .../jet/codegen/FunctionCodegen.java | 9 +++--- .../codegen/ImplementationBodyCodegen.java | 6 ++-- .../jet/codegen/PlatformStaticGenerator.kt | 31 ++++++++++++------- .../boxWithStdlib/native/privateStatic.kt | 24 ++++++++++++++ .../platformStatic/privateMethod.kt | 16 ++++++++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 12 +++++++ 7 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/native/privateStatic.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/platformStatic/privateMethod.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java b/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java index f69868cb9b3..10b5e20aec6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java @@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.annotations.AnnotationsPackage; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; @@ -45,7 +46,9 @@ public class AccessorForFunctionDescriptor extends SimpleFunctionDescriptorImpl this.calleeDescriptor = descriptor; initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()), - descriptor instanceof ConstructorDescriptor ? NO_RECEIVER_PARAMETER : descriptor.getDispatchReceiverParameter(), + descriptor instanceof ConstructorDescriptor || AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor) + ? NO_RECEIVER_PARAMETER + : descriptor.getDispatchReceiverParameter(), copyTypeParameters(descriptor), copyValueParameters(descriptor), descriptor.getReturnType(), diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index b23a13a6b08..832704fb449 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -189,10 +189,11 @@ public class FunctionCodegen extends ParentCodegenAware { else if (staticInClassObject) { // native platformStatic foo() in class object should delegate to the static native function moved to the outer class mv.visitCode(); - ClassifierDescriptor outerClassDescriptor = - (ClassifierDescriptor) functionDescriptor.getContainingDeclaration().getContainingDeclaration(); - assert outerClassDescriptor != null : "Class object has no outer class: " + functionDescriptor.getContainingDeclaration(); - generateDelegateToMethodBody(false, mv, asmMethod, typeMapper.mapClass(outerClassDescriptor).getInternalName()); + FunctionDescriptor staticFunctionDescriptor = PlatformStaticGenerator.createStaticFunctionDescriptor(functionDescriptor); + JvmMethodSignature jvmMethodSignature = + typeMapper.mapSignature(getParentCodegen().getContext().accessibleFunctionDescriptor(staticFunctionDescriptor)); + Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration()); + generateDelegateToMethodBody(false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName()); } endVisit(mv, null, origin.getElement()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 0d45a72f249..724301ed5c2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DeclarationResolver; import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.annotations.AnnotationsPackage; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.jet.lang.resolve.calls.model.DefaultValueArgument; @@ -58,7 +59,6 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignat import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetTokens; @@ -982,7 +982,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { reg = 0; } else if (callFromAccessor) { - iv.load(0, OBJECT_TYPE); + if (!AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) { + iv.load(0, OBJECT_TYPE); + } } for (Type argType : callableMethod.getAsmMethod().getArgumentTypes()) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt b/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt index 3b615f60a2e..dfadddae550 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt @@ -29,6 +29,7 @@ import org.jetbrains.jet.codegen.context.MethodContext import org.jetbrains.jet.lang.psi.JetElement import org.jetbrains.jet.backend.common.CodegenUtil import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor +import kotlin.platform.platformStatic class PlatformStaticGenerator( val descriptor: FunctionDescriptor, @@ -37,17 +38,7 @@ class PlatformStaticGenerator( ) : Function2 { override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) { - val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor - val copies = CodegenUtil.copyFunctions( - memberDescriptor, - memberDescriptor, - declarationOrigin.descriptor?.getContainingDeclaration()?.getContainingDeclaration(), - descriptor.getModality(), - descriptor.getVisibility(), - CallableMemberDescriptor.Kind.SYNTHESIZED, - false - ) - val staticFunctionDescriptor = copies[descriptor]!! + val staticFunctionDescriptor = createStaticFunctionDescriptor(descriptor) val jvmMethodSignature = state.getTypeMapper().mapSignature(staticFunctionDescriptor) @@ -87,4 +78,22 @@ class PlatformStaticGenerator( } ) } + + class object { + [platformStatic] + public fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor { + val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor + val copies = CodegenUtil.copyFunctions( + memberDescriptor, + memberDescriptor, + descriptor.getContainingDeclaration()?.getContainingDeclaration(), + descriptor.getModality(), + descriptor.getVisibility(), + CallableMemberDescriptor.Kind.SYNTHESIZED, + false + ) + val staticFunctionDescriptor = copies[descriptor]!! + return staticFunctionDescriptor + } + } } \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/native/privateStatic.kt b/compiler/testData/codegen/boxWithStdlib/native/privateStatic.kt new file mode 100644 index 00000000000..8ec5f1b8c1c --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/native/privateStatic.kt @@ -0,0 +1,24 @@ +import kotlin.jvm.* +import kotlin.platform.* + +class C { + class object { + private platformStatic native fun foo() + } + + fun bar() { + foo() + } +} + +fun box(): String { + try { + C().bar() + return "Link error expected" + } + catch (e: java.lang.UnsatisfiedLinkError) { + if (e.getMessage() != "C.foo()V") return "Fail 1: " + e.getMessage() + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/platformStatic/privateMethod.kt b/compiler/testData/codegen/boxWithStdlib/platformStatic/privateMethod.kt new file mode 100644 index 00000000000..9b0ada16440 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformStatic/privateMethod.kt @@ -0,0 +1,16 @@ +import kotlin.platform.platformStatic + +object A { + + private platformStatic fun a(): String { + return "OK" + } + + object Z { + val p = a() + } +} + +fun box(): String { + return A.Z.p +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index ec3a3e66fa2..11c68befa55 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -1831,6 +1831,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("privateStatic.kt") + public void testPrivateStatic() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/native/privateStatic.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("simpleNative.kt") public void testSimpleNative() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/native/simpleNative.kt"); @@ -1972,6 +1978,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("privateMethod.kt") + public void testPrivateMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/privateMethod.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("propertyAccess.kt") public void testPropertyAccess() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic/propertyAccess.kt");