JVM IR: Write ACC_DEPRECATED flags

This commit is contained in:
Steven Schäfer
2019-08-08 12:14:11 +02:00
committed by Alexander Udalov
parent a90ac2438d
commit fd2ad89799
23 changed files with 56 additions and 53 deletions
@@ -1056,13 +1056,6 @@ open class WrappedFieldDescriptor(
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
}
fun wrappedSimpleFunctionDescriptorBasedOn(descriptor: SimpleFunctionDescriptor) =
if (descriptor is DescriptorWithContainerSource)
// TODO: Do we ever need annotations and source for these?
WrappedFunctionDescriptorWithContainerSource(descriptor.containerSource)
else
WrappedSimpleFunctionDescriptor(descriptor.annotations, descriptor.source)
private fun getContainingDeclaration(declaration: IrDeclarationWithName): DeclarationDescriptor {
val parent = declaration.parent
return if (parent is IrClass && parent.origin == IrDeclarationOrigin.FILE_CLASS && parent.parent is IrExternalPackageFragment) {
@@ -6,13 +6,9 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.descriptors.wrappedSimpleFunctionDescriptorBasedOn
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
@@ -31,6 +27,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
// TODO: fix expect/actual default parameters
@@ -484,7 +482,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(
private fun buildFunctionDeclaration(irFunction: IrFunction, origin: IrDeclarationOrigin): IrFunction {
when (irFunction) {
is IrConstructor -> {
val descriptor = WrappedClassConstructorDescriptor(irFunction.descriptor.annotations, irFunction.descriptor.source)
val descriptor = WrappedClassConstructorDescriptor()
return IrConstructorImpl(
irFunction.startOffset,
irFunction.endOffset,
@@ -502,7 +500,9 @@ private fun buildFunctionDeclaration(irFunction: IrFunction, origin: IrDeclarati
}
}
is IrSimpleFunction -> {
val descriptor = wrappedSimpleFunctionDescriptorBasedOn(irFunction.descriptor as SimpleFunctionDescriptor)
val descriptor = irFunction.descriptor.safeAs<DescriptorWithContainerSource>()?.let {
WrappedFunctionDescriptorWithContainerSource(it.containerSource)
} ?: WrappedSimpleFunctionDescriptor()
val name = Name.identifier("${irFunction.name}\$default")
return IrFunctionImpl(
@@ -11,9 +11,9 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDesc
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
@@ -74,17 +74,16 @@ class PropertiesLowering(
private fun createSyntheticMethodForAnnotations(declaration: IrProperty, origin: IrDeclarationOrigin, name: String): IrFunctionImpl {
val descriptor = WrappedSimpleFunctionDescriptor(declaration.descriptor.annotations)
val symbol = IrSimpleFunctionSymbolImpl(descriptor)
// TODO: ACC_DEPRECATED
return IrFunctionImpl(
-1, -1, origin, symbol, Name.identifier(name),
Visibilities.PUBLIC, Modality.OPEN, context.irBuiltIns.unitType,
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, symbol, Name.identifier(name),
declaration.visibility, Modality.OPEN, context.irBuiltIns.unitType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false
).apply {
descriptor.bind(this)
extensionReceiverParameter = declaration.getter?.extensionReceiverParameter?.copyTo(this)
body = IrBlockBodyImpl(-1, -1)
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
annotations.addAll(declaration.annotations)
metadata = declaration.metadata
@@ -360,7 +360,7 @@ open class ClassCodegen protected constructor(
}
private val IrClass.flags: Int
get() = origin.flags or getVisibilityAccessFlagForClass() or when {
get() = origin.flags or getVisibilityAccessFlagForClass() or deprecationFlags or when {
isAnnotationClass -> Opcodes.ACC_ANNOTATION or Opcodes.ACC_INTERFACE or Opcodes.ACC_ABSTRACT
isInterface -> Opcodes.ACC_INTERFACE or Opcodes.ACC_ABSTRACT
isEnumClass -> Opcodes.ACC_ENUM or Opcodes.ACC_SUPER or modality.flags
@@ -368,7 +368,7 @@ private val IrClass.flags: Int
}
private val IrField.flags: Int
get() = origin.flags or visibility.flags or
get() = origin.flags or visibility.flags or (correspondingPropertySymbol?.owner?.deprecationFlags ?: 0) or
(if (isFinal) Opcodes.ACC_FINAL else 0) or
(if (isStatic) Opcodes.ACC_STATIC else 0) or
(if (hasAnnotation(VOLATILE_ANNOTATION_FQ_NAME)) Opcodes.ACC_VOLATILE else 0) or
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.OwnerKind
@@ -51,17 +50,26 @@ open class FunctionCodegen(
var methodVisitor = createMethod(flags, signature)
val hasSyntheticFlag = flags.and(Opcodes.ACC_SYNTHETIC) != 0
generateParameterNames(irFunction, methodVisitor, signature, state, hasSyntheticFlag)
if (state.generateParametersMetadata && !hasSyntheticFlag) {
generateParameterNames(irFunction, methodVisitor, signature, state)
}
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
AnnotationCodegen(classCodegen, context, methodVisitor::visitAnnotation).genAnnotations(
irFunction,
signature.asmMethod.returnType
)
}
// FIXME: The following test is a workaround for a bug in anonymous object regeneration.
// We currently need to avoid parameter annotations on the (synthetic) constructors of inlined anonymous objects,
// since otherwise anonymous object regeneration can fail with an ArrayIndexOutOfBounds exception if the number
// or arguments to the constructor changes.
if (!hasSyntheticFlag ||
irFunction.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS ||
//TODO: investigate this case: annotation here is generated twice in lowered function and in interface method overload
irFunction.origin == JvmLoweredDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
) {
AnnotationCodegen(classCodegen, context, methodVisitor::visitAnnotation).genAnnotations(
irFunction,
signature.asmMethod.returnType
)
generateParameterAnnotations(irFunction, methodVisitor, signature, classCodegen, context)
}
@@ -101,7 +109,7 @@ open class FunctionCodegen(
val visibility = AsmUtil.getVisibilityAccessFlag(irFunction.visibility) ?: error("Unmapped visibility ${irFunction.visibility}")
val staticFlag = if (isStatic) Opcodes.ACC_STATIC else 0
val varargFlag = if (irFunction.valueParameters.any { it.varargElementType != null }) Opcodes.ACC_VARARGS else 0
val deprecation = if (irFunction.hasAnnotation(FQ_NAMES.deprecated)) Opcodes.ACC_DEPRECATED else 0
val deprecation = irFunction.deprecationFlags
val bridgeFlag = if (
irFunction.origin == IrDeclarationOrigin.BRIDGE ||
irFunction.origin == IrDeclarationOrigin.BRIDGE_SPECIAL
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.lower.allOverridden
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.LABELED_THIS_PARAMETER
@@ -24,12 +25,14 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -46,7 +49,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
class IrFrameMap : FrameMapBase<IrSymbol>() {
private val typeMap = mutableMapOf<IrSymbol,Type>()
private val typeMap = mutableMapOf<IrSymbol, Type>()
override fun enter(descriptor: IrSymbol, type: Type): Int {
typeMap[descriptor] = type
@@ -175,7 +178,8 @@ private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?):
// return ACC_PUBLIC
// }
if (this is IrClass && Visibilities.isPrivate(visibility) &&
parent.safeAs<IrClass>()?.isInterface ?: false) { // TODO: non-intrinsic
parent.safeAs<IrClass>()?.isInterface ?: false
) { // TODO: non-intrinsic
return Opcodes.ACC_PUBLIC
}
@@ -448,13 +452,8 @@ fun generateParameterNames(
irFunction: IrFunction,
mv: MethodVisitor,
jvmSignature: JvmMethodSignature,
state: GenerationState,
isSynthetic: Boolean
state: GenerationState
) {
if (!state.generateParametersMetadata || isSynthetic) {
return
}
val iterator = irFunction.valueParameters.iterator()
val kotlinParameterTypes = jvmSignature.valueParameters
var isEnumName = true
@@ -545,3 +544,24 @@ fun getLabeledThisName(callableName: String, prefix: String, defaultName: String
defaultName
} else prefix + mangleNameIfNeeded(callableName)
}
val IrAnnotationContainer.deprecationFlags: Int
get() {
val annotation = annotations.findAnnotation(FQ_NAMES.deprecated) ?: return 0
val isHidden = (annotation.getValueArgument(2) as? IrGetEnumValue)?.symbol?.owner
?.name?.asString() == DeprecationLevel.HIDDEN.name
return Opcodes.ACC_DEPRECATED or if (isHidden) Opcodes.ACC_SYNTHETIC else 0
}
// We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods
// moved to DefaultImpls, origin is changed to DEFAULT_IMPLS
// TODO: Fix origin somehow
val IrFunction.isSyntheticMethodForProperty: Boolean
get() = name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)
val IrFunction.deprecationFlags: Int
get() {
val originFlags = if (isSyntheticMethodForProperty) Opcodes.ACC_DEPRECATED else 0
val propertyFlags = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.deprecationFlags ?: 0
return originFlags or propertyFlags or (this as IrAnnotationContainer).deprecationFlags
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
@Deprecated("") class MyClass() {
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass {
@Deprecated("") companion object {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
@Deprecated("") enum class MyEnum {
FIRST
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("") public class MyInnerClass() {}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
@Deprecated("") public interface MyTrait {
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("") val test = ""
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("") var test = ""
}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("hidden", level = DeprecationLevel.HIDDEN)
fun test() {}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("hidden", level = DeprecationLevel.HIDDEN)
var test: Int
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("hidden", level = DeprecationLevel.HIDDEN)
var test: Int
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: compatibility
// IGNORE_BACKEND: JVM_IR
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND: JVM_IR
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
@Deprecated("") public val test: Int = 0
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
@Deprecated("") val test: Int = 0
// TESTED_OBJECT_KIND: property
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class Foo {
annotation class Anno
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
open class Foo {
annotation class Anno
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
class Foo {
annotation class Anno