Implement $default method synthesis

This adds methods that fill in default parameters whenever a constructor or method uses default parameter values. I use as similar an approach to the real Kotlin compiler as possible both because this produces the desirable dataflow, and because it should merge cleanly with the same class file seen by the Java extractor, which will see and
extract the signatures of the default methods.
This commit is contained in:
Chris Smowton
2022-10-03 14:47:07 +01:00
parent 6f3c9e4403
commit 34a0a0d080
8 changed files with 1460 additions and 95 deletions

View File

@@ -65,6 +65,8 @@ class Element extends @element, Top {
i = 8 and result = "Proxy static method for a @JvmStatic-annotated function or property"
or
i = 9 and result = "Forwarder for a @JvmOverloads-annotated function"
or
i = 10 and result = "Forwarder for Kotlin calls that need default arguments filling in"
)
}
}

View File

@@ -0,0 +1,849 @@
test.kt:
# 0| [CompilationUnit] test
# 0| 1: [Class] TestKt
# 1| 1: [Method] sink
# 1| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 1| 0: [Parameter] a
# 1| 0: [TypeAccess] Object
# 1| 5: [BlockStmt] { ... }
# 3| 2: [Class] TestMember
# 3| 1: [Constructor] TestMember
# 3| 5: [BlockStmt] { ... }
# 3| 0: [SuperConstructorInvocationStmt] super(...)
# 3| 1: [BlockStmt] { ... }
# 5| 2: [Method] f
# 5| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 5| 0: [Parameter] x
# 5| 0: [TypeAccess] String
# 5| 1: [Parameter] y
# 5| 0: [TypeAccess] String
# 5| 2: [Parameter] z
# 5| 0: [TypeAccess] String
# 5| 5: [BlockStmt] { ... }
# 6| 0: [ExprStmt] <Expr>;
# 6| 0: [MethodAccess] sink(...)
# 6| -1: [TypeAccess] TestKt
# 6| 0: [VarAccess] y
# 5| 3: [Method] f$default
# 5| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 5| 0: [Parameter] p0
# 5| 0: [TypeAccess] TestMember
# 5| 1: [Parameter] p1
# 5| 0: [TypeAccess] String
# 5| 2: [Parameter] p2
# 5| 0: [TypeAccess] String
# 5| 3: [Parameter] p3
# 5| 0: [TypeAccess] String
# 5| 4: [Parameter] p4
# 5| 0: [TypeAccess] int
# 5| 5: [Parameter] p5
# 5| 0: [TypeAccess] Object
# 5| 5: [BlockStmt] { ... }
# 5| 0: [IfStmt] if (...)
# 5| 0: [EQExpr] ... == ...
# 5| 0: [AndBitwiseExpr] ... & ...
# 5| 0: [IntegerLiteral] 2
# 5| 1: [VarAccess] p4
# 5| 1: [IntegerLiteral] 0
# 5| 1: [ExprStmt] <Expr>;
# 5| 0: [AssignExpr] ...=...
# 5| 0: [VarAccess] p2
# 5| 1: [VarAccess] p1
# 5| 1: [IfStmt] if (...)
# 5| 0: [EQExpr] ... == ...
# 5| 0: [AndBitwiseExpr] ... & ...
# 5| 0: [IntegerLiteral] 4
# 5| 1: [VarAccess] p4
# 5| 1: [IntegerLiteral] 0
# 5| 1: [ExprStmt] <Expr>;
# 5| 0: [AssignExpr] ...=...
# 5| 0: [VarAccess] p3
# 5| 1: [StringLiteral] hello world
# 5| 2: [ReturnStmt] return ...
# 5| 0: [MethodAccess] f(...)
# 5| -1: [VarAccess] p0
# 5| 0: [VarAccess] p1
# 5| 1: [VarAccess] p2
# 5| 2: [VarAccess] p3
# 9| 4: [Method] user
# 9| 3: [TypeAccess] Unit
# 9| 5: [BlockStmt] { ... }
# 10| 0: [ExprStmt] <Expr>;
# 10| 0: [MethodAccess] f$default(...)
# 10| -1: [TypeAccess] TestMember
# 10| 0: [ThisAccess] this
# 10| 1: [StringLiteral] member sunk
# 1| 2: [NullLiteral] null
# 1| 3: [NullLiteral] null
# 1| 4: [IntegerLiteral] 1
# 1| 5: [NullLiteral] null
# 11| 1: [ExprStmt] <Expr>;
# 11| 0: [MethodAccess] f$default(...)
# 11| -1: [TypeAccess] TestMember
# 11| 0: [ThisAccess] this
# 11| 1: [StringLiteral] member sunk fp
# 11| 2: [StringLiteral] member sunk 2
# 1| 3: [NullLiteral] null
# 1| 4: [IntegerLiteral] 3
# 1| 5: [NullLiteral] null
# 12| 2: [ExprStmt] <Expr>;
# 12| 0: [MethodAccess] f(...)
# 12| -1: [ThisAccess] this
# 12| 0: [StringLiteral] not sunk
# 12| 1: [StringLiteral] member sunk 3
# 12| 2: [StringLiteral] not sunk
# 17| 3: [Class] TestExtensionMember
# 17| 1: [Constructor] TestExtensionMember
# 17| 5: [BlockStmt] { ... }
# 17| 0: [SuperConstructorInvocationStmt] super(...)
# 17| 1: [BlockStmt] { ... }
# 19| 2: [ExtensionMethod] f
# 19| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 19| 0: [Parameter] <this>
# 19| 0: [TypeAccess] String
# 19| 1: [Parameter] x
# 19| 0: [TypeAccess] String
# 19| 2: [Parameter] y
# 19| 0: [TypeAccess] String
# 19| 3: [Parameter] z
# 19| 0: [TypeAccess] String
# 19| 5: [BlockStmt] { ... }
# 20| 0: [ExprStmt] <Expr>;
# 20| 0: [MethodAccess] sink(...)
# 20| -1: [TypeAccess] TestKt
# 20| 0: [ExtensionReceiverAccess] this
# 21| 1: [ExprStmt] <Expr>;
# 21| 0: [MethodAccess] sink(...)
# 21| -1: [TypeAccess] TestKt
# 21| 0: [VarAccess] y
# 19| 3: [Method] f$default
# 19| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 19| 0: [Parameter] p0
# 19| 0: [TypeAccess] String
# 19| 1: [Parameter] p1
# 19| 0: [TypeAccess] TestExtensionMember
# 19| 2: [Parameter] p2
# 19| 0: [TypeAccess] String
# 19| 3: [Parameter] p3
# 19| 0: [TypeAccess] String
# 19| 4: [Parameter] p4
# 19| 0: [TypeAccess] String
# 19| 5: [Parameter] p5
# 19| 0: [TypeAccess] int
# 19| 6: [Parameter] p6
# 19| 0: [TypeAccess] Object
# 19| 5: [BlockStmt] { ... }
# 19| 0: [IfStmt] if (...)
# 19| 0: [EQExpr] ... == ...
# 19| 0: [AndBitwiseExpr] ... & ...
# 19| 0: [IntegerLiteral] 2
# 19| 1: [VarAccess] p5
# 19| 1: [IntegerLiteral] 0
# 19| 1: [ExprStmt] <Expr>;
# 19| 0: [AssignExpr] ...=...
# 19| 0: [VarAccess] p3
# 19| 1: [VarAccess] p2
# 19| 1: [IfStmt] if (...)
# 19| 0: [EQExpr] ... == ...
# 19| 0: [AndBitwiseExpr] ... & ...
# 19| 0: [IntegerLiteral] 4
# 19| 1: [VarAccess] p5
# 19| 1: [IntegerLiteral] 0
# 19| 1: [ExprStmt] <Expr>;
# 19| 0: [AssignExpr] ...=...
# 19| 0: [VarAccess] p4
# 19| 1: [StringLiteral] hello world
# 19| 2: [ReturnStmt] return ...
# 19| 0: [MethodAccess] f(...)
# 19| -1: [VarAccess] p1
# 19| 0: [VarAccess] p0
# 19| 1: [VarAccess] p2
# 19| 2: [VarAccess] p3
# 19| 3: [VarAccess] p4
# 24| 4: [Method] user
# 24| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 24| 0: [Parameter] sunk
# 24| 0: [TypeAccess] String
# 24| 5: [BlockStmt] { ... }
# 25| 0: [ExprStmt] <Expr>;
# 25| 0: [MethodAccess] f$default(...)
# 25| -1: [TypeAccess] TestExtensionMember
# 25| 0: [VarAccess] sunk
# 25| 1: [ThisAccess] this
# 25| 2: [StringLiteral] extension sunk
# 1| 3: [NullLiteral] null
# 1| 4: [NullLiteral] null
# 1| 5: [IntegerLiteral] 1
# 1| 6: [NullLiteral] null
# 26| 1: [ExprStmt] <Expr>;
# 26| 0: [MethodAccess] f$default(...)
# 26| -1: [TypeAccess] TestExtensionMember
# 26| 0: [VarAccess] sunk
# 26| 1: [ThisAccess] this
# 26| 2: [StringLiteral] extension sunk fp
# 26| 3: [StringLiteral] extension sunk 2
# 1| 4: [NullLiteral] null
# 1| 5: [IntegerLiteral] 3
# 1| 6: [NullLiteral] null
# 27| 2: [ExprStmt] <Expr>;
# 27| 0: [MethodAccess] f(...)
# 27| -1: [ThisAccess] this
# 27| 0: [VarAccess] sunk
# 27| 1: [StringLiteral] not sunk
# 27| 2: [StringLiteral] extension sunk 3
# 27| 3: [StringLiteral] not sunk
# 32| 4: [Class] TestStaticMember
# 32| 1: [Constructor] TestStaticMember
# 32| 5: [BlockStmt] { ... }
# 32| 0: [SuperConstructorInvocationStmt] super(...)
# 32| 1: [BlockStmt] { ... }
# 34| 2: [Method] f
# 34| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 34| 0: [Parameter] x
# 34| 0: [TypeAccess] String
# 34| 1: [Parameter] y
# 34| 0: [TypeAccess] String
# 34| 2: [Parameter] z
# 34| 0: [TypeAccess] String
# 34| 5: [BlockStmt] { ... }
# 35| 0: [ExprStmt] <Expr>;
# 35| 0: [MethodAccess] sink(...)
# 35| -1: [TypeAccess] TestKt
# 35| 0: [VarAccess] y
# 34| 3: [Method] f$default
# 34| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 34| 0: [Parameter] p0
# 34| 0: [TypeAccess] String
# 34| 1: [Parameter] p1
# 34| 0: [TypeAccess] String
# 34| 2: [Parameter] p2
# 34| 0: [TypeAccess] String
# 34| 3: [Parameter] p3
# 34| 0: [TypeAccess] int
# 34| 4: [Parameter] p4
# 34| 0: [TypeAccess] Object
# 34| 5: [BlockStmt] { ... }
# 34| 0: [IfStmt] if (...)
# 34| 0: [EQExpr] ... == ...
# 34| 0: [AndBitwiseExpr] ... & ...
# 34| 0: [IntegerLiteral] 2
# 34| 1: [VarAccess] p3
# 34| 1: [IntegerLiteral] 0
# 34| 1: [ExprStmt] <Expr>;
# 34| 0: [AssignExpr] ...=...
# 34| 0: [VarAccess] p1
# 34| 1: [VarAccess] p0
# 34| 1: [IfStmt] if (...)
# 34| 0: [EQExpr] ... == ...
# 34| 0: [AndBitwiseExpr] ... & ...
# 34| 0: [IntegerLiteral] 4
# 34| 1: [VarAccess] p3
# 34| 1: [IntegerLiteral] 0
# 34| 1: [ExprStmt] <Expr>;
# 34| 0: [AssignExpr] ...=...
# 34| 0: [VarAccess] p2
# 34| 1: [StringLiteral] hello world
# 34| 2: [ReturnStmt] return ...
# 34| 0: [MethodAccess] f(...)
# 34| -1: [TypeAccess] TestStaticMember
# 34| 0: [VarAccess] p0
# 34| 1: [VarAccess] p1
# 34| 2: [VarAccess] p2
# 38| 4: [Method] user
# 38| 3: [TypeAccess] Unit
# 38| 5: [BlockStmt] { ... }
# 39| 0: [ExprStmt] <Expr>;
# 39| 0: [MethodAccess] f$default(...)
# 39| -1: [TypeAccess] TestStaticMember
# 39| 0: [StringLiteral] static sunk
# 1| 1: [NullLiteral] null
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 1
# 1| 4: [NullLiteral] null
# 40| 1: [ExprStmt] <Expr>;
# 40| 0: [MethodAccess] f$default(...)
# 40| -1: [TypeAccess] TestStaticMember
# 40| 0: [StringLiteral] static sunk fp
# 40| 1: [StringLiteral] static sunk 2
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 3
# 1| 4: [NullLiteral] null
# 41| 2: [ExprStmt] <Expr>;
# 41| 0: [MethodAccess] f(...)
# 41| -1: [TypeAccess] TestStaticMember
# 41| 0: [StringLiteral] not sunk
# 41| 1: [StringLiteral] static sunk 3
# 41| 2: [StringLiteral] not sunk
# 46| 5: [Class] ExtendMe
# 46| 1: [Constructor] ExtendMe
# 46| 5: [BlockStmt] { ... }
# 46| 0: [SuperConstructorInvocationStmt] super(...)
# 46| 1: [BlockStmt] { ... }
# 48| 2: [Method] f
# 48| 3: [TypeAccess] String
#-----| 4: (Parameters)
# 48| 0: [Parameter] x
# 48| 0: [TypeAccess] String
# 48| 5: [BlockStmt] { ... }
# 48| 0: [ReturnStmt] return ...
# 48| 0: [VarAccess] x
# 52| 6: [Class] TestReceiverReferences
# 52| 1: [Constructor] TestReceiverReferences
# 52| 5: [BlockStmt] { ... }
# 52| 0: [SuperConstructorInvocationStmt] super(...)
# 52| 1: [BlockStmt] { ... }
# 54| 2: [Method] g
# 54| 3: [TypeAccess] String
#-----| 4: (Parameters)
# 54| 0: [Parameter] x
# 54| 0: [TypeAccess] String
# 54| 5: [BlockStmt] { ... }
# 54| 0: [ReturnStmt] return ...
# 54| 0: [VarAccess] x
# 56| 3: [ExtensionMethod] test
# 56| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 56| 0: [Parameter] <this>
# 56| 0: [TypeAccess] ExtendMe
# 56| 1: [Parameter] x
# 56| 0: [TypeAccess] String
# 56| 2: [Parameter] y
# 56| 0: [TypeAccess] String
# 56| 3: [Parameter] z
# 56| 0: [TypeAccess] String
# 56| 5: [BlockStmt] { ... }
# 57| 0: [ExprStmt] <Expr>;
# 57| 0: [MethodAccess] sink(...)
# 57| -1: [TypeAccess] TestKt
# 57| 0: [VarAccess] y
# 56| 4: [Method] test$default
# 56| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 56| 0: [Parameter] p0
# 56| 0: [TypeAccess] ExtendMe
# 56| 1: [Parameter] p1
# 56| 0: [TypeAccess] TestReceiverReferences
# 56| 2: [Parameter] p2
# 56| 0: [TypeAccess] String
# 56| 3: [Parameter] p3
# 56| 0: [TypeAccess] String
# 56| 4: [Parameter] p4
# 56| 0: [TypeAccess] String
# 56| 5: [Parameter] p5
# 56| 0: [TypeAccess] int
# 56| 6: [Parameter] p6
# 56| 0: [TypeAccess] Object
# 56| 5: [BlockStmt] { ... }
# 56| 0: [IfStmt] if (...)
# 56| 0: [EQExpr] ... == ...
# 56| 0: [AndBitwiseExpr] ... & ...
# 56| 0: [IntegerLiteral] 2
# 56| 1: [VarAccess] p5
# 56| 1: [IntegerLiteral] 0
# 56| 1: [ExprStmt] <Expr>;
# 56| 0: [AssignExpr] ...=...
# 56| 0: [VarAccess] p3
# 56| 1: [MethodAccess] f(...)
# 56| -1: [VarAccess] p0
# 56| 0: [MethodAccess] g(...)
# 56| -1: [VarAccess] p1
# 56| 0: [VarAccess] p2
# 56| 1: [IfStmt] if (...)
# 56| 0: [EQExpr] ... == ...
# 56| 0: [AndBitwiseExpr] ... & ...
# 56| 0: [IntegerLiteral] 4
# 56| 1: [VarAccess] p5
# 56| 1: [IntegerLiteral] 0
# 56| 1: [ExprStmt] <Expr>;
# 56| 0: [AssignExpr] ...=...
# 56| 0: [VarAccess] p4
# 56| 1: [StringLiteral] hello world
# 56| 2: [ReturnStmt] return ...
# 56| 0: [MethodAccess] test(...)
# 56| -1: [VarAccess] p1
# 56| 0: [VarAccess] p0
# 56| 1: [VarAccess] p2
# 56| 2: [VarAccess] p3
# 56| 3: [VarAccess] p4
# 60| 5: [Method] user
# 60| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 60| 0: [Parameter] t
# 60| 0: [TypeAccess] ExtendMe
# 60| 5: [BlockStmt] { ... }
# 61| 0: [ExprStmt] <Expr>;
# 61| 0: [MethodAccess] test$default(...)
# 61| -1: [TypeAccess] TestReceiverReferences
# 61| 0: [VarAccess] t
# 61| 1: [ThisAccess] this
# 61| 2: [StringLiteral] receiver refs sunk
# 1| 3: [NullLiteral] null
# 1| 4: [NullLiteral] null
# 1| 5: [IntegerLiteral] 1
# 1| 6: [NullLiteral] null
# 62| 1: [ExprStmt] <Expr>;
# 62| 0: [MethodAccess] test$default(...)
# 62| -1: [TypeAccess] TestReceiverReferences
# 62| 0: [VarAccess] t
# 62| 1: [ThisAccess] this
# 62| 2: [StringLiteral] receiver refs sunk fp
# 62| 3: [StringLiteral] receiver refs sunk 2
# 1| 4: [NullLiteral] null
# 1| 5: [IntegerLiteral] 3
# 1| 6: [NullLiteral] null
# 63| 2: [ExprStmt] <Expr>;
# 63| 0: [MethodAccess] test(...)
# 63| -1: [ThisAccess] this
# 63| 0: [VarAccess] t
# 63| 1: [StringLiteral] not sunk
# 63| 2: [StringLiteral] receiver refs sunk 3
# 63| 3: [StringLiteral] not sunk
# 68| 7: [Class] TestConstructor
# 68| 1: [Constructor] TestConstructor
#-----| 4: (Parameters)
# 68| 0: [Parameter] x
# 68| 0: [TypeAccess] String
# 68| 1: [Parameter] y
# 68| 0: [TypeAccess] String
# 68| 2: [Parameter] z
# 68| 0: [TypeAccess] String
# 68| 5: [BlockStmt] { ... }
# 68| 0: [SuperConstructorInvocationStmt] super(...)
# 68| 1: [BlockStmt] { ... }
# 71| 0: [ExprStmt] <Expr>;
# 71| 0: [MethodAccess] sink(...)
# 71| -1: [TypeAccess] TestKt
# 71| 0: [VarAccess] y
# 68| 2: [Constructor] TestConstructor
#-----| 4: (Parameters)
# 68| 0: [Parameter] p0
# 68| 0: [TypeAccess] String
# 68| 1: [Parameter] p1
# 68| 0: [TypeAccess] String
# 68| 2: [Parameter] p2
# 68| 0: [TypeAccess] String
# 68| 3: [Parameter] p3
# 68| 0: [TypeAccess] int
# 68| 4: [Parameter] p4
# 68| 0: [TypeAccess] DefaultConstructorMarker
# 68| 5: [BlockStmt] { ... }
# 68| 0: [IfStmt] if (...)
# 68| 0: [EQExpr] ... == ...
# 68| 0: [AndBitwiseExpr] ... & ...
# 68| 0: [IntegerLiteral] 2
# 68| 1: [VarAccess] p3
# 68| 1: [IntegerLiteral] 0
# 68| 1: [ExprStmt] <Expr>;
# 68| 0: [AssignExpr] ...=...
# 68| 0: [VarAccess] p1
# 68| 1: [VarAccess] p0
# 68| 1: [IfStmt] if (...)
# 68| 0: [EQExpr] ... == ...
# 68| 0: [AndBitwiseExpr] ... & ...
# 68| 0: [IntegerLiteral] 4
# 68| 1: [VarAccess] p3
# 68| 1: [IntegerLiteral] 0
# 68| 1: [ExprStmt] <Expr>;
# 68| 0: [AssignExpr] ...=...
# 68| 0: [VarAccess] p2
# 68| 1: [StringLiteral] hello world
# 68| 2: [ThisConstructorInvocationStmt] this(...)
# 68| 0: [VarAccess] p0
# 68| 1: [VarAccess] p1
# 68| 2: [VarAccess] p2
# 74| 3: [Method] user
# 74| 3: [TypeAccess] Unit
# 74| 5: [BlockStmt] { ... }
# 75| 0: [ExprStmt] <Expr>;
# 75| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
# 75| 0: [TypeAccess] Unit
# 75| 1: [ClassInstanceExpr] new TestConstructor(...)
# 75| -3: [TypeAccess] TestConstructor
# 75| 0: [StringLiteral] constructor sunk
# 1| 1: [NullLiteral] null
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 1
# 1| 4: [NullLiteral] null
# 76| 1: [ExprStmt] <Expr>;
# 76| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
# 76| 0: [TypeAccess] Unit
# 76| 1: [ClassInstanceExpr] new TestConstructor(...)
# 76| -3: [TypeAccess] TestConstructor
# 76| 0: [StringLiteral] constructor sunk fp
# 76| 1: [StringLiteral] constructor sunk 2
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 3
# 1| 4: [NullLiteral] null
# 77| 2: [ExprStmt] <Expr>;
# 77| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
# 77| 0: [TypeAccess] Unit
# 77| 1: [ClassInstanceExpr] new TestConstructor(...)
# 77| -3: [TypeAccess] TestConstructor
# 77| 0: [StringLiteral] not sunk
# 77| 1: [StringLiteral] constructor sunk 3
# 77| 2: [StringLiteral] not sunk
# 82| 8: [Class] TestLocal
# 82| 1: [Constructor] TestLocal
# 82| 5: [BlockStmt] { ... }
# 82| 0: [SuperConstructorInvocationStmt] super(...)
# 82| 1: [BlockStmt] { ... }
# 84| 2: [Method] enclosing
# 84| 3: [TypeAccess] Unit
# 84| 5: [BlockStmt] { ... }
# 86| 0: [LocalTypeDeclStmt] class ...
# 86| 0: [LocalClass]
# 86| 1: [Constructor]
# 86| 5: [BlockStmt] { ... }
# 86| 0: [SuperConstructorInvocationStmt] super(...)
# 86| 2: [Method] f
# 86| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 86| 0: [Parameter] x
# 86| 0: [TypeAccess] String
# 86| 1: [Parameter] y
# 86| 0: [TypeAccess] String
# 86| 2: [Parameter] z
# 86| 0: [TypeAccess] String
# 86| 5: [BlockStmt] { ... }
# 87| 0: [ExprStmt] <Expr>;
# 87| 0: [MethodAccess] sink(...)
# 87| -1: [TypeAccess] TestKt
# 87| 0: [VarAccess] y
# 86| 3: [Method] f$default
# 86| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 86| 0: [Parameter] p0
# 86| 0: [TypeAccess] String
# 86| 1: [Parameter] p1
# 86| 0: [TypeAccess] String
# 86| 2: [Parameter] p2
# 86| 0: [TypeAccess] String
# 86| 3: [Parameter] p3
# 86| 0: [TypeAccess] int
# 86| 4: [Parameter] p4
# 86| 0: [TypeAccess] Object
# 86| 5: [BlockStmt] { ... }
# 86| 0: [IfStmt] if (...)
# 86| 0: [EQExpr] ... == ...
# 86| 0: [AndBitwiseExpr] ... & ...
# 86| 0: [IntegerLiteral] 2
# 86| 1: [VarAccess] p3
# 86| 1: [IntegerLiteral] 0
# 86| 1: [ExprStmt] <Expr>;
# 86| 0: [AssignExpr] ...=...
# 86| 0: [VarAccess] p1
# 86| 1: [VarAccess] p0
# 86| 1: [IfStmt] if (...)
# 86| 0: [EQExpr] ... == ...
# 86| 0: [AndBitwiseExpr] ... & ...
# 86| 0: [IntegerLiteral] 4
# 86| 1: [VarAccess] p3
# 86| 1: [IntegerLiteral] 0
# 86| 1: [ExprStmt] <Expr>;
# 86| 0: [AssignExpr] ...=...
# 86| 0: [VarAccess] p2
# 86| 1: [StringLiteral] hello world
# 86| 2: [ReturnStmt] return ...
# 86| 0: [MethodAccess] f(...)
# 86| -1: [ClassInstanceExpr] new (...)
# 86| -3: [TypeAccess] Object
# 86| 0: [VarAccess] p0
# 86| 1: [VarAccess] p1
# 86| 2: [VarAccess] p2
# 90| 1: [LocalTypeDeclStmt] class ...
# 90| 0: [LocalClass]
# 90| 1: [Constructor]
# 90| 5: [BlockStmt] { ... }
# 90| 0: [SuperConstructorInvocationStmt] super(...)
# 90| 2: [Method] user
# 90| 3: [TypeAccess] Unit
# 90| 5: [BlockStmt] { ... }
# 91| 0: [ExprStmt] <Expr>;
# 91| 0: [MethodAccess] f$default(...)
# 91| -1: [ClassInstanceExpr] new (...)
# 91| -3: [TypeAccess] Object
# 91| 0: [StringLiteral] local sunk
# 1| 1: [NullLiteral] null
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 1
# 1| 4: [NullLiteral] null
# 92| 1: [ExprStmt] <Expr>;
# 92| 0: [MethodAccess] f$default(...)
# 92| -1: [ClassInstanceExpr] new (...)
# 92| -3: [TypeAccess] Object
# 92| 0: [StringLiteral] local sunk fp
# 92| 1: [StringLiteral] local sunk 2
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 3
# 1| 4: [NullLiteral] null
# 93| 2: [ExprStmt] <Expr>;
# 93| 0: [MethodAccess] f(...)
# 93| -1: [ClassInstanceExpr] new (...)
# 93| -3: [TypeAccess] Object
# 93| 0: [StringLiteral] not sunk
# 93| 1: [StringLiteral] local sunk 3
# 93| 2: [StringLiteral] not sunk
# 100| 9: [Class] TestLocalClass
# 100| 1: [Constructor] TestLocalClass
# 100| 5: [BlockStmt] { ... }
# 100| 0: [SuperConstructorInvocationStmt] super(...)
# 100| 1: [BlockStmt] { ... }
# 102| 2: [Method] enclosingFunction
# 102| 3: [TypeAccess] Unit
# 102| 5: [BlockStmt] { ... }
# 104| 0: [LocalTypeDeclStmt] class ...
# 104| 0: [LocalClass] EnclosingLocalClass
# 104| 1: [Constructor] EnclosingLocalClass
# 104| 5: [BlockStmt] { ... }
# 104| 0: [SuperConstructorInvocationStmt] super(...)
# 104| 1: [BlockStmt] { ... }
# 106| 2: [Method] f
# 106| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 106| 0: [Parameter] x
# 106| 0: [TypeAccess] String
# 106| 1: [Parameter] y
# 106| 0: [TypeAccess] String
# 106| 2: [Parameter] z
# 106| 0: [TypeAccess] String
# 106| 5: [BlockStmt] { ... }
# 107| 0: [ExprStmt] <Expr>;
# 107| 0: [MethodAccess] sink(...)
# 107| -1: [TypeAccess] TestKt
# 107| 0: [VarAccess] y
# 106| 3: [Method] f$default
# 106| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 106| 0: [Parameter] p0
# 106| 0: [TypeAccess] EnclosingLocalClass
# 106| 1: [Parameter] p1
# 106| 0: [TypeAccess] String
# 106| 2: [Parameter] p2
# 106| 0: [TypeAccess] String
# 106| 3: [Parameter] p3
# 106| 0: [TypeAccess] String
# 106| 4: [Parameter] p4
# 106| 0: [TypeAccess] int
# 106| 5: [Parameter] p5
# 106| 0: [TypeAccess] Object
# 106| 5: [BlockStmt] { ... }
# 106| 0: [IfStmt] if (...)
# 106| 0: [EQExpr] ... == ...
# 106| 0: [AndBitwiseExpr] ... & ...
# 106| 0: [IntegerLiteral] 2
# 106| 1: [VarAccess] p4
# 106| 1: [IntegerLiteral] 0
# 106| 1: [ExprStmt] <Expr>;
# 106| 0: [AssignExpr] ...=...
# 106| 0: [VarAccess] p2
# 106| 1: [VarAccess] p1
# 106| 1: [IfStmt] if (...)
# 106| 0: [EQExpr] ... == ...
# 106| 0: [AndBitwiseExpr] ... & ...
# 106| 0: [IntegerLiteral] 4
# 106| 1: [VarAccess] p4
# 106| 1: [IntegerLiteral] 0
# 106| 1: [ExprStmt] <Expr>;
# 106| 0: [AssignExpr] ...=...
# 106| 0: [VarAccess] p3
# 106| 1: [StringLiteral] hello world
# 106| 2: [ReturnStmt] return ...
# 106| 0: [MethodAccess] f(...)
# 106| -1: [VarAccess] p0
# 106| 0: [VarAccess] p1
# 106| 1: [VarAccess] p2
# 106| 2: [VarAccess] p3
# 110| 4: [Method] user
# 110| 3: [TypeAccess] Unit
# 110| 5: [BlockStmt] { ... }
# 111| 0: [ExprStmt] <Expr>;
# 111| 0: [MethodAccess] f$default(...)
# 111| -1: [TypeAccess] EnclosingLocalClass
# 111| 0: [ThisAccess] this
# 111| 1: [StringLiteral] local sunk
# 1| 2: [NullLiteral] null
# 1| 3: [NullLiteral] null
# 1| 4: [IntegerLiteral] 1
# 1| 5: [NullLiteral] null
# 112| 1: [ExprStmt] <Expr>;
# 112| 0: [MethodAccess] f$default(...)
# 112| -1: [TypeAccess] EnclosingLocalClass
# 112| 0: [ThisAccess] this
# 112| 1: [StringLiteral] local sunk fp
# 112| 2: [StringLiteral] local sunk 2
# 1| 3: [NullLiteral] null
# 1| 4: [IntegerLiteral] 3
# 1| 5: [NullLiteral] null
# 113| 2: [ExprStmt] <Expr>;
# 113| 0: [MethodAccess] f(...)
# 113| -1: [ThisAccess] this
# 113| 0: [StringLiteral] not sunk
# 113| 1: [StringLiteral] local sunk 3
# 113| 2: [StringLiteral] not sunk
# 122| 10: [Class,GenericType,ParameterizedType] TestGeneric
#-----| -2: (Generic Parameters)
# 122| 0: [TypeVariable] T
# 122| 1: [Constructor] TestGeneric
# 122| 5: [BlockStmt] { ... }
# 122| 0: [SuperConstructorInvocationStmt] super(...)
# 122| 1: [BlockStmt] { ... }
# 124| 2: [Method] f
# 124| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 124| 0: [Parameter] x
# 124| 0: [TypeAccess] T
# 124| 1: [Parameter] y
# 124| 0: [TypeAccess] T
# 124| 2: [Parameter] z
# 124| 0: [TypeAccess] T
# 124| 5: [BlockStmt] { ... }
# 125| 0: [ExprStmt] <Expr>;
# 125| 0: [MethodAccess] sink(...)
# 125| -1: [TypeAccess] TestKt
# 125| 0: [VarAccess] y
# 124| 3: [Method] f$default
# 124| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 124| 0: [Parameter] p0
# 124| 0: [TypeAccess] TestGeneric<>
# 124| 1: [Parameter] p1
# 124| 0: [TypeAccess] Object
# 124| 2: [Parameter] p2
# 124| 0: [TypeAccess] Object
# 124| 3: [Parameter] p3
# 124| 0: [TypeAccess] Object
# 124| 4: [Parameter] p4
# 124| 0: [TypeAccess] int
# 124| 5: [Parameter] p5
# 124| 0: [TypeAccess] Object
# 124| 5: [BlockStmt] { ... }
# 124| 0: [IfStmt] if (...)
# 124| 0: [EQExpr] ... == ...
# 124| 0: [AndBitwiseExpr] ... & ...
# 124| 0: [IntegerLiteral] 2
# 124| 1: [VarAccess] p4
# 124| 1: [IntegerLiteral] 0
# 124| 1: [ExprStmt] <Expr>;
# 124| 0: [AssignExpr] ...=...
# 124| 0: [VarAccess] p2
# 124| 1: [VarAccess] p1
# 124| 1: [IfStmt] if (...)
# 124| 0: [EQExpr] ... == ...
# 124| 0: [AndBitwiseExpr] ... & ...
# 124| 0: [IntegerLiteral] 4
# 124| 1: [VarAccess] p4
# 124| 1: [IntegerLiteral] 0
# 124| 1: [ExprStmt] <Expr>;
# 124| 0: [AssignExpr] ...=...
# 124| 0: [VarAccess] p3
# 124| 1: [NullLiteral] null
# 124| 2: [ReturnStmt] return ...
# 124| 0: [MethodAccess] f(...)
# 124| -1: [VarAccess] p0
# 124| 0: [VarAccess] p1
# 124| 1: [VarAccess] p2
# 124| 2: [VarAccess] p3
# 128| 4: [Method] user
# 128| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 128| 0: [Parameter] tgs
# 128| 0: [TypeAccess] TestGeneric<String>
# 128| 0: [TypeAccess] String
# 128| 1: [Parameter] tcs
# 128| 0: [TypeAccess] TestGeneric<CharSequence>
# 128| 0: [TypeAccess] CharSequence
# 128| 5: [BlockStmt] { ... }
# 129| 0: [ExprStmt] <Expr>;
# 129| 0: [MethodAccess] f$default(...)
# 129| -1: [TypeAccess] TestGeneric<>
# 129| 0: [VarAccess] tgs
# 129| 1: [StringLiteral] generic sunk
# 1| 2: [NullLiteral] null
# 1| 3: [NullLiteral] null
# 1| 4: [IntegerLiteral] 1
# 1| 5: [NullLiteral] null
# 130| 1: [ExprStmt] <Expr>;
# 130| 0: [MethodAccess] f$default(...)
# 130| -1: [TypeAccess] TestGeneric<>
# 130| 0: [VarAccess] tcs
# 130| 1: [StringLiteral] generic sunk fp
# 130| 2: [StringLiteral] generic sunk 2
# 1| 3: [NullLiteral] null
# 1| 4: [IntegerLiteral] 3
# 1| 5: [NullLiteral] null
# 131| 2: [ExprStmt] <Expr>;
# 131| 0: [MethodAccess] f(...)
# 131| -1: [VarAccess] tgs
# 131| 0: [StringLiteral] not sunk
# 131| 1: [StringLiteral] generic sunk 3
# 131| 2: [StringLiteral] not sunk
# 132| 3: [ExprStmt] <Expr>;
# 132| 0: [MethodAccess] f(...)
# 132| -1: [VarAccess] tcs
# 132| 0: [StringLiteral] not sunk
# 132| 1: [StringLiteral] generic sunk 3
# 132| 2: [StringLiteral] not sunk
# 135| 5: [Method] testReturn
# 135| 3: [TypeAccess] T
#-----| 4: (Parameters)
# 135| 0: [Parameter] t1
# 135| 0: [TypeAccess] T
# 135| 1: [Parameter] t2
# 135| 0: [TypeAccess] T
# 135| 5: [BlockStmt] { ... }
# 135| 0: [ReturnStmt] return ...
# 135| 0: [VarAccess] t1
# 135| 6: [Method] testReturn$default
# 135| 3: [TypeAccess] Object
#-----| 4: (Parameters)
# 135| 0: [Parameter] p0
# 135| 0: [TypeAccess] TestGeneric<>
# 135| 1: [Parameter] p1
# 135| 0: [TypeAccess] Object
# 135| 2: [Parameter] p2
# 135| 0: [TypeAccess] Object
# 135| 3: [Parameter] p3
# 135| 0: [TypeAccess] int
# 135| 4: [Parameter] p4
# 135| 0: [TypeAccess] Object
# 135| 5: [BlockStmt] { ... }
# 135| 0: [IfStmt] if (...)
# 135| 0: [EQExpr] ... == ...
# 135| 0: [AndBitwiseExpr] ... & ...
# 135| 0: [IntegerLiteral] 2
# 135| 1: [VarAccess] p3
# 135| 1: [IntegerLiteral] 0
# 135| 1: [ExprStmt] <Expr>;
# 135| 0: [AssignExpr] ...=...
# 135| 0: [VarAccess] p2
# 135| 1: [NullLiteral] null
# 135| 1: [ReturnStmt] return ...
# 135| 0: [MethodAccess] testReturn(...)
# 135| -1: [VarAccess] p0
# 135| 0: [VarAccess] p1
# 135| 1: [VarAccess] p2
# 137| 7: [Method] testReturnUser
# 137| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 137| 0: [Parameter] tgs
# 137| 0: [TypeAccess] TestGeneric<String>
# 137| 0: [TypeAccess] String
# 137| 5: [BlockStmt] { ... }
# 138| 0: [ExprStmt] <Expr>;
# 138| 0: [MethodAccess] sink(...)
# 138| -1: [TypeAccess] TestKt
# 138| 0: [MethodAccess] testReturn$default(...)
# 138| -1: [TypeAccess] TestGeneric<>
# 138| 0: [VarAccess] tgs
# 138| 1: [StringLiteral] sunk return value
# 1| 2: [NullLiteral] null
# 1| 3: [IntegerLiteral] 1
# 1| 4: [NullLiteral] null

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View File

