Skip to content

Commit 327757d

Browse files
committed
C#: Update the child indices for assignments, update Assign classes to extend OperatorCall and add AssignOperation classes.
1 parent b426c6f commit 327757d

File tree

7 files changed

+163
-59
lines changed

7 files changed

+163
-59
lines changed

csharp/ql/lib/semmle/code/csharp/Property.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ class Property extends DeclarationWithGetSetAccessors, @property {
226226
* }
227227
* ```
228228
*/
229-
Expr getInitializer() { result = this.getChildExpr(1).getChildExpr(0) }
229+
Expr getInitializer() { result = this.getChildExpr(1).getChildExpr(1) }
230230

231231
/**
232232
* Holds if this property has an initial value. For example, the initial

csharp/ql/lib/semmle/code/csharp/Variable.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent
408408
* }
409409
* ```
410410
*/
411-
final override Expr getInitializer() { result = this.getChildExpr(0).getChildExpr(0) }
411+
final override Expr getInitializer() { result = this.getChildExpr(0).getChildExpr(1) }
412412

413413
/**
414414
* Holds if this field has an initial value. For example, the initial

csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,14 @@ class Assignment extends BinaryOperation, @assign_expr {
1717
implies
1818
// Same as `this.(LocalVariableDeclExpr).hasInitializer()` but avoids
1919
// negative recursion
20-
expr_parent(_, 0, this)
20+
expr_parent(_, 1, this)
2121
}
2222

23-
override Expr getLeftOperand() { result = this.getChild(1) }
24-
25-
override Expr getRightOperand() { result = this.getChild(0) }
26-
2723
/** Gets the left operand of this assignment. */
28-
Expr getLValue() { result = this.getChild(1) }
24+
Expr getLValue() { result = this.getLeftOperand() }
2925

3026
/** Gets the right operand of this assignment. */
31-
Expr getRValue() { result = this.getChild(0) }
27+
Expr getRValue() { result = this.getRightOperand() }
3228

