JVM IR: Validate corresponding properties
This commit is contained in:
committed by
Alexander Udalov
parent
13f15a702b
commit
9bc8fdcb3c
+16
-8
@@ -76,6 +76,19 @@ class CheckIrElementVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrElement.checkFunction(function: IrFunction) {
|
||||||
|
if (function is IrSimpleFunction && config.checkProperties) {
|
||||||
|
val property = function.correspondingPropertySymbol?.owner
|
||||||
|
if (property != null && property.getter != function && property.setter != function) {
|
||||||
|
reportError(this, "Orphaned property getter/setter ${function.render()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function.dispatchReceiverParameter?.type is IrDynamicType) {
|
||||||
|
reportError(this, "Dispatch receivers with 'dynamic' type are not allowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> visitConst(expression: IrConst<T>) {
|
override fun <T> visitConst(expression: IrConst<T>) {
|
||||||
super.visitConst(expression)
|
super.visitConst(expression)
|
||||||
|
|
||||||
@@ -152,10 +165,8 @@ class CheckIrElementVisitor(
|
|||||||
super.visitCall(expression)
|
super.visitCall(expression)
|
||||||
|
|
||||||
val function = expression.symbol.owner
|
val function = expression.symbol.owner
|
||||||
|
expression.checkFunction(function)
|
||||||
|
|
||||||
if (function.dispatchReceiverParameter?.type is IrDynamicType) {
|
|
||||||
reportError(expression, "Dispatch receivers with 'dynamic' type are not allowed")
|
|
||||||
}
|
|
||||||
// TODO: Why don't we check parameters as well?
|
// TODO: Why don't we check parameters as well?
|
||||||
|
|
||||||
val returnType = expression.symbol.owner.returnType
|
val returnType = expression.symbol.owner.returnType
|
||||||
@@ -267,10 +278,7 @@ class CheckIrElementVisitor(
|
|||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
super.visitFunction(declaration)
|
super.visitFunction(declaration)
|
||||||
|
declaration.checkFunction(declaration)
|
||||||
if (declaration.dispatchReceiverParameter?.type is IrDynamicType) {
|
|
||||||
reportError(declaration, "Dispatch receivers with 'dynamic' type are not allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((i, p) in declaration.valueParameters.withIndex()) {
|
for ((i, p) in declaration.valueParameters.withIndex()) {
|
||||||
if (p.index != i) {
|
if (p.index != i) {
|
||||||
@@ -323,7 +331,7 @@ class CheckIrElementVisitor(
|
|||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference) {
|
override fun visitFunctionReference(expression: IrFunctionReference) {
|
||||||
super.visitFunctionReference(expression)
|
super.visitFunctionReference(expression)
|
||||||
|
expression.checkFunction(expression.symbol.owner)
|
||||||
expression.symbol.ensureBound(expression)
|
expression.symbol.ensureBound(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ data class IrValidatorConfig(
|
|||||||
val abortOnError: Boolean,
|
val abortOnError: Boolean,
|
||||||
val ensureAllNodesAreDifferent: Boolean,
|
val ensureAllNodesAreDifferent: Boolean,
|
||||||
val checkTypes: Boolean = true,
|
val checkTypes: Boolean = true,
|
||||||
val checkDescriptors: Boolean = true
|
val checkDescriptors: Boolean = true,
|
||||||
|
val checkProperties: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
class IrValidator(val context: CommonBackendContext, val config: IrValidatorConfig) : IrElementVisitorVoid {
|
class IrValidator(val context: CommonBackendContext, val config: IrValidatorConfig) : IrElementVisitorVoid {
|
||||||
|
|||||||
+3
-2
@@ -123,12 +123,13 @@ fun <Data, Context> dumpToStdout(
|
|||||||
|
|
||||||
val defaultDumper = makeDumpAction(dumpToStdout(::dumpIrElement) + dumpToFile("ir", ::dumpIrElement))
|
val defaultDumper = makeDumpAction(dumpToStdout(::dumpIrElement) + dumpToFile("ir", ::dumpIrElement))
|
||||||
|
|
||||||
fun <Fragment : IrElement> validationCallback(context: CommonBackendContext, fragment: Fragment) {
|
fun <Fragment : IrElement> validationCallback(context: CommonBackendContext, fragment: Fragment, checkProperties: Boolean = false) {
|
||||||
val validatorConfig = IrValidatorConfig(
|
val validatorConfig = IrValidatorConfig(
|
||||||
abortOnError = true,
|
abortOnError = true,
|
||||||
ensureAllNodesAreDifferent = true,
|
ensureAllNodesAreDifferent = true,
|
||||||
checkTypes = false,
|
checkTypes = false,
|
||||||
checkDescriptors = false
|
checkDescriptors = false,
|
||||||
|
checkProperties = checkProperties,
|
||||||
)
|
)
|
||||||
fragment.accept(IrValidator(context, validatorConfig), null)
|
fragment.accept(IrValidator(context, validatorConfig), null)
|
||||||
fragment.accept(CheckDeclarationParentsVisitor, null)
|
fragment.accept(CheckDeclarationParentsVisitor, null)
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val validateIrBeforeLowering = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
private val validateIrBeforeLowering = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
||||||
{ context, module -> validationCallback(context, module) },
|
{ context, module -> validationCallback(context, module, checkProperties = true) },
|
||||||
name = "ValidateIrBeforeLowering",
|
name = "ValidateIrBeforeLowering",
|
||||||
description = "Validate IR before lowering"
|
description = "Validate IR before lowering"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val validateIrAfterLowering = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
private val validateIrAfterLowering = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
||||||
{ context, module -> validationCallback(context, module) },
|
{ context, module -> validationCallback(context, module, checkProperties = true) },
|
||||||
name = "ValidateIrAfterLowering",
|
name = "ValidateIrAfterLowering",
|
||||||
description = "Validate IR after lowering"
|
description = "Validate IR after lowering"
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -255,6 +255,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
|||||||
currentScope?.scope?.scopeOwnerSymbol ?: irClass.symbol, expression.startOffset, expression.endOffset
|
currentScope?.scope?.scopeOwnerSymbol ?: irClass.symbol, expression.startOffset, expression.endOffset
|
||||||
)
|
)
|
||||||
.irBlock {
|
.irBlock {
|
||||||
|
// TODO: Move this to the enclosing class, right now the parent field is wrong!
|
||||||
+referenceClass
|
+referenceClass
|
||||||
+irCall(referenceClass.constructors.single()).apply {
|
+irCall(referenceClass.constructors.single()).apply {
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user