C#: Extend (Annotated)ExitNode to also cover static fields

This commit is contained in:
Tom Hvitved
2021-11-15 17:04:11 +01:00
parent 474c808373
commit a89be2e3f8
5 changed files with 53 additions and 15 deletions

View File

@@ -268,13 +268,13 @@ module ControlFlow {
/** A node for a callable exit point, annotated with the type of exit. */
class AnnotatedExitNode extends Node, TAnnotatedExitNode {
private Callable c;
private CfgScope scope;
private boolean normal;
AnnotatedExitNode() { this = TAnnotatedExitNode(c, normal) }
AnnotatedExitNode() { this = TAnnotatedExitNode(scope, normal) }
/** Gets the callable that this exit applies to. */
Callable getCallable() { result = c }
CfgScope getCallable() { result = scope }
/** Holds if this node represents a normal exit. */
predicate isNormal() { normal = true }
@@ -285,7 +285,7 @@ module ControlFlow {
override Callable getEnclosingCallable() { result = this.getCallable() }
override Location getLocation() { result = this.getCallable().getLocation() }
override Location getLocation() { result = scope.getLocation() }
override string toString() {
exists(string s |
@@ -293,23 +293,27 @@ module ControlFlow {
or
normal = false and s = "abnormal"
|
result = "exit " + this.getCallable() + " (" + s + ")"
result = "exit " + scope + " (" + s + ")"
)
}
}
/** A node for a callable exit point. */
class ExitNode extends Node, TExitNode {
private CfgScope scope;
ExitNode() { this = TExitNode(scope) }
/** Gets the callable that this exit applies to. */
Callable getCallable() { this = TExitNode(result) }
Callable getCallable() { result = scope }
override BasicBlocks::ExitBlock getBasicBlock() { result = Node.super.getBasicBlock() }
override Callable getEnclosingCallable() { result = this.getCallable() }
override Location getLocation() { result = this.getCallable().getLocation() }
override Location getLocation() { result = scope.getLocation() }
override string toString() { result = "exit " + this.getCallable().toString() }
override string toString() { result = "exit " + scope }
}
/**

View File

@@ -97,6 +97,24 @@ module ControlFlowTree {
predicate idOf(Range_ x, int y) = equivalenceRelation(id/2)(x, y)
}
/**
* The `expr_parent_top_level_adjusted()` relation restricted to exclude relations
* between properties and their getters' expression bodies in properties such as
* `int P => 0`.
*
* This is in order to only associate the expression body with one CFG scope, namely
* the getter (and not the declaration itself).
*/
private predicate expr_parent_top_level_adjusted2(
Expr child, int i, @top_level_exprorstmt_parent parent
) {
expr_parent_top_level_adjusted(child, i, parent) and
not exists(Getter g |
g.getDeclaration() = parent and
i = 0
)
}
/** Holds if `first` is first executed when entering `scope`. */
predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
scope =
@@ -109,17 +127,23 @@ predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
else first(c.getBody(), first)
)
or
expr_parent_top_level_adjusted(any(Expr e | first(e, first)), _, scope) and
expr_parent_top_level_adjusted2(any(Expr e | first(e, first)), _, scope) and
not scope instanceof Callable
}
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
predicate scopeLast(Callable scope, ControlFlowElement last, Completion c) {
last(scope.getBody(), last, c) and
not c instanceof GotoCompletion
predicate scopeLast(CfgScope scope, ControlFlowElement last, Completion c) {
scope =
any(Callable callable |
last(callable.getBody(), last, c) and
not c instanceof GotoCompletion
or
last(InitializerSplitting::lastConstructorInitializer(scope, _), last, c) and
not callable.hasBody()
)
or
last(InitializerSplitting::lastConstructorInitializer(scope, _), last, c) and
not scope.hasBody()
expr_parent_top_level_adjusted2(any(Expr e | last(e, last, c)), _, scope) and
not scope instanceof Callable
}
private class ConstructorTree extends ControlFlowTree, Constructor {

View File

@@ -677,7 +677,7 @@
| Initializers.cs:8:5:8:16 | enter Initializers | Initializers.cs:8:5:8:16 | exit Initializers | 16 |
| Initializers.cs:10:5:10:16 | enter Initializers | Initializers.cs:10:5:10:16 | exit Initializers | 16 |
| Initializers.cs:12:10:12:10 | enter M | Initializers.cs:12:10:12:10 | exit M | 22 |
| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:16:18:20 | ... = ... | 3 |
| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:16:18:16 | exit H | 5 |
| Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:20:11:20:23 | exit NoConstructor | 9 |
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | exit Sub | 12 |
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | exit Sub | 9 |

View File

@@ -2505,6 +2505,8 @@ dominance
| Initializers.cs:15:42:15:61 | object creation of type Initializers | Initializers.cs:15:37:15:63 | { ..., ... } |
| Initializers.cs:15:59:15:60 | "" | Initializers.cs:15:42:15:61 | object creation of type Initializers |
| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:20:18:20 | 1 |
| Initializers.cs:18:16:18:16 | exit H (normal) | Initializers.cs:18:16:18:16 | exit H |
| Initializers.cs:18:16:18:20 | ... = ... | Initializers.cs:18:16:18:16 | exit H (normal) |
| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:20 | ... = ... |
| Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:22:23:22:23 | this access |
| Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | Initializers.cs:20:11:20:23 | exit NoConstructor |
@@ -6631,6 +6633,8 @@ postDominance
| Initializers.cs:15:39:15:39 | access to local variable i | Initializers.cs:15:18:15:63 | array creation of type Initializers[] |
| Initializers.cs:15:42:15:61 | object creation of type Initializers | Initializers.cs:15:59:15:60 | "" |
| Initializers.cs:15:59:15:60 | "" | Initializers.cs:15:39:15:39 | access to local variable i |
| Initializers.cs:18:16:18:16 | exit H | Initializers.cs:18:16:18:16 | exit H (normal) |
| Initializers.cs:18:16:18:16 | exit H (normal) | Initializers.cs:18:16:18:20 | ... = ... |
| Initializers.cs:18:16:18:20 | ... = ... | Initializers.cs:18:20:18:20 | 1 |
| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:16 | enter H |
| Initializers.cs:20:11:20:23 | exit NoConstructor | Initializers.cs:20:11:20:23 | exit NoConstructor (normal) |

View File

@@ -8252,6 +8252,12 @@ Initializers.cs:
#-----| -> 1
# 18| ... = ...
#-----| -> exit H (normal)
# 18| exit H
# 18| exit H (normal)
#-----| -> exit H
# 18| 1
#-----| -> ... = ...