@@ -0,0 +1,2 @@
shouldBeSunkButIsnt
shouldntBeSunkButIs

View File

@@ -0,0 +1,34 @@
import java
import semmle.code.java.dataflow.DataFlow
class ShouldNotBeSunk extends StringLiteral {
ShouldNotBeSunk() { this.getValue().matches("%not sunk%") }
}
class ShouldBeSunk extends StringLiteral {
ShouldBeSunk() {
this.getValue().matches("%sunk%") and
not this instanceof ShouldNotBeSunk
}
}
class Config extends DataFlow::Configuration {
Config() { this = "Config" }
override predicate isSource(DataFlow::Node n) {
n.asExpr() instanceof ShouldBeSunk or
n.asExpr() instanceof ShouldNotBeSunk
}
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
}
}
predicate isSunk(StringLiteral sl) {
exists(Config c, DataFlow::Node source | c.hasFlow(source, _) and sl = source.asExpr())
}
query predicate shouldBeSunkButIsnt(ShouldBeSunk src) { not isSunk(src) }
query predicate shouldntBeSunkButIs(ShouldNotBeSunk src) { isSunk(src) }

View File

@@ -0,0 +1,141 @@
fun sink(a: Any?) { }
class TestMember {
fun f(x: String, y: String = x, z: String = "hello world") {
sink(y)
}
fun user() {
f("member sunk")
f("member sunk fp", "member sunk 2")
f("not sunk", "member sunk 3", "not sunk")
}
}
class TestExtensionMember {
fun String.f(x: String, y: String = x, z: String = "hello world") {
sink(this)
sink(y)
}
fun user(sunk: String) {
sunk.f("extension sunk")
sunk.f("extension sunk fp", "extension sunk 2")
sunk.f("not sunk", "extension sunk 3", "not sunk")
}
}
object TestStaticMember {
@JvmStatic fun f(x: String, y: String = x, z: String = "hello world") {
sink(y)
}
fun user() {
f("static sunk")
f("static sunk fp", "static sunk 2")
f("not sunk", "static sunk 3", "not sunk")
}
}
class ExtendMe {
fun f(x: String) = x
}
class TestReceiverReferences {
fun g(x: String) = x
fun ExtendMe.test(x: String, y: String = this.f(this@TestReceiverReferences.g(x)), z: String = "hello world") {
sink(y)
}
fun user(t: ExtendMe) {
t.test("receiver refs sunk")
t.test("receiver refs sunk fp", "receiver refs sunk 2")
t.test("not sunk", "receiver refs sunk 3", "not sunk")
}
}
class TestConstructor(x: String, y: String = x, z: String = "hello world") {
init {
sink(y)
}
fun user() {
TestConstructor("constructor sunk")
TestConstructor("constructor sunk fp", "constructor sunk 2")
TestConstructor("not sunk", "constructor sunk 3", "not sunk")
}
}
class TestLocal {
fun enclosing() {
fun f(x: String, y: String = x, z: String = "hello world") {
sink(y)
}
fun user() {
f("local sunk")
f("local sunk fp", "local sunk 2")
f("not sunk", "local sunk 3", "not sunk")
}
}
}
class TestLocalClass {
fun enclosingFunction() {
class EnclosingLocalClass {
fun f(x: String, y: String = x, z: String = "hello world") {
sink(y)
}
fun user() {
f("local sunk")
f("local sunk fp", "local sunk 2")
f("not sunk", "local sunk 3", "not sunk")
}
}
}
}
class TestGeneric<T> {
fun f(x: T, y: T = x, z: T? = null) {
sink(y)
}
fun user(tgs: TestGeneric<String>, tcs: TestGeneric<CharSequence>) {
tgs.f("generic sunk")
tcs.f("generic sunk fp", "generic sunk 2")
tgs.f("not sunk", "generic sunk 3", "not sunk")
tcs.f("not sunk", "generic sunk 3", "not sunk")
}
fun testReturn(t1: T, t2: T? = null) = t1
fun testReturnUser(tgs: TestGeneric<String>) {
sink(tgs.testReturn("sunk return value"))
}
}