Skip to content

Commit 716568e

Browse files
authored
Merge pull request github#5623 from hvitved/csharp/enclosing
C#: Compute enclosing callable as a transitive closure
2 parents 9820116 + 1cf30d2 commit 716568e

File tree

4 files changed

+51
-86
lines changed

4 files changed

+51
-86
lines changed

csharp/ql/src/semmle/code/csharp/Enclosing.qll

Lines changed: 0 additions & 83 deletions
This file was deleted.

csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,54 @@ private module Cached {
138138
)
139139
else expr_parent(child, i, parent)
140140
}
141+
142+
private Expr getAChildExpr(ExprOrStmtParent parent) {
143+
result = parent.getAChildExpr() or
144+
result = parent.(AssignOperation).getExpandedAssignment()
145+
}
146+
147+
private ControlFlowElement getAChild(ExprOrStmtParent parent) {
148+
result = getAChildExpr(parent)
149+
or
150+
result = parent.getAChildStmt()
151+
}
152+
153+
pragma[inline]
154+
private ControlFlowElement enclosingStart(ControlFlowElement cfe) {
155+
result = cfe
156+
or
157+
getAChild(result).(AnonymousFunctionExpr) = cfe
158+
}
159+
160+
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {
161+
child = getAChild(parent) and
162+
not child instanceof Callable
163+
}
164+
165+
/** Holds if the enclosing body of `cfe` is `body`. */
166+
cached
167+
predicate enclosingBody(ControlFlowElement cfe, ControlFlowElement body) {
168+
body = any(Callable c).getBody() and
169+
parent*(enclosingStart(cfe), body)
170+
}
171+
172+
/** Holds if the enclosing callable of `cfe` is `c`. */
173+
cached
174+
predicate enclosingCallable(ControlFlowElement cfe, Callable c) {
175+
enclosingBody(cfe, c.getBody())
176+
or
177+
parent*(enclosingStart(cfe), c.(Constructor).getInitializer())
178+
}
179+
180+
/** Holds if the enclosing statement of expression `e` is `s`. */
181+
cached
182+
predicate enclosingStmt(Expr e, Stmt s) {
183+
// Compute the enclosing statement for an expression. Note that this need
184+
// not exist, since expressions can occur in contexts where they have no
185+
// enclosing statement (examples include field initialisers, both inline
186+
// and explicit on constructor definitions, and annotation arguments).
187+
getAChildExpr+(s) = e
188+
}
141189
}
142190

143191
import Cached

csharp/ql/src/semmle/code/csharp/Stmt.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Element
88
import Location
99
import Member
1010
import exprs.Expr
11-
private import semmle.code.csharp.Enclosing::Internal
11+
private import semmle.code.csharp.ExprOrStmtParent
1212
private import semmle.code.csharp.frameworks.System
1313
private import TypeRef
1414

csharp/ql/src/semmle/code/csharp/exprs/Expr.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import semmle.code.csharp.Location
2020
import semmle.code.csharp.Stmt
2121
import semmle.code.csharp.Type
2222
private import dotnet
23-
private import semmle.code.csharp.Enclosing::Internal
23+
private import semmle.code.csharp.ExprOrStmtParent
2424
private import semmle.code.csharp.frameworks.System
2525
private import semmle.code.csharp.TypeRef
2626

@@ -55,7 +55,7 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr {
5555
final Stmt getEnclosingStmt() { enclosingStmt(this, result) }
5656

5757
/** Gets the enclosing callable of this expression, if any. */
58-
override Callable getEnclosingCallable() { exprEnclosingCallable(this, result) }
58+
override Callable getEnclosingCallable() { enclosingCallable(this, result) }
5959

6060
/**
6161
* Holds if this expression is generated by the compiler and does not appear

0 commit comments

Comments
 (0)