diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java index 54536b2d5b6..400dedfd589 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java @@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.Map; import static org.jetbrains.asm4.Opcodes.ACC_PRIVATE; +import static org.jetbrains.asm4.Opcodes.ACC_PROTECTED; import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_THIS_FIELD; import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; @@ -405,8 +406,9 @@ public abstract class CodegenContext { @NotNull private MemberDescriptor accessibleDescriptorIfNeeded(CallableMemberDescriptor descriptor, boolean fromOutsideContext) { - int flag = getAccessFlags(descriptor); - if ((flag & ACC_PRIVATE) == 0) { + CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor); + int flag = getAccessFlags(unwrappedDescriptor); + if ((flag & ACC_PRIVATE) == 0 && (flag & ACC_PROTECTED) == 0) { return descriptor; } @@ -438,7 +440,24 @@ public abstract class CodegenContext { } } - return (MemberDescriptor) (descriptorContext != null ? descriptorContext.getAccessor(descriptor) : descriptor); + if (descriptorContext == null) { + return descriptor; + } + + if ((flag & ACC_PROTECTED) != 0) { + PackageFragmentDescriptor unwrappedDescriptorPackage = + DescriptorUtils.getParentOfType(unwrappedDescriptor, PackageFragmentDescriptor.class, false); + PackageFragmentDescriptor contextDescriptorPackage = + DescriptorUtils.getParentOfType(descriptorContext.getContextDescriptor(), PackageFragmentDescriptor.class, false); + + boolean inSamePackage = contextDescriptorPackage != null && unwrappedDescriptorPackage != null && + unwrappedDescriptorPackage.getFqName().equals(contextDescriptorPackage.getFqName()); + if (inSamePackage) { + return descriptor; + } + } + + return (MemberDescriptor) descriptorContext.getAccessor(descriptor); } private void addChild(@NotNull CodegenContext child) { diff --git a/compiler/testData/codegen/boxMultiFile/accessorForProtected/1.kt b/compiler/testData/codegen/boxMultiFile/accessorForProtected/1.kt new file mode 100644 index 00000000000..e5846cdf592 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/accessorForProtected/1.kt @@ -0,0 +1,4 @@ +import b.B +import a.BSamePackage + +fun box() = if (B().test() == BSamePackage().test()) "OK" else "fail" diff --git a/compiler/testData/codegen/boxMultiFile/accessorForProtected/2.kt b/compiler/testData/codegen/boxMultiFile/accessorForProtected/2.kt new file mode 100644 index 00000000000..859cbbed3a7 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/accessorForProtected/2.kt @@ -0,0 +1,14 @@ +package a + +open class A { + protected fun protectedFun(): String = "OK" +} + +class BSamePackage: A() { + fun test(): String { + val a = { + protectedFun() + } + return a() + } +} diff --git a/compiler/testData/codegen/boxMultiFile/accessorForProtected/3.kt b/compiler/testData/codegen/boxMultiFile/accessorForProtected/3.kt new file mode 100644 index 00000000000..60ab0f257ee --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/accessorForProtected/3.kt @@ -0,0 +1,12 @@ +package b + +import a.A + +class B: A() { + fun test(): String { + val a = { + protectedFun() + } + return a() + } +} diff --git a/compiler/testData/codegen/bytecodeText/accessorForProtected.kt b/compiler/testData/codegen/bytecodeText/accessorForProtected.kt new file mode 100644 index 00000000000..eb65d14cacd --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/accessorForProtected.kt @@ -0,0 +1,16 @@ +package a + +open class A { + protected fun protectedFun(): String = "OK" +} + +class BSamePackage: A() { + fun test(): String { + val a = { + protectedFun() + } + return a() + } +} + +// 0 INVOKESTATIC a/BSamePackage.protectedFun diff --git a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java index 224ee62fbb7..47aa95ba354 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java @@ -33,6 +33,11 @@ import org.jetbrains.jet.codegen.AbstractBytecodeTextTest; @TestMetadata("compiler/testData/codegen/bytecodeText") @InnerTestClasses({BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class}) public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { + @TestMetadata("accessorForProtected.kt") + public void testAccessorForProtected() throws Exception { + doTest("compiler/testData/codegen/bytecodeText/accessorForProtected.kt"); + } + public void testAllFilesPresentInBytecodeText() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/bytecodeText"), Pattern.compile("^(.+)\\.kt$"), true); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java index c70b3cbad7a..595e74e5ad0 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java @@ -32,6 +32,11 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest; @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/boxMultiFile") public class BlackBoxMultiFileCodegenTestGenerated extends AbstractBlackBoxCodegenTest { + @TestMetadata("accessorForProtected") + public void testAccessorForProtected() throws Exception { + doTestMultiFile("compiler/testData/codegen/boxMultiFile/accessorForProtected"); + } + public void testAllFilesPresentInBoxMultiFile() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/boxMultiFile"), Pattern.compile("^([^\\.]+)$"), false); }