Fix protected call to super method from lambda

Previously JVM back-end had an assumption that if we're calling a method
declared in the super class from a lambda via a synthetic accessor, that should
be a super call and it must be done with 'invokespecial'. Which is wrong
because a method declared in the super class may be open and overridden in the
subclass, so 'invokevirtual' should be used. Surprisingly, Java SE verifier
allowed both instructions, but on Android only the latter is possible

 #KT-8899 Fixed
 #KT-9052 Fixed
This commit is contained in:
Alexander Udalov
2015-09-07 13:34:15 +03:00
parent 1ccd0f9fc2
commit 3c4b2994a9
15 changed files with 281 additions and 146 deletions
@@ -0,0 +1,49 @@
import test.A
import kotlin.test.assertEquals
open class B : A() {
fun box(): String {
val overriddenMethod: () -> String = {
method()
}
assertEquals("C.method", overriddenMethod())
val superMethod: () -> String = {
super.method()
}
assertEquals("A.method", superMethod())
val overriddenPropertyGetter: () -> String = {
property
}
assertEquals("C.property", overriddenPropertyGetter())
val superPropertyGetter: () -> String = {
super.property
}
assertEquals("A.property", superPropertyGetter())
val overriddenPropertySetter: () -> Unit = {
property = ""
}
overriddenPropertySetter()
val superPropertySetter: () -> Unit = {
super.property = ""
}
superPropertySetter()
assertEquals("C.property;A.property;", state)
return "OK"
}
}
class C : B() {
override fun method() = "C.method"
override var property: String
get() = "C.property"
set(value) { state += "C.property;" }
}
fun box() = C().box()
@@ -0,0 +1,13 @@
package test
abstract class A {
public var state = ""
// These implementations should not be called, because they are overridden in C
protected open fun method(): String = "A.method"
protected open var property: String
get() = "A.property"
set(value) { state += "A.property;" }
}