Fix handling of 'null' passed as C string (#3452)
This commit is contained in:
committed by
GitHub
parent
496ebbe2a8
commit
5081adbf87
+25
-13
@@ -1375,8 +1375,10 @@ private class ObjCBlockPointerValuePassing(
|
||||
private class WCStringArgumentPassing : KotlinToCArgumentPassing {
|
||||
|
||||
override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression {
|
||||
val wcstr = irBuilder.irCall(symbols.interopWcstr.owner).apply {
|
||||
extensionReceiver = expression
|
||||
val wcstr = irBuilder.irSafeTransform(expression) {
|
||||
irCall(symbols.interopWcstr.owner).apply {
|
||||
extensionReceiver = it
|
||||
}
|
||||
}
|
||||
return with(CValuesRefArgumentPassing) { passValue(wcstr) }
|
||||
}
|
||||
@@ -1386,8 +1388,10 @@ private class WCStringArgumentPassing : KotlinToCArgumentPassing {
|
||||
private class CStringArgumentPassing : KotlinToCArgumentPassing {
|
||||
|
||||
override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression {
|
||||
val cstr = irBuilder.irCall(symbols.interopCstr.owner).apply {
|
||||
extensionReceiver = expression
|
||||
val cstr = irBuilder.irSafeTransform(expression) {
|
||||
irCall(symbols.interopCstr.owner).apply {
|
||||
extensionReceiver = it
|
||||
}
|
||||
}
|
||||
return with(CValuesRefArgumentPassing) { passValue(cstr) }
|
||||
}
|
||||
@@ -1410,25 +1414,33 @@ private fun KotlinToCCallBuilder.cValuesRefToPointer(
|
||||
value: IrExpression
|
||||
): IrExpression = if (value.type.classifierOrNull == symbols.interopCPointer) {
|
||||
value // Optimization
|
||||
} else with(irBuilder) {
|
||||
} else {
|
||||
val getPointerFunction = symbols.interopCValuesRef.owner
|
||||
.simpleFunctions()
|
||||
.single { it.name.asString() == "getPointer" }
|
||||
|
||||
fun getPointer(expression: IrExpression) = irCall(getPointerFunction).apply {
|
||||
dispatchReceiver = expression
|
||||
putValueArgument(0, bridgeCallBuilder.getMemScope())
|
||||
irBuilder.irSafeTransform(value) {
|
||||
irCall(getPointerFunction).apply {
|
||||
dispatchReceiver = it
|
||||
putValueArgument(0, bridgeCallBuilder.getMemScope())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!value.type.isNullable()) {
|
||||
getPointer(value) // Optimization
|
||||
} else irLetS(value) { valueVarSymbol ->
|
||||
private fun IrBuilderWithScope.irSafeTransform(
|
||||
value: IrExpression,
|
||||
block: IrBuilderWithScope.(IrExpression) -> IrExpression
|
||||
): IrExpression = if (!value.type.isNullable()) {
|
||||
block(value) // Optimization
|
||||
} else {
|
||||
irLetS(value) { valueVarSymbol ->
|
||||
val valueVar = valueVarSymbol.owner
|
||||
val transformed = block(irGet(valueVar))
|
||||
irIfThenElse(
|
||||
type = symbols.interopCPointer.typeWithStarProjections.makeNullable(),
|
||||
type = transformed.type.makeNullable(),
|
||||
condition = irEqeqeq(irGet(valueVar), irNull()),
|
||||
thenPart = irNull(),
|
||||
elsePart = getPointer(irGet(valueVar))
|
||||
elsePart = transformed
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3292,6 +3292,10 @@ createInterop("ctypes") {
|
||||
it.defFile 'interop/basics/ctypes.def'
|
||||
}
|
||||
|
||||
createInterop("cvalues") {
|
||||
it.defFile 'interop/basics/cvalues.def'
|
||||
}
|
||||
|
||||
createInterop("ccallbacksAndVarargs") {
|
||||
it.defFile 'interop/basics/ccallbacksAndVarargs.def'
|
||||
}
|
||||
@@ -3449,6 +3453,12 @@ interopTest("interop_types") {
|
||||
interop = 'ctypes'
|
||||
}
|
||||
|
||||
interopTest("interop_values") {
|
||||
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
||||
source = "interop/basics/values.kt"
|
||||
interop = 'cvalues'
|
||||
}
|
||||
|
||||
interopTest("interop_callbacksAndVarargs") {
|
||||
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
||||
source = "interop/basics/callbacksAndVarargs.kt"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
_Bool isNullString(const char* str) {
|
||||
return str == (const char*)0;
|
||||
}
|
||||
|
||||
typedef const short* LPCWSTR;
|
||||
|
||||
_Bool isNullWString(LPCWSTR str) {
|
||||
return str == (LPCWSTR)0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import kotlinx.cinterop.*
|
||||
import kotlin.test.*
|
||||
import cvalues.*
|
||||
|
||||
fun main() {
|
||||
assertTrue(isNullString(null))
|
||||
assertTrue(isNullWString(null))
|
||||
assertFalse(isNullString("a"))
|
||||
assertFalse(isNullWString("b"))
|
||||
}
|
||||
Reference in New Issue
Block a user