3329
/** Gets the variable being assigned to, if any. */
3430
Variable getTargetVariable() { result.getAnAccess() = this.getLValue() }
@@ -64,34 +60,30 @@ class AssignExpr extends Assignment, @simple_assign_expr {
6460

6561
/**
6662
* An assignment operation. Either an arithmetic assignment operation
67-
* (`AssignArithmeticOperation`), a bitwise assignment operation
68-
* (`AssignBitwiseOperation`), or an event assignment (`AddOrRemoveEventExpr`).
63+
* (`AssignArithmeticOperation`), a bitwise assignment operation or
64+
* (`AssignBitwiseOperation`), an event assignment (`AddOrRemoveEventExpr`), or
65+
* a null-coalescing assignment (`AssignCoalesceExpr`).
6966
*/
7067
class AssignOperation extends Assignment, @assign_op_expr {
7168
override string getOperator() { none() }
7269

7370
/**
74-
* Gets the expanded version of this assignment operation, if any.
75-
*
76-
* For example, if this assignment operation is `x += y` then
77-
* the expanded assignment is `x = x + y`.
78-
*
79-
* If an expanded version exists, then it is used in the control
80-
* flow graph.
71+
* Expanded versions of compound assignments are no longer extracted.
8172
*/
82-
AssignExpr getExpandedAssignment() { expr_parent(result, 2, this) }
73+
deprecated AssignExpr getExpandedAssignment() { none() }
8374

8475
/**
85-
* Holds if this assignment operation has an expanded version.
86-
*
87-
* For example, if this assignment operation is `x += y` then
88-
* it has the expanded version `x = x + y`.
89-
*
90-
* If an expanded version exists, then it is used in the control
91-
* flow graph.
76+
* Expanded versions of compound assignments are no longer extracted.
9277
*/
93-
predicate hasExpandedAssignment() { exists(this.getExpandedAssignment()) }
78+
deprecated predicate hasExpandedAssignment() { none() }
79+
80+
override string toString() { result = "... " + this.getOperator() + " ..." }
81+
}
9482

83+
/**
84+
* An assignment operation that corresponds to an operator call, for example `x += y` corresponds to `x = x + y`.
85+
*/
86+
class AssignCallOperation extends AssignOperation, OperatorCall, @assign_op_call_expr {
9587
override string toString() { result = "... " + this.getOperator() + " ..." }
9688
}
9789

@@ -102,7 +94,7 @@ class AssignOperation extends Assignment, @assign_op_expr {
10294
* operation (`AssignDivExpr`), or a remainder assignment operation
10395
* (`AssignRemExpr`).
10496
*/
105-
class AssignArithmeticOperation extends AssignOperation, @assign_arith_expr { }
97+
class AssignArithmeticOperation extends AssignCallOperation, @assign_arith_expr { }
10698

10799
/**
108100
* An addition assignment operation, for example `x += y`.
@@ -158,7 +150,7 @@ class AssignRemExpr extends AssignArithmeticOperation, @assign_rem_expr {
158150
* operation (`AssignRightShiftExpr`), or an unsigned right-shift assignment
159151
* operation (`AssignUnsignedRightShiftExpr`).
160152
*/
161-
class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { }
153+
class AssignBitwiseOperation extends AssignCallOperation, @assign_bitwise_expr { }
162154

163155
/**
164156
* A bitwise-and assignment operation, for example `x &= y`.
@@ -208,12 +200,17 @@ class AssignRightShiftExpr extends AssignBitwiseOperation, @assign_rshift_expr {
208200
/**
209201
* An unsigned right-shift assignment operation, for example `x >>>= y`.
210202
*/
211-
class AssignUnsighedRightShiftExpr extends AssignBitwiseOperation, @assign_urshift_expr {
203+
class AssignUnsignedRightShiftExpr extends AssignBitwiseOperation, @assign_urshift_expr {
212204
override string getOperator() { result = ">>>=" }
213205

214-
override string getAPrimaryQlClass() { result = "AssignUnsighedRightShiftExpr" }
206+
override string getAPrimaryQlClass() { result = "AssignUnsignedRightShiftExpr" }
215207
}
216208

209+
/**
210+
* DEPRECATED: Use `AssignUnsignedRightShiftExpr` instead.
211+
*/
212+
deprecated class AssignUnsighedRightShiftExpr = AssignUnsignedRightShiftExpr;
213+
217214
/**
218215
* An event assignment. Either an event addition (`AddEventExpr`) or an event
219216
* removal (`RemoveEventExpr`).
@@ -222,9 +219,9 @@ class AddOrRemoveEventExpr extends AssignOperation, @assign_event_expr {
222219
/** Gets the event targeted by this event assignment. */
223220
Event getTarget() { result = this.getLValue().getTarget() }
224221

225-
override EventAccess getLValue() { result = this.getChild(1) }
222+
override EventAccess getLValue() { result = this.getChild(0) }
226223

227-
override Expr getRValue() { result = this.getChild(0) }
224+
override EventAccess getLeftOperand() { result = this.getChild(0) }
228225
}
229226

230227
/**

csharp/ql/lib/semmle/code/csharp/exprs/Call.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,12 +493,16 @@ class ConstructorInitializer extends Call, @constructor_init_expr {
493493
* }
494494
* ```
495495
*/
496-
class OperatorCall extends Call, LateBindableExpr, @operator_invocation_expr {
496+
class OperatorCall extends Call, LateBindableExpr, @op_invoke_expr {
497497
override Operator getTarget() { expr_call(this, result) }
498498

499499
override Operator getARuntimeTarget() { result = Call.super.getARuntimeTarget() }
500500

501-
override string toString() { result = "call to operator " + this.getTarget().getName() }
501+
override string toString() {
502+
if this instanceof DynamicOperatorCall
503+
then result = "dynamic call to operator " + this.getLateBoundTargetName()
504+
else result = "call to operator " + this.getTarget().getName()
505+
}
502506

503507
override string getAPrimaryQlClass() { result = "OperatorCall" }
504508
}

csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,7 @@ class DynamicMethodCall extends DynamicExpr, MethodCall {
9696
* Unlike an ordinary call to a user-defined operator (`OperatorCall`), the
9797
* target operator may not be known at compile-time (as in the example above).
9898
*/
99-
class DynamicOperatorCall extends DynamicExpr, OperatorCall {
100-
override string toString() {
101-
result = "dynamic call to operator " + this.getLateBoundTargetName()
102-
}
103-
104-
override string getAPrimaryQlClass() { result = "DynamicOperatorCall" }
105-
}
99+
class DynamicOperatorCall extends DynamicExpr, OperatorCall { }
106100

107101
/**
108102
* A call to a user-defined mutator operator where the operand is a `dynamic`

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Creation
1414
import Dynamic
1515
import Literal
1616
import LogicalOperation
17+
import Operation
1718
import semmle.code.csharp.controlflow.ControlFlowElement
1819
import semmle.code.csharp.Location
1920
import semmle.code.csharp.Stmt
@@ -65,25 +66,11 @@ class Expr extends ControlFlowElement, @expr {
6566
/** Gets the enclosing callable of this expression, if any. */
6667
override Callable getEnclosingCallable() { enclosingCallable(this, result) }
6768

68-
pragma[nomagic]
69-
private predicate isExpandedAssignmentRValueDescendant() {
70-
this =
71-
any(AssignOperation op).getExpandedAssignment().getRValue().getChildExpr(0).getAChildExpr()
72-
or
73-
exists(Expr parent |
74-
parent.isExpandedAssignmentRValueDescendant() and
75-
this = parent.getAChildExpr()
76-
)
77-
}
78-
7969
/**
8070
* Holds if this expression is generated by the compiler and does not appear
8171
* explicitly in the source code.
8272
*/
83-
final predicate isImplicit() {
84-
compiler_generated(this) or
85-
this.isExpandedAssignmentRValueDescendant()
86-
}
73+
final predicate isImplicit() { compiler_generated(this) }
8774

8875
/**
8976
* Gets an expression that is the result of stripping (recursively) all
@@ -168,7 +155,7 @@ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr {
168155
string getName() { result = this.getVariable().getName() }
169156

170157
/** Gets the initializer expression of this local variable declaration, if any. */
171-
Expr getInitializer() { result = this.getChild(0) }
158+
Expr getInitializer() { result = this.getChild(1) }
172159

173160
/** Holds if this local variable declaration has an initializer. */
174161
predicate hasInitializer() { exists(this.getInitializer()) }
@@ -188,7 +175,7 @@ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr {
188175

189176
/** Gets the variable access used in this declaration, if any. */
190177
LocalVariableAccess getAccess() {
191-
result = this.getChild(1) or
178+
result = this.getChild(0) or
192179
result = this // `out` argument
193180
}
194181

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* Provides classes for operations that also have compound assignment forms.
3+
*/
4+
5+
import Expr
6+
7+
/** A binary operation that involves a null-coalescing operation. */
8+
abstract private class NullCoalescingOperationImpl extends BinaryOperation { }
9+
10+
final class NullCoalescingOperation = NullCoalescingOperationImpl;
11+
12+
private class AddNullCoalescingExpr extends NullCoalescingOperationImpl instanceof NullCoalescingExpr
13+
{ }
14+
15+
private class AddAssignCoalesceExpr extends NullCoalescingOperationImpl instanceof AssignCoalesceExpr
16+
{ }
17+
18+
/** A binary operations that involves an addition operation. */
19+
abstract private class AddOperationImpl extends BinaryOperation { }
20+
21+
final class AddOperation = AddOperationImpl;
22+
23+
private class AddAddExpr extends AddOperationImpl instanceof AddExpr { }
24+
25+
private class AddAssignExpr extends AddOperationImpl instanceof AssignAddExpr { }
26+
27+
/** A binary operation that involves a subtraction operation. */
28+
abstract private class SubOperationImpl extends BinaryOperation { }
29+
30+
final class SubOperation = SubOperationImpl;
31+
32+
private class AddSubExpr extends SubOperationImpl instanceof SubExpr { }
33+
34+
private class AddSubAssignExpr extends SubOperationImpl instanceof AssignSubExpr { }
35+
36+
/** A binary operation that involves a multiplication operation. */
37+
abstract private class MulOperationImpl extends BinaryOperation { }
38+
39+
final class MulOperation = MulOperationImpl;
40+
41+
private class AddMulExpr extends MulOperationImpl instanceof MulExpr { }
42+
43+
private class AddMulAssignExpr extends MulOperationImpl instanceof AssignMulExpr { }
44+
45+
/** A binary operation that involves a division operation. */
46+
abstract private class DivOperationImpl extends BinaryOperation {
47+
/** Gets the denominator of this division operation. */
48+
Expr getDenominator() { result = this.getRightOperand() }
49+
}
50+
51+
final class DivOperation = DivOperationImpl;
52+
53+
private class AddDivExpr extends DivOperationImpl instanceof DivExpr { }
54+
55+
private class AddDivAssignExpr extends DivOperationImpl instanceof AssignDivExpr { }
56+
57+
/** A binary operation that involves a remainder operation. */
58+
abstract private class RemOperationImpl extends BinaryOperation { }
59+
60+
final class RemOperation = RemOperationImpl;
61+
62+
private class AddRemExpr extends RemOperationImpl instanceof RemExpr { }
63+
64+
private class AddRemAssignExpr extends RemOperationImpl instanceof AssignRemExpr { }
65+
66+
/** A binary operation that involves a bitwise AND operation. */
67+
abstract private class BitwiseAndOperationImpl extends BinaryOperation { }
68+
69+
final class BitwiseAndOperation = BitwiseAndOperationImpl;
70+
71+
private class AddBitwiseAndExpr extends BitwiseAndOperationImpl instanceof BitwiseAndExpr { }
72+
73+
private class AddAssignBitwiseAndExpr extends BitwiseAndOperationImpl instanceof AssignAndExpr { }
74+
75+
/** A binary operation that involves a bitwise OR operation. */
76+
abstract private class BitwiseOrOperationImpl extends BinaryOperation { }
77+
78+
final class BitwiseOrOperation = BitwiseOrOperationImpl;
79+
80+
private class AddBitwiseOrExpr extends BitwiseOrOperationImpl instanceof BitwiseOrExpr { }
81+
82+
private class AddAssignBitwiseOrExpr extends BitwiseOrOperationImpl instanceof AssignOrExpr { }
83+
84+
/** A binary operation that involves a bitwise XOR operation. */
85+
abstract private class BitwiseXorOperationImpl extends BinaryOperation { }
86+
87+
final class BitwiseXorOperation = BitwiseXorOperationImpl;
88+
89+
private class AddBitwiseXorExpr extends BitwiseXorOperationImpl instanceof BitwiseXorExpr { }
90+
91+
private class AddAssignBitwiseXorExpr extends BitwiseXorOperationImpl instanceof AssignXorExpr { }
92+
93+
/** A binary operation that involves a left shift operation. */
94+
abstract private class LeftShiftOperationImpl extends BinaryOperation { }
95+
96+
final class LeftShiftOperation = LeftShiftOperationImpl;
97+
98+
private class AddLeftShiftExpr extends LeftShiftOperationImpl instanceof LeftShiftExpr { }
99+
100+
private class AddAssignLeftShiftExpr extends LeftShiftOperationImpl instanceof AssignLeftShiftExpr {
101+
}
102+
103+
/** A binary operation that involves a right shift operation. */
104+
abstract private class RightShiftOperationImpl extends BinaryOperation { }
105+
106+
final class RightShiftOperation = RightShiftOperationImpl;
107+
108+
private class AddRightShiftExpr extends RightShiftOperationImpl instanceof RightShiftExpr { }
109+
110+
private class AddAssignRightShiftExpr extends RightShiftOperationImpl instanceof AssignRightShiftExpr
111+
{ }
112+
113+
/** A binary operation that involves a unsigned right shift operation. */
114+
abstract private class UnsignedRightShiftOperationImpl extends BinaryOperation { }
115+
116+
final class UnsignedRightShiftOperation = UnsignedRightShiftOperationImpl;
117+
118+
private class AddUnsignedRightShiftExpr extends UnsignedRightShiftOperationImpl instanceof UnsignedRightShiftExpr
119+
{ }
120+
121+
private class AddAssignUnsignedRightShiftExpr extends UnsignedRightShiftOperationImpl instanceof AssignUnsignedRightShiftExpr
122+
{ }

0 commit comments

Comments
 (0)