Skip to content

Commit be9a579

Browse files
committed
C#: Remove some unnecessary TCs
1 parent b34777e commit be9a579

File tree

5 files changed

+66
-21
lines changed

5 files changed

+66
-21
lines changed

csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ private module GuardsInput implements
142142
}
143143
}
144144

145+
pragma[nomagic]
145146
predicate equalityTest(Expr eqtest, Expr left, Expr right, boolean polarity) {
146147
exists(ComparisonTest ct |
147148
ct.getExpr() = eqtest and
@@ -410,6 +411,21 @@ private predicate typePattern(PatternMatch pm, TypePatternExpr tpe, Type t) {
410411
t = pm.getExpr().getType()
411412
}
412413

414+
private predicate dereferenceableExpr(Expr e, boolean isNullableType) {
415+
exists(Type t | t = e.getType() |
416+
t instanceof NullableType and
417+
isNullableType = true
418+
or
419+
t instanceof RefType and
420+
isNullableType = false
421+
)
422+
or
423+
exists(Expr parent |
424+
dereferenceableExpr(parent, isNullableType) and
425+
e = getNullEquivParent(parent)
426+
)
427+
}
428+
413429
/**
414430
* An expression that evaluates to a value that can be dereferenced. That is,
415431
* an expression that may evaluate to `null`.
@@ -418,21 +434,12 @@ class DereferenceableExpr extends Expr {
418434
private boolean isNullableType;
419435

420436
DereferenceableExpr() {
421-
exists(Expr e, Type t |
422-
// There is currently a bug in the extractor: the type of `x?.Length` is
423-
// incorrectly `int`, while it should have been `int?`. We apply
424-
// `getNullEquivParent()` as a workaround
425-
this = getNullEquivParent*(e) and
426-
t = e.getType() and
427-
not this instanceof SwitchCaseExpr and
428-
not this instanceof PatternExpr
429-
|
430-
t instanceof NullableType and
431-
isNullableType = true
432-
or
433-
t instanceof RefType and
434-
isNullableType = false
435-
)
437+
// There is currently a bug in the extractor: the type of `x?.Length` is
438+
// incorrectly `int`, while it should have been `int?`. We apply
439+
// `getNullEquivParent()` as a workaround
440+
dereferenceableExpr(this, isNullableType) and
441+
not this instanceof SwitchCaseExpr and
442+
not this instanceof PatternExpr
436443
}
437444

438445
/** Holds if this expression has a nullable type `T?`. */

csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,15 @@ private Element getAChild(Element p) {
9696

9797
/** An AST node. */
9898
class AstNode extends Element, TAstNode {
99-
AstNode() { this = getAChild*(any(@top_level_exprorstmt_parent p | not p instanceof Attribute)) }
99+
AstNode() {
100+
exists(@top_level_exprorstmt_parent p | not p instanceof Attribute |
101+
this = p
102+
or
103+
this = getAChild(p)
104+
)
105+
or
106+
this = getAChild(any(AstNode parent))
107+
}
100108

101109
int getId() { idOf(this, result) }
102110
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ private import FlowSummaryImpl as FlowSummaryImpl
77
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
88
private import semmle.code.csharp.dataflow.internal.ExternalFlow
99
private import semmle.code.csharp.Conversion
10+
private import semmle.code.csharp.exprs.internal.Expr
1011
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
1112
private import semmle.code.csharp.ExprOrStmtParent
1213
private import semmle.code.csharp.Unification
@@ -2377,6 +2378,15 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
23772378
storeStepDelegateCall(node1, c, node2)
23782379
}
23792380

2381+
private predicate isAssignExprLValue(Expr e) {
2382+
e = any(AssignExpr ae).getLValue()
2383+
or
2384+
exists(Expr parent |
2385+
isAssignExprLValue(parent) and
2386+
e = parent.getAChildExpr()
2387+
)
2388+
}
2389+
23802390
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
23812391
ReadStepConfiguration() { this = "ReadStepConfiguration" }
23822392

@@ -2432,7 +2442,7 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
24322442
scope =
24332443
any(AssignExpr ae |
24342444
ae = defTo.(AssignableDefinitions::TupleAssignmentDefinition).getAssignment() and
2435-
e = ae.getLValue().getAChildExpr*().(TupleExpr) and
2445+
isAssignExprLValue(e.(TupleExpr)) and
24362446
exactScope = false and
24372447
isSuccessor = true
24382448
)
@@ -2488,7 +2498,7 @@ private predicate readContentStep(Node node1, Content c, Node node2) {
24882498
)
24892499
or
24902500
// item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
2491-
te = any(PatternExpr pe).getAChildExpr*() and
2501+
isPatternExprAncestor(te) and
24922502
exists(AssignableDefinitions::LocalVariableDefinition lvd |
24932503
node2.(AssignableDefinitionNode).getDefinition() = lvd and
24942504
lvd.getDeclaration() = item and

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import semmle.code.csharp.Type
2121
private import semmle.code.csharp.ExprOrStmtParent
2222
private import semmle.code.csharp.frameworks.System
2323
private import semmle.code.csharp.TypeRef
24+
private import internal.Expr
2425

2526
/**
2627
* An expression. Either an access (`Access`), a call (`Call`), an object or
@@ -64,14 +65,23 @@ class Expr extends ControlFlowElement, @expr {
6465
/** Gets the enclosing callable of this expression, if any. */
6566
override Callable getEnclosingCallable() { enclosingCallable(this, result) }
6667

68+
private predicate isExpandedAssignmentRValue() {
69+
this =
70+
any(AssignOperation op).getExpandedAssignment().getRValue().getChildExpr(0).getAChildExpr()
71+
or
72+
exists(Expr parent |
73+
parent.isExpandedAssignmentRValue() and
74+
this = parent.getAChildExpr()
75+
)
76+
}
77+
6778
/**
6879
* Holds if this expression is generated by the compiler and does not appear
6980
* explicitly in the source code.
7081
*/
7182
final predicate isImplicit() {
7283
compiler_generated(this) or
73-
this =
74-
any(AssignOperation op).getExpandedAssignment().getRValue().getChildExpr(0).getAChildExpr+()
84+
this.isExpandedAssignmentRValue()
7585
}
7686

7787
/**
@@ -1133,7 +1143,7 @@ class TupleExpr extends Expr, @tuple_expr {
11331143
/** Holds if this expression is a tuple construction. */
11341144
predicate isConstruction() {
11351145
not this = getAnAssignOrForeachChild() and
1136-
not this = any(PatternExpr pe).getAChildExpr*()
1146+
not isPatternExprAncestor(this)
11371147
}
11381148

11391149
override string getAPrimaryQlClass() { result = "TupleExpr" }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
private import csharp
2+
3+
predicate isPatternExprAncestor(Expr e) {
4+
e instanceof PatternExpr
5+
or
6+
exists(Expr parent |
7+
isPatternExprAncestor(parent) and
8+
e = parent.getAChildExpr()
9+
)
10+
}

0 commit comments

Comments
 (0)