Remove ExtensionMethodAccess and revert all dataflow changes

This commit is contained in:
Tamas Vajk
2022-04-01 10:51:11 +02:00
committed by Ian Lynagh
parent 95cb0149a3
commit a1842f9f17
7 changed files with 26 additions and 94 deletions

View File

@@ -550,23 +550,12 @@ private module ControlFlowGraphImpl {
or
index = 0 and result = this.(RValue).getQualifier() and not result instanceof TypeAccess
or
exists(Call e | e = this and not e instanceof ExtensionMethodAccess |
exists(Call e | e = this |
index = -1 and result = e.getQualifier() and not result instanceof TypeAccess
or
result = e.getArgument(index)
)
or
exists(ExtensionMethodAccess e | e = this |
// the actual qualifier of the expression method access
index = -1 and result = e.getImplicitQualifier() and not result instanceof TypeAccess
or
// the extension receiver
index = 0 and result = e.getQualifier()
or
// the arguments
result = e.getArgument(index - 1)
)
or
exists(StringTemplateExpr e | e = this | result = e.getComponent(index))
or
index = 0 and result = this.(ClassExpr).getExpr()

View File

@@ -1984,27 +1984,6 @@ class MethodAccess extends Expr, Call, @methodaccess {
override string getAPrimaryQlClass() { result = "MethodAccess" }
}
/**
* An invocation of a Kotlin `ExtensionMethod`.
*/
class ExtensionMethodAccess extends MethodAccess {
ExtensionMethodAccess() { this.getMethod() instanceof ExtensionMethod }
/**
* Gets the implicit qualifier of this extension method access. This expression
* is the qualifier of this method access in bytecode.
*/
Expr getImplicitQualifier() { result.isNthChildOf(this, -1) }
// The syntactic qualifier of an extension method is its receiver (arg 0),
// whereas the actual arguments begin at index 1.
override Expr getQualifier() { result.isNthChildOf(this, 0) }
override Expr getAnArgument() { result = this.getArgument(_) }
override Expr getArgument(int index) { result = super.getArgument(index + 1) and index >= 0 }
}
/** A type access is a (possibly qualified) reference to a type. */
class TypeAccess extends Expr, Annotatable, @typeaccess {
/** Gets the qualifier of this type access, if any. */
@@ -2246,11 +2225,8 @@ private module Qualifier {
/** Gets the qualifier of this member access, if any. */
Expr getQualifier() {
result = this.(FieldAccess).getQualifier()
or
result = this.(MethodAccess).getQualifier() and not this instanceof ExtensionMethodAccess
or
result = this.(ExtensionMethodAccess).getImplicitQualifier()
result = this.(FieldAccess).getQualifier() or
result = this.(MethodAccess).getQualifier()
}
}

View File

@@ -108,20 +108,7 @@ class Parameter extends Element, @param, LocalScopeVariable {
pragma[noinline]
private Expr getACallArgument(int i) {
exists(Call call |
(
exists(int idx |
(
idx = i and not call instanceof ExtensionMethodAccess
or
idx = i - 1 and call instanceof ExtensionMethodAccess
) and
result = call.getArgument(idx)
)
or
i = 0 and
call instanceof ExtensionMethodAccess and
result = call.getQualifier()
) and
result = call.getArgument(i) and
call.getCallee().getSourceDeclaration().getAParameter() = this
)
}

View File

@@ -49,16 +49,10 @@ newtype TNode =
private predicate explicitInstanceArgument(Call call, Expr instarg) {
call instanceof MethodAccess and
instarg = getQualifier(call) and
instarg = call.getQualifier() and
not call.getCallee().isStatic()
}
private Expr getQualifier(MethodAccess ma) {
not ma instanceof ExtensionMethodAccess and result = ma.getQualifier()
or
result = ma.(ExtensionMethodAccess).getImplicitQualifier()
}
private predicate implicitInstanceArgument(Call call, InstanceAccessExt ia) {
ia.isImplicitMethodQualifier(call) or
ia.isImplicitThisConstructorArgument(call)
@@ -366,9 +360,6 @@ module Private {
ArgumentNode() {
exists(Argument arg | this.asExpr() = arg | not arg.isVararg())
or
// In JVM bytecode the qualifier of an extension method call is the 0th argument
exists(ExtensionMethodAccess ema | this.asExpr() = ema.getQualifier())
or
this instanceof ImplicitVarargsArray
or
this = getInstanceArgument(_)
@@ -382,20 +373,7 @@ module Private {
*/
predicate argumentOf(DataFlowCall call, int pos) {
exists(Argument arg | this.asExpr() = arg |
call.asCall() = arg.getCall() and
(
pos = arg.getPosition() and not call.asCall() instanceof ExtensionMethodAccess
or
// Shift the positions of an extension method call by 1 to make space for the qualifier at index 0.
pos = arg.getPosition() + 1 and call.asCall() instanceof ExtensionMethodAccess
)
)
or
// In JVM bytecode the qualifier of an extension method call is the 0th argument
exists(ExtensionMethodAccess ema |
call.asCall() = ema and
pos = 0 and
this.asExpr() = ema.getQualifier()
call.asCall() = arg.getCall() and pos = arg.getPosition()
)
or
call.asCall() = this.(ImplicitVarargsArray).getCall() and

View File

@@ -273,14 +273,8 @@ private module Dispatch {
not e instanceof FunctionalExpr and result = e.getType()
}
private Expr getQualifier(MethodAccess ma) {
not ma instanceof ExtensionMethodAccess and result = ma.getQualifier()
or
result = ma.(ExtensionMethodAccess).getImplicitQualifier()
}
private predicate hasQualifierType(VirtualMethodAccess ma, RefType t, boolean exact) {
exists(Expr src | src = variableTrack(getQualifier(ma)) |
exists(Expr src | src = variableTrack(ma.getQualifier()) |
// If we have a qualifier, then we track it through variable assignments
// and take the type of the assigned value.
exists(RefType srctype | srctype = getPreciseType(src) |

View File

@@ -1,10 +1,18 @@
| extensions.kt:21:17:21:38 | someClassMethod(...) | extensions.kt:21:5:21:15 | new SomeClass(...) | extensions.kt:21:34:21:36 | foo |
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:5:22:15 | new SomeClass(...) | extensions.kt:22:26:22:28 | foo |
| extensions.kt:23:17:23:30 | bothFun(...) | extensions.kt:23:5:23:15 | new SomeClass(...) | extensions.kt:23:26:23:28 | foo |
| extensions.kt:24:17:24:35 | bothFunDiffTypes(...) | extensions.kt:24:5:24:15 | new SomeClass(...) | extensions.kt:24:34:24:34 | 1 |
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:17:22:30 | ExtensionsKt | extensions.kt:22:5:22:15 | new SomeClass(...) |
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:17:22:30 | ExtensionsKt | extensions.kt:22:26:22:28 | foo |
| extensions.kt:23:17:23:30 | bothFun(...) | extensions.kt:23:17:23:30 | ExtensionsKt | extensions.kt:23:5:23:15 | new SomeClass(...) |
| extensions.kt:23:17:23:30 | bothFun(...) | extensions.kt:23:17:23:30 | ExtensionsKt | extensions.kt:23:26:23:28 | foo |
| extensions.kt:24:17:24:35 | bothFunDiffTypes(...) | extensions.kt:24:17:24:35 | ExtensionsKt | extensions.kt:24:5:24:15 | new SomeClass(...) |
| extensions.kt:24:17:24:35 | bothFunDiffTypes(...) | extensions.kt:24:17:24:35 | ExtensionsKt | extensions.kt:24:34:24:34 | 1 |
| extensions.kt:25:20:25:44 | anotherClassMethod(...) | extensions.kt:25:5:25:18 | new AnotherClass(...) | extensions.kt:25:40:25:42 | foo |
| extensions.kt:26:20:26:36 | anotherFun(...) | extensions.kt:26:5:26:18 | new AnotherClass(...) | extensions.kt:26:32:26:34 | foo |
| extensions.kt:27:20:27:33 | bothFun(...) | extensions.kt:27:5:27:18 | new AnotherClass(...) | extensions.kt:27:29:27:31 | foo |
| extensions.kt:28:20:28:42 | bothFunDiffTypes(...) | extensions.kt:28:5:28:18 | new AnotherClass(...) | extensions.kt:28:38:28:40 | foo |
| extensions.kt:29:18:29:27 | bar(...) | extensions.kt:29:6:29:15 | someString | extensions.kt:29:23:29:25 | foo |
| extensions.kt:31:18:31:32 | baz(...) | extensions.kt:31:6:31:15 | someString | extensions.kt:31:23:31:30 | bazParam |
| extensions.kt:26:20:26:36 | anotherFun(...) | extensions.kt:26:20:26:36 | ExtensionsKt | extensions.kt:26:5:26:18 | new AnotherClass(...) |
| extensions.kt:26:20:26:36 | anotherFun(...) | extensions.kt:26:20:26:36 | ExtensionsKt | extensions.kt:26:32:26:34 | foo |
| extensions.kt:27:20:27:33 | bothFun(...) | extensions.kt:27:20:27:33 | ExtensionsKt | extensions.kt:27:5:27:18 | new AnotherClass(...) |
| extensions.kt:27:20:27:33 | bothFun(...) | extensions.kt:27:20:27:33 | ExtensionsKt | extensions.kt:27:29:27:31 | foo |
| extensions.kt:28:20:28:42 | bothFunDiffTypes(...) | extensions.kt:28:20:28:42 | ExtensionsKt | extensions.kt:28:5:28:18 | new AnotherClass(...) |
| extensions.kt:28:20:28:42 | bothFunDiffTypes(...) | extensions.kt:28:20:28:42 | ExtensionsKt | extensions.kt:28:38:28:40 | foo |
| extensions.kt:29:18:29:27 | bar(...) | extensions.kt:29:18:29:27 | ExtensionsKt | extensions.kt:29:6:29:15 | someString |
| extensions.kt:29:18:29:27 | bar(...) | extensions.kt:29:18:29:27 | ExtensionsKt | extensions.kt:29:23:29:25 | foo |
| extensions.kt:31:18:31:32 | baz(...) | extensions.kt:31:18:31:32 | new (...) | extensions.kt:31:6:31:15 | someString |
| extensions.kt:31:18:31:32 | baz(...) | extensions.kt:31:18:31:32 | new (...) | extensions.kt:31:23:31:30 | bazParam |

View File

@@ -1,7 +1,7 @@
import java
// For ExtensionMethodAccess:
// * qualifier is the child with index 0 instead of -1
// * arguments are children starting from index 1 instead of 0
// For extension methods we use JVM bytecode representation:
// * the qualifier is the dispatch receiver expression, and
// * the extension receiver expression is the 0th argument.
from MethodAccess ma
select ma, ma.getQualifier(), ma.getAnArgument()