Merge pull request #15296 from michaelnebel/csharp/getruntimeargument

C#: Improve getRuntimeArgumentForParameter to consider named arguments.
This commit is contained in:
Michael Nebel
2024-01-12 15:57:17 +01:00
committed by GitHub
6 changed files with 75 additions and 20 deletions

View File

@@ -60,18 +60,17 @@ class Call extends DotNet::Call, Expr, @call {
*/
cached
override Expr getArgumentForParameter(DotNet::Parameter p) {
// Appears in the positional part of the call
result = this.getImplicitArgument(p)
or
// Appears in the named part of the call
this.getTarget().getAParameter() = p and
(
// Appears in the positional part of the call
result = this.getImplicitArgument(p)
or
// Appears in the named part of the call
result = this.getExplicitArgument(p.getName())
)
result = this.getExplicitArgument(p.getName())
}
pragma[noinline]
private Expr getImplicitArgument(DotNet::Parameter p) {
this.getTarget().getAParameter() = p and
not exists(result.getExplicitArgumentName()) and
(
p.(Parameter).isParams() and
@@ -183,24 +182,38 @@ class Call extends DotNet::Call, Expr, @call {
* Gets the argument that corresponds to parameter `p` of a potential
* run-time target of this call.
*
* Does not consider
* - default arguments,
* - named arguments.
* This takes into account both positional and named arguments, but does not
* consider default arguments.
*/
cached
Expr getRuntimeArgumentForParameter(Parameter p) {
exists(Callable c |
c = this.getARuntimeTarget() and
p = c.getAParameter() and
(
p.isParams() and
result = this.getRuntimeArgument(any(int i | i >= p.getPosition()))
or
not p.isParams() and
result = this.getRuntimeArgument(p.getPosition())
)
// Appears in the positional part of the call
result = this.getImplicitRuntimeArgument(p)
or
// Appears in the named part of the call
this.getARuntimeTarget().getAParameter() = p and
result = this.getExplicitRuntimeArgument(p.getName())
}
pragma[noinline]
private Expr getImplicitRuntimeArgument(Parameter p) {
this.getARuntimeTarget().getAParameter() = p and
not exists(result.getExplicitArgumentName()) and
(
p.isParams() and
result = this.getRuntimeArgument(any(int i | i >= p.getPosition()))
or
not p.isParams() and
result = this.getRuntimeArgument(p.getPosition())
)
}
pragma[nomagic]
private Expr getExplicitRuntimeArgument(string name) {
result = this.getARuntimeArgument() and
result.getExplicitArgumentName() = name
}
/**
* Gets the argument that corresponds to a parameter named `name` of a potential
* run-time target of this call.

View File

@@ -421,3 +421,30 @@ lambdas.cs:
# 17| 0: [IntLiteral] 7
# 17| 1: [IntLiteral] 8
# 17| 2: [IntLiteral] 9
# 20| 6: [DelegateType] MyDelegate
#-----| 2: (Parameters)
# 20| 0: [Parameter] x
# 20| -1: [TypeMention] int
# 20| 1: [Parameter] y
# 20| -1: [TypeMention] int
# 22| 7: [Method] M2
# 22| -1: [TypeMention] Void
# 23| 4: [BlockStmt] {...}
# 24| 0: [LocalVariableDeclStmt] ... ...;
# 24| 0: [LocalVariableDeclAndInitExpr] MyDelegate sum = ...
# 24| -1: [TypeMention] MyDelegate
# 24| 0: [LocalVariableAccess] access to local variable sum
# 24| 1: [LambdaExpr] (...) => ...
#-----| 2: (Parameters)
# 24| 0: [Parameter] x
# 24| -1: [TypeMention] int
# 24| 1: [Parameter] y
# 24| -1: [TypeMention] int
# 24| 4: [AddExpr] ... + ...
# 24| 0: [ParameterAccess] access to parameter x
# 24| 1: [ParameterAccess] access to parameter y
# 25| 1: [ExprStmt] ...;
# 25| 0: [DelegateCall] delegate call
# 25| -1: [LocalVariableAccess] access to local variable sum
# 25| 0: [IntLiteral] 4
# 25| 1: [IntLiteral] 5

View File

@@ -11,3 +11,5 @@
| arguments.cs:70:36:70:36 | 0 | x |
| arguments.cs:78:18:78:21 | access to parameter args | args |
| arguments.cs:78:27:78:27 | 0 | o |
| lambdas.cs:25:16:25:16 | 4 | y |
| lambdas.cs:25:22:25:22 | 5 | x |

View File

@@ -79,3 +79,5 @@
| lambdas.cs:17:12:17:12 | 7 | 0 |
| lambdas.cs:17:15:17:15 | 8 | 0 |
| lambdas.cs:17:18:17:18 | 9 | 0 |
| lambdas.cs:25:16:25:16 | 4 | 0 |
| lambdas.cs:25:22:25:22 | 5 | 0 |

View File

@@ -7,3 +7,5 @@
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:12:17:12 | 7 |
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:15:17:15 | 8 |
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:18:17:18 | 9 |
| lambdas.cs:25:9:25:23 | delegate call | lambdas.cs:24:31:24:31 | x | lambdas.cs:25:22:25:22 | 5 |
| lambdas.cs:25:9:25:23 | delegate call | lambdas.cs:24:38:24:38 | y | lambdas.cs:25:16:25:16 | 4 |

View File

@@ -16,4 +16,13 @@ class LambdaArgumentsTest
l3();
l3(7, 8, 9);
}
delegate int MyDelegate(int x, int y);
void M2()
{
MyDelegate sum = (int x, int y) => x + y;
sum(y: 4, x: 5);
}
}