Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ba7a753

Browse files
committed
Kotlin: Add support for more type operators
1 parent d247e4f commit ba7a753

7 files changed

Lines changed: 102 additions & 9 deletions

File tree

java/kotlin-extractor/src/main/kotlin/KotlinExtractorExtension.kt

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,19 +1475,45 @@ class X {
14751475
}
14761476
}
14771477

1478+
fun extractTypeAccess(t: IrType, parent: Label<out DbExprparent>, idx: Int, elementForLocation: IrElement) {
1479+
// TODO: elementForLocation allows us to give some sort of
1480+
// location, but a proper location for the type access will
1481+
// require upstream changes
1482+
val type = useType(t)
1483+
val id = tw.getFreshIdLabel<DbUnannotatedtypeaccess>()
1484+
tw.writeExprs_unannotatedtypeaccess(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
1485+
val locId = tw.getLocation(elementForLocation)
1486+
tw.writeHasLocation(id, locId)
1487+
}
1488+
14781489
fun extractTypeOperatorCall(e: IrTypeOperatorCall, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int) {
14791490
when(e.operator) {
1491+
IrTypeOperator.CAST -> {
1492+
val id = tw.getFreshIdLabel<DbCastexpr>()
1493+
val locId = tw.getLocation(e)
1494+
val type = useType(e.type)
1495+
tw.writeExprs_castexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
1496+
tw.writeHasLocation(id, locId)
1497+
extractTypeAccess(e.typeOperand, id, 0, e)
1498+
extractExpressionExpr(e.argument, callable, id, 1)
1499+
}
14801500
IrTypeOperator.INSTANCEOF -> {
14811501
val id = tw.getFreshIdLabel<DbInstanceofexpr>()
14821502
val locId = tw.getLocation(e)
14831503
val type = useType(e.type)
14841504
tw.writeExprs_instanceofexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
14851505
tw.writeHasLocation(id, locId)
14861506
extractExpressionExpr(e.argument, callable, id, 0)
1487-
val typeArg = useType(e.typeOperand)
1488-
val typeAccessId = tw.getFreshIdLabel<DbUnannotatedtypeaccess>()
1489-
tw.writeExprs_unannotatedtypeaccess(typeAccessId, typeArg.javaResult.id, typeArg.kotlinResult.id, id, 1)
1490-
// TODO: Type access location
1507+
extractTypeAccess(e.typeOperand, id, 1, e)
1508+
}
1509+
IrTypeOperator.NOT_INSTANCEOF -> {
1510+
val id = tw.getFreshIdLabel<DbNotinstanceofexpr>()
1511+
val locId = tw.getLocation(e)
1512+
val type = useType(e.type)
1513+
tw.writeExprs_notinstanceofexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
1514+
tw.writeHasLocation(id, locId)
1515+
extractExpressionExpr(e.argument, callable, id, 0)
1516+
extractTypeAccess(e.typeOperand, id, 1, e)
14911517
}
14921518
else -> {
14931519
logger.warnElement(Severity.ErrorSevere, "Unrecognised IrTypeOperatorCall: " + e.render(), e)

java/ql/lib/config/semmlecode.dbscheme

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,8 @@ case @expr.kind of
667667
| 74 = @errorexpr
668668
| 75 = @whenexpr
669669
| 76 = @getclassexpr
670+
| 77 = @safecastexpr
671+
| 78 = @notinstanceofexpr
670672
;
671673

672674
/** Holds if this `when` expression was written as an `if` expression. */

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,12 @@ private module ControlFlowGraphImpl {
448448
or
449449
this instanceof CastExpr
450450
or
451+
this instanceof SafeCastExpr
452+
or
451453
this instanceof InstanceOfExpr and not this.(InstanceOfExpr).isPattern()
452454
or
455+
this instanceof NotInstanceOfExpr
456+
or
453457
this instanceof LocalVariableDeclExpr and
454458
not this = any(InstanceOfExpr ioe).getLocalVariableDeclExpr()
455459
or
@@ -526,8 +530,12 @@ private module ControlFlowGraphImpl {
526530
or
527531
index = 0 and result = this.(CastExpr).getExpr()
528532
or
533+
index = 0 and result = this.(SafeCastExpr).getExpr()
534+
or
529535
index = 0 and result = this.(InstanceOfExpr).getExpr()
530536
or
537+
index = 0 and result = this.(NotInstanceOfExpr).getExpr()
538+
or
531539
index = 0 and result = this.(LocalVariableDeclExpr).getInit()
532540
or
533541
index = 0 and result = this.(RValue).getQualifier() and not result instanceof TypeAccess
@@ -599,6 +607,8 @@ private module ControlFlowGraphImpl {
599607
or
600608
result = first(n.(InstanceOfExpr).getExpr())
601609
or
610+
result = first(n.(NotInstanceOfExpr).getExpr())
611+
or
602612
result = first(n.(SynchronizedStmt).getExpr())
603613
or
604614
result = n and

java/ql/lib/semmle/code/java/Conversions.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ class CastConversionContext extends ConversionSite {
123123
override string kind() { result = "cast context" }
124124
}
125125

126+
class SafeCastConversionContext extends ConversionSite {
127+
SafeCastExpr c;
128+
129+
CastConversionContext() { this = c.getExpr() }
130+
131+
override Type getConversionTarget() { result = c.getType() }
132+
133+
override predicate isImplicit() { none() }
134+
135+
override string kind() { result = "safe cast context" }
136+
}
137+
126138
/**
127139
* A numeric conversion. For example, `a * b` converts `a` and
128140
* `b` to have an appropriate numeric type.

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,21 @@ class CastExpr extends Expr, @castexpr {
11521152
override string getAPrimaryQlClass() { result = "CastExpr" }
11531153
}
11541154

1155+
// TODO: Would this be better as a predicate on CastExpr?
1156+
/** A safe cast expression. */
1157+
class SafeCastExpr extends Expr, @safecastexpr {
1158+
/** Gets the target type of this cast expression. */
1159+
Expr getTypeExpr() { result.isNthChildOf(this, 0) }
1160+
1161+
/** Gets the expression to which the cast operator is applied. */
1162+
Expr getExpr() { result.isNthChildOf(this, 1) }
1163+
1164+
/** Gets a printable representation of this expression. */
1165+
override string toString() { result = "... as? ..." }
1166+
1167+
override string getAPrimaryQlClass() { result = "SafeCastExpr" }
1168+
}
1169+
11551170
/** A class instance creation expression. */
11561171
class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr {
11571172
/** Gets the number of arguments provided to the constructor of the class instance creation expression. */
@@ -1442,6 +1457,28 @@ class InstanceOfExpr extends Expr, @instanceofexpr {
14421457
override string getAPrimaryQlClass() { result = "InstanceOfExpr" }
14431458
}
14441459

1460+
// TODO: Should this be desugared into instanceof.not()?
1461+
// Note expressions/IrTypeOperatorCall.kt says:
1462+
// NOT_INSTANCEOF, // TODO drop and replace with `INSTANCEOF<T>(x).not()`?
1463+
/** An `instanceof` expression. */
1464+
class NotInstanceOfExpr extends Expr, @notinstanceofexpr {
1465+
/** Gets the expression on the left-hand side of the `!is` operator. */
1466+
Expr getExpr() {
1467+
result.isNthChildOf(this, 0)
1468+
}
1469+
1470+
/** Gets the access to the type on the right-hand side of the `!is` operator. */
1471+
Expr getTypeName() { result.isNthChildOf(this, 1) }
1472+
1473+
/** Gets the type this `!is` expression checks for. */
1474+
RefType getCheckedType() { result = getTypeName().getType() }
1475+
1476+
/** Gets a printable representation of this expression. */
1477+
override string toString() { result = "... !is ..." }
1478+
1479+
override string getAPrimaryQlClass() { result = "NotInstanceOfExpr" }
1480+
}
1481+
14451482
/**
14461483
* A local variable declaration expression.
14471484
*

java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ private predicate safeCast(Type fromtyp, Type totyp) {
360360
/**
361361
* A cast that can be ignored for the purpose of range analysis.
362362
*/
363-
private class SafeCastExpr extends CastExpr {
364-
SafeCastExpr() { safeCast(getExpr().getType(), getType()) }
363+
private class RangeAnalysisSafeCastExpr extends CastExpr {
364+
RangeAnalysisSafeCastExpr() { safeCast(getExpr().getType(), getType()) }
365365
}
366366

367367
/**
@@ -382,7 +382,7 @@ private predicate typeBound(Type typ, int lowerbound, int upperbound) {
382382
*/
383383
private class NarrowingCastExpr extends CastExpr {
384384
NarrowingCastExpr() {
385-
not this instanceof SafeCastExpr and
385+
not this instanceof RangeAnalysisSafeCastExpr and
386386
typeBound(getType(), _, _)
387387
}
388388

@@ -412,7 +412,7 @@ private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) {
412412
valueFlowStep(e2, e1, delta) and
413413
(upper = true or upper = false)
414414
or
415-
e2.(SafeCastExpr).getExpr() = e1 and
415+
e2.(RangeAnalysisSafeCastExpr).getExpr() = e1 and
416416
delta = 0 and
417417
(upper = true or upper = false)
418418
or

java/ql/test/kotlin/library-tests/exprs/exprs.expected

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,15 @@
5454
| exprs.kt:40:5:40:22 | b6 | LocalVariableDeclExpr |
5555
| exprs.kt:40:14:40:15 | i1 | VarAccess |
5656
| exprs.kt:40:14:40:22 | ...instanceof... | InstanceOfExpr |
57+
| exprs.kt:40:14:40:22 | int | TypeAccess |
5758
| exprs.kt:41:5:41:23 | b7 | LocalVariableDeclExpr |
59+
| exprs.kt:41:14:41:15 | i1 | VarAccess |
60+
| exprs.kt:41:14:41:23 | ... !is ... | NotInstanceOfExpr |
61+
| exprs.kt:41:14:41:23 | int | TypeAccess |
5862
| exprs.kt:42:5:42:26 | b8 | LocalVariableDeclExpr |
63+
| exprs.kt:42:14:42:15 | b7 | VarAccess |
64+
| exprs.kt:42:14:42:26 | (...)... | CastExpr |
65+
| exprs.kt:42:14:42:26 | boolean | TypeAccess |
5966
| exprs.kt:43:5:43:35 | str1 | LocalVariableDeclExpr |
6067
| exprs.kt:43:25:43:34 | string lit | StringLiteral |
6168
| exprs.kt:44:5:44:36 | str2 | LocalVariableDeclExpr |
@@ -74,4 +81,3 @@
7481
| exprs.kt:53:9:53:18 | n | VarAccess |
7582
| exprs.kt:54:27:54:31 | new C(...) | ClassInstanceExpr |
7683
| exprs.kt:54:29:54:30 | 42 | IntegerLiteral |
77-
| file://:0:0:0:0 | int | TypeAccess |

0 commit comments

Comments
 (0)