mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Restrict interface override synthesis to cases where both the overriding class and the interface are Kotlin-defined.
If the interface is Java-defined and it provides a default interface implementation then real class-file default methods are being used and kotlinc won't synthesise anything. If the loaded .class file wasn't made by Kotlin, then we see all the real methods and there is no need to synthesise anything either.
This commit is contained in:
@@ -829,14 +829,18 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun isKotlinDefinedInterface(cls: IrClass?) =
|
||||
cls != null && cls.isInterface && cls.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||
|
||||
private fun needsInterfaceForwarder(f: IrFunction) =
|
||||
// forAllMethodsWithBody means -Xjvm-default=all or all-compatibility, in which case real Java default interfaces are used, and we don't need to do anything.
|
||||
// Otherwise, for a method inheriting a default, we need to create a synthetic method like `int f(int x) { return super.InterfaceWithDefault.f(x); }`, because
|
||||
// kotlinc will generate a public method and Java callers may directly target it.
|
||||
// Otherwise, for a Kotlin-defined method inheriting a Kotlin-defined default, we need to create a synthetic method like
|
||||
// `int f(int x) { return super.InterfaceWithDefault.f(x); }`, because kotlinc will generate a public method and Java callers may directly target it.
|
||||
// (NB. kotlinc's actual implementation strategy is different -- it makes an inner class called InterfaceWithDefault$DefaultImpls and stores the default methods
|
||||
// there to allow default method usage in Java < 8, but this is hopefully niche.
|
||||
!pluginContext.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode).forAllMethodsWithBody &&
|
||||
f.realOverrideTarget.let { it != f && it.parentClassOrNull?.isInterface == true }
|
||||
f.parentClassOrNull?.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB &&
|
||||
f.realOverrideTarget.let { it != f && isKotlinDefinedInterface(it.parentClassOrNull) }
|
||||
|
||||
private fun makeInterfaceForwarder(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) =
|
||||
forceExtractFunction(f, parentId, extractBody = false, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses).also { functionId ->
|
||||
|
||||
Reference in New Issue
Block a user