mirror of
https://github.com/github/codeql.git
synced 2026-07-10 05:55:32 +02:00
kotlin extractor: fold unaryMinus(IrConst) into a signed literal in K2
In K2 mode the frontend emits `-123L` as IrCall(unaryMinus, IrConst(123L)) rather than IrConst(-123L) as in K1. Queries that search for negative numeric literals therefore need to match both a UnaryMinusExpr wrapping a literal and a plain literal, depending on language mode. Fix: when extractCallExpression encounters an isNumericFunction(unaryMinus) call whose dispatchReceiver is already an IrConst, fold the negation into the constant before extracting. The resulting literal node is identical to what K1 emits. Location: extend the span one character to the left to cover the `-` sign. In K2 the IrCall's startOffset equals the receiver's startOffset, so we recover the minus by subtracting one from the receiver offset. K1 is unaffected: the K1 frontend folds the sign into the constant before IR generation, so this new branch never triggers when compiling with -language 1.9. Expected output changes: - test-kotlin2/library-tests/literals/literals.expected: negative long, float and double literals now appear as plain typed literals instead of as UnaryMinus nodes. The file is now byte-identical to test-kotlin1/library-tests/literals/literals.expected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -4391,6 +4391,55 @@ open class KotlinFileExtractor(
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
unaryopDisp(id)
|
||||
}
|
||||
// Fold unaryMinus applied to a numeric constant into a single negative literal.
|
||||
// In K2 mode, `-123L` is emitted as IrCall(unaryMinus, IrConst(123L)) rather than
|
||||
// IrConst(-123L) as in K1. Folding restores K1 behaviour and makes negative
|
||||
// numeric literals directly queryable in both modes.
|
||||
isNumericFunction(target, "unaryMinus") && c.dispatchReceiver is CodeQLIrConst<*> -> {
|
||||
val receiver = c.dispatchReceiver as CodeQLIrConst<*>
|
||||
val v = receiver.value
|
||||
val type = useType(c.type)
|
||||
// In K2 the IrCall's startOffset equals the receiver's startOffset, so the
|
||||
// minus sign (one character before the literal) must be recovered from the source.
|
||||
val locId =
|
||||
if (receiver.startOffset > 0)
|
||||
tw.getLocation(receiver.startOffset - 1, c.endOffset)
|
||||
else
|
||||
tw.getLocation(c)
|
||||
when (v) {
|
||||
is Int ->
|
||||
extractConstantInteger(-v, locId, parent, idx, callable, enclosingStmt)
|
||||
is Short ->
|
||||
extractConstantInteger(-v.toInt(), locId, parent, idx, callable, enclosingStmt)
|
||||
is Byte ->
|
||||
extractConstantInteger(-v.toInt(), locId, parent, idx, callable, enclosingStmt)
|
||||
is Long ->
|
||||
exprIdOrFresh<DbLongliteral>(null).also { id ->
|
||||
tw.writeExprs_longliteral(id, type.javaResult.id, parent, idx)
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
extractExprContext(id, locId, callable, enclosingStmt)
|
||||
tw.writeNamestrings((-v).toString(), (-v).toString(), id)
|
||||
}
|
||||
is Float ->
|
||||
exprIdOrFresh<DbFloatingpointliteral>(null).also { id ->
|
||||
tw.writeExprs_floatingpointliteral(id, type.javaResult.id, parent, idx)
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
extractExprContext(id, locId, callable, enclosingStmt)
|
||||
tw.writeNamestrings((-v).toString(), (-v).toString(), id)
|
||||
}
|
||||
is Double ->
|
||||
exprIdOrFresh<DbDoubleliteral>(null).also { id ->
|
||||
tw.writeExprs_doubleliteral(id, type.javaResult.id, parent, idx)
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
extractExprContext(id, locId, callable, enclosingStmt)
|
||||
tw.writeNamestrings((-v).toString(), (-v).toString(), id)
|
||||
}
|
||||
else ->
|
||||
logger.errorElement(
|
||||
"Unexpected constant type for unaryMinus folding: ${v?.javaClass}", c
|
||||
)
|
||||
}
|
||||
}
|
||||
isNumericFunction(target, "inv", "unaryMinus", "unaryPlus") -> {
|
||||
val type = useType(c.type)
|
||||
val id: Label<out DbExpr> =
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
| literals.kt:13:30:13:33 | -123 | LongLiteral |
|
||||
| literals.kt:14:30:14:31 | 0 | LongLiteral |
|
||||
| literals.kt:15:30:15:33 | 123 | LongLiteral |
|
||||
| literals.kt:16:31:16:34 | 123 | LongLiteral |
|
||||
| literals.kt:16:30:16:34 | -123 | LongLiteral |
|
||||
| literals.kt:17:30:17:33 | 15 | LongLiteral |
|
||||
| literals.kt:18:30:18:39 | 11 | LongLiteral |
|
||||
| literals.kt:19:30:19:38 | 1234567 | LongLiteral |
|
||||
| literals.kt:20:32:20:35 | 0.0 | FloatLiteral |
|
||||
| literals.kt:21:32:21:37 | 123.4 | FloatLiteral |
|
||||
| literals.kt:22:33:22:38 | 123.4 | FloatLiteral |
|
||||
| literals.kt:22:32:22:38 | -123.4 | FloatLiteral |
|
||||
| literals.kt:23:34:23:36 | 0.0 | DoubleLiteral |
|
||||
| literals.kt:24:34:24:38 | 123.4 | DoubleLiteral |
|
||||
| literals.kt:25:35:25:39 | 123.4 | DoubleLiteral |
|
||||
| literals.kt:25:34:25:39 | -123.4 | DoubleLiteral |
|
||||
| literals.kt:26:30:26:32 | c | CharacterLiteral |
|
||||
| literals.kt:27:30:27:33 | \n | CharacterLiteral |
|
||||
| literals.kt:28:34:28:35 | "" | StringLiteral |
|
||||
|
||||
Reference in New Issue
Block a user