Skip to content

Commit d0cb984

Browse files
authored
Merge pull request #6 from hvitved/csharp/gvn-cfecomparison
C#: Code review suggestions
2 parents 23fbfbc + c51ddd0 commit d0cb984

File tree

1 file changed

+59
-72
lines changed

1 file changed

+59
-72
lines changed

csharp/ql/lib/semmle/code/csharp/commons/StructuralComparison.qll

Lines changed: 59 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ private class GvnKindExpr extends GvnKind, TGvnKindExpr {
1414

1515
GvnKindExpr() { this = TGvnKindExpr(kind) }
1616

17-
override string toString() { result = "Expr(" + kind.toString() + ")" }
17+
override string toString() { result = "Expr(" + kind + ")" }
1818
}
1919

2020
private class GvnKindStmt extends GvnKind, TGvnKindStmt {
2121
private int kind;
2222

2323
GvnKindStmt() { this = TGvnKindStmt(kind) }
2424

25-
override string toString() { result = "Stmt(" + kind.toString() + ")" }
25+
override string toString() { result = "Stmt(" + kind + ")" }
2626
}
2727

2828
private class GvnKindDeclaration extends GvnKind, TGvnKindDeclaration {
@@ -32,9 +32,7 @@ private class GvnKindDeclaration extends GvnKind, TGvnKindDeclaration {
3232

3333
GvnKindDeclaration() { this = TGvnKindDeclaration(kind, isTargetThis, d) }
3434

35-
override string toString() {
36-
result = "Expr(" + kind.toString() + ")," + isTargetThis + "," + d.toString()
37-
}
35+
override string toString() { result = "Expr(" + kind + ")," + isTargetThis + "," + d }
3836
}
3937

4038
/** Gets the declaration referenced by the expression `e`, if any. */
@@ -46,62 +44,56 @@ private Declaration referenceAttribute(Expr e) {
4644
result = e.(Access).getTarget()
4745
}
4846

49-
/** Returns true iff the target of the expression `e` is `this`. */
47+
/** Gets a Boolean indicating whether the target of the expression `e` is `this`. */
5048
private boolean isTargetThis(Expr e) {
5149
result = true and e.(MemberAccess).targetIsThisInstance()
5250
or
5351
result = false and not e.(MemberAccess).targetIsThisInstance()
5452
}
5553

56-
/** Gets the AST node kind of element `cfe` wrapped in the `GvnKind` type. */
57-
private GvnKind getKind(ControlFlowElement cfe) {
58-
exists(int kind |
59-
expressions(cfe, kind, _) and
60-
result = TGvnKindExpr(kind)
61-
or
62-
statements(cfe, kind) and
63-
result = TGvnKindStmt(kind)
64-
)
65-
}
66-
67-
/** The global value number of a control flow element. */
68-
abstract class Gvn extends TGvn {
54+
/**
55+
* A global value number (GVN) for a control flow element.
56+
*
57+
* GVNs are used to map control flow elements to a representation that
58+
* omits location information, that is, two elements that are structurally
59+
* equal will be mapped to the same GVN.
60+
*/
61+
class Gvn extends TGvn {
6962
/** Gets the string representation of this global value number. */
70-
abstract string toString();
63+
string toString() { none() }
7164
}
7265

7366
private class ConstantGvn extends Gvn, TConstantGvn {
7467
override string toString() { this = TConstantGvn(result) }
7568
}
7669

77-
private class GvnBase extends Gvn, TGvnBase {
70+
private class GvnNil extends Gvn, TGvnNil {
7871
private GvnKind kind;
7972

80-
GvnBase() { this = TGvnBase(kind) }
73+
GvnNil() { this = TGvnNil(kind) }
8174

8275
override string toString() { result = "(kind:" + kind + ")" }
8376
}
8477

85-
private class GvnStruct extends Gvn, TGvnStruct {
78+
private class GvnCons extends Gvn, TGvnCons {
8679
private Gvn head;
8780
private Gvn tail;
8881

89-
GvnStruct() { this = TGvnStruct(head, tail) }
82+
GvnCons() { this = TGvnCons(head, tail) }
9083

91-
override string toString() { result = "(" + head.toString() + " :: " + tail.toString() + ")" }
84+
override string toString() { result = "(" + head + " :: " + tail + ")" }
9285
}
9386

9487
pragma[noinline]
95-
private predicate gvnKindDeclaration(
96-
ControlFlowElement cfe, int kind, boolean isTargetThis, Declaration d
97-
) {
98-
isTargetThis = isTargetThis(cfe) and
99-
d = referenceAttribute(cfe) and
100-
expressions(cfe, kind, _)
88+
private predicate gvnKindDeclaration(Expr e, int kind, boolean isTargetThis, Declaration d) {
89+
isTargetThis = isTargetThis(e) and
90+
d = referenceAttribute(e) and
91+
expressions(e, kind, _)
10192
}
10293

10394
/**
10495
* Gets the `GvnKind` of the element `cfe`.
96+
*
10597
* In case `cfe` is a reference attribute, we encode the entire declaration and whether
10698
* the target is semantically equivalent to `this`.
10799
*/
@@ -111,18 +103,24 @@ private GvnKind getGvnKind(ControlFlowElement cfe) {
111103
result = TGvnKindDeclaration(kind, isTargetThis, d)
112104
)
113105
or
114-
not exists(referenceAttribute(cfe)) and
115-
result = getKind(cfe)
106+
exists(int kind |
107+
not exists(referenceAttribute(cfe)) and
108+
expressions(cfe, kind, _) and
109+
result = TGvnKindExpr(kind)
110+
or
111+
statements(cfe, kind) and
112+
result = TGvnKindStmt(kind)
113+
)
116114
}
117115

118-
private Gvn gvnConstructed(ControlFlowElement cfe, GvnKind kind, int index) {
116+
private Gvn toGvn(ControlFlowElement cfe, GvnKind kind, int index) {
119117
kind = getGvnKind(cfe) and
120-
result = TGvnBase(kind) and
118+
result = TGvnNil(kind) and
121119
index = -1
122120
or
123121
exists(Gvn head, Gvn tail |
124-
gvnConstructedStruct(cfe, kind, index, head, tail) and
125-
result = TGvnStruct(head, tail)
122+
toGvnCons(cfe, kind, index, head, tail) and
123+
result = TGvnCons(head, tail)
126124
)
127125
}
128126

@@ -147,16 +145,14 @@ private ControlFlowElement getRankedChild(ControlFlowElement cfe, int rnk) {
147145
}
148146

149147
pragma[noinline]
150-
private Gvn gvnChild(ControlFlowElement cfe, int index) {
148+
private Gvn toGvnChild(ControlFlowElement cfe, int index) {
151149
result = toGvn(getRankedChild(cfe, index))
152150
}
153151

154152
pragma[noinline]
155-
private predicate gvnConstructedStruct(
156-
ControlFlowElement cfe, GvnKind kind, int index, Gvn head, Gvn tail
157-
) {
158-
tail = gvnConstructed(cfe, kind, index - 1) and
159-
head = gvnChild(cfe, index)
153+
private predicate toGvnCons(ControlFlowElement cfe, GvnKind kind, int index, Gvn head, Gvn tail) {
154+
tail = toGvn(cfe, kind, index - 1) and
155+
head = toGvnChild(cfe, index)
160156
}
161157

162158
cached
@@ -171,30 +167,33 @@ private module Cached {
171167
)
172168
}
173169

174-
/**
175-
* Type for containing the global value number of a control flow element.
176-
* A global value number, can either be a constant, a kind or a structure containing multiple global value numbers.
177-
* The construction of the type produces a list like structure.
178-
*/
179170
cached
180171
newtype TGvn =
181172
TConstantGvn(string s) { s = any(Expr e).getValue() } or
182-
TGvnBase(GvnKind gkind) or
183-
TGvnStruct(Gvn head, Gvn tail) { gvnConstructedStruct(_, _, _, head, tail) }
173+
TGvnNil(GvnKind gkind) or
174+
TGvnCons(Gvn head, Gvn tail) { toGvnCons(_, _, _, head, tail) }
175+
176+
/** Gets the global value number of the element `cfe`. */
177+
cached
178+
Gvn toGvnCached(ControlFlowElement cfe) {
179+
result = TConstantGvn(cfe.(Expr).getValue())
180+
or
181+
not exists(cfe.(Expr).getValue()) and
182+
exists(GvnKind kind, int index |
183+
result = toGvn(cfe, kind, index - 1) and
184+
index = getNumberOfActualChildren(cfe)
185+
)
186+
}
184187
}
185188

186189
private import Cached
187190

188-
/** Gets the global value number of the element `cfe` */
189-
cached
190-
Gvn toGvn(ControlFlowElement cfe) {
191-
result = TConstantGvn(cfe.(Expr).getValue())
192-
or
193-
not exists(cfe.(Expr).getValue()) and
194-
exists(GvnKind kind, int index |
195-
result = gvnConstructed(cfe, kind, index - 1) and
196-
index = getNumberOfActualChildren(cfe)
197-
)
191+
predicate toGvn = toGvnCached/1;
192+
193+
pragma[inline]
194+
private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
195+
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
196+
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
198197
}
199198

200199
/**
@@ -227,12 +226,6 @@ abstract class StructuralComparisonConfiguration extends string {
227226
*/
228227
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
229228

230-
pragma[inline]
231-
private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
232-
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
233-
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
234-
}
235-
236229
/**
237230
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
238231
* flagged as candidates for structural equality, that is,
@@ -284,12 +277,6 @@ module Internal {
284277
*/
285278
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
286279

287-
pragma[inline]
288-
private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
289-
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
290-
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
291-
}
292-
293280
/**
294281
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
295282
* flagged as candidates for structural equality, that is,

0 commit comments

Comments
 (0)