forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathExprOrStmtParent.qll
More file actions
161 lines (140 loc) · 4.66 KB
/
ExprOrStmtParent.qll
File metadata and controls
161 lines (140 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/**
* INTERNAL: Do not use.
*
* Provides logic for calculating the child relation on expressions and statements.
*/
import csharp
private import internal.Location
/**
* INTERNAL: Do not use.
*
* An element that can have a child statement or expression.
*/
class ExprOrStmtParent extends Element, @exprorstmt_parent {
override ControlFlowElement getChild(int i) {
result = this.getChildExpr(i) or
result = this.getChildStmt(i)
}
/** Gets the `i`th child expression of this element (zero-based). */
final Expr getChildExpr(int i) {
expr_parent(result, i, this) or
expr_parent_top_level_adjusted(result, i, this)
}
/** Gets a child expression of this element, if any. */
final Expr getAChildExpr() { result = this.getChildExpr(_) }
/** Gets the `i`th child statement of this element (zero-based). */
final Stmt getChildStmt(int i) {
stmt_parent(result, i, this) or
stmt_parent_top_level(result, i, this)
}
/** Gets a child statement of this element, if any. */
final Stmt getAChildStmt() { result = this.getChildStmt(_) }
}
/**
* INTERNAL: Do not use.
*
* An element that can have a child top-level expression.
*/
class TopLevelExprParent extends ExprOrStmtParent, @top_level_expr_parent {
final override Expr getChild(int i) { result = this.getChildExpr(i) }
}
/** INTERNAL: Do not use. */
Expr getExpressionBody(Callable c) {
result = c.getAChildExpr() and
not result = c.(Constructor).getInitializer() and
not result = c.(Constructor).getObjectInitializerCall()
}
/** INTERNAL: Do not use. */
BlockStmt getStatementBody(Callable c) { result = c.getAChildStmt() }
private ControlFlowElement getBody(Callable c) {
result = getExpressionBody(c) or
result = getStatementBody(c)
}
pragma[nomagic]
private predicate hasNoSourceLocation(Element e) { not exists(getASourceLocation(e)) }
pragma[nomagic]
private Location getFirstSourceLocation(Element e) {
result =
min(Location l, string filepath, int startline, int startcolumn, int endline, int endcolumn |
l = getASourceLocation(e) and
l.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
l order by filepath, startline, startcolumn, endline, endcolumn
)
}
cached
private module Cached {
cached
Location bestLocation(Element e) {
(
if e.(Modifiable).isPartial() or e instanceof Namespace
then result = getASourceLocation(e)
else result = getFirstSourceLocation(e)
)
or
hasNoSourceLocation(e) and
result =
min(Location l, string filepath |
l = e.getALocation() and
l.hasLocationInfo(filepath, _, _, _, _)
|
l order by filepath
)
or
not exists(e.getALocation()) and
result instanceof EmptyLocation
}
/**
* INTERNAL: Do not use.
*
* The `expr_parent_top_level()` relation extended to include a relation
* between getters and expression bodies in properties such as `int P => 0`.
*/
cached
predicate expr_parent_top_level_adjusted(Expr child, int i, @top_level_exprorstmt_parent parent) {
expr_parent_top_level(child, i, parent)
or
parent = any(Getter g | expr_parent_top_level(child, i, g.getDeclaration())) and
i = 0
}
private Expr getAChildExpr(ExprOrStmtParent parent) {
result = parent.getAChildExpr() and
not result = parent.(DeclarationWithGetSetAccessors).getExpressionBody()
}
private ControlFlowElement getAChild(ExprOrStmtParent parent) {
result = getAChildExpr(parent)
or
result = parent.getAChildStmt()
}
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {
child = getAChild(parent) and
not child = getBody(_)
}
/** Holds if the enclosing body of `cfe` is `body`. */
cached
predicate enclosingBody(ControlFlowElement cfe, ControlFlowElement body) {
body = getBody(_) and
parent*(cfe, body)
}
/** Holds if the enclosing callable of `cfe` is `c`. */
cached
predicate enclosingCallable(ControlFlowElement cfe, Callable c) {
enclosingBody(cfe, getBody(c))
or
parent*(cfe, c.(Constructor).getInitializer())
or
parent*(cfe, c.(Constructor).getObjectInitializerCall())
or
parent*(cfe, any(AssignExpr init | c.(ObjectInitMethod).initializes(init)))
}
/** Holds if the enclosing statement of expression `e` is `s`. */
cached
predicate enclosingStmt(Expr e, Stmt s) {
// Compute the enclosing statement for an expression. Note that this need
// not exist, since expressions can occur in contexts where they have no
// enclosing statement (examples include field initialisers, both inline
// and explicit on constructor definitions, and annotation arguments).
getAChildExpr+(s) = e
}
}
import Cached