Skip to content

Commit aa7a730

Browse files
committed
C#: Remove some unnecessary TCs
1 parent 600f585 commit aa7a730

File tree

5 files changed

+72
-21
lines changed

5 files changed

+72
-21
lines changed

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

Lines changed: 23 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,22 @@ private predicate typePattern(PatternMatch pm, TypePatternExpr tpe, Type t) {
410411
t = pm.getExpr().getType()
411412
}
412413

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

420437
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-
)
438+
// There is currently a bug in the extractor: the type of `x?.Length` is
439+
// incorrectly `int`, while it should have been `int?`. We apply
440+
// `getNullEquivParent()` as a workaround
441+
dereferenceableExpr(this, isNullableType) and
442+
not this instanceof SwitchCaseExpr and
443+
not this instanceof PatternExpr
436444
}
437445

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

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,19 @@ private Element getAChild(Element p) {
9494
result = p.(AssignOperation).getExpandedAssignment()
9595
}
9696

97+
pragma[nomagic]
98+
private predicate astNode(Element e) {
99+
e = any(@top_level_exprorstmt_parent p | not p instanceof Attribute)
100+
or
101+
exists(Element parent |
102+
astNode(parent) and
103+
e = getAChild(parent)
104+
)
105+
}
106+
97107
/** An AST node. */
98108
class AstNode extends Element, TAstNode {
99-
AstNode() { this = getAChild*(any(@top_level_exprorstmt_parent p | not p instanceof Attribute)) }
109+
AstNode() { astNode(this) }
100110

101111
int getId() { idOf(this, result) }
102112
}

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

Lines changed: 13 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,16 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
23772378
storeStepDelegateCall(node1, c, node2)
23782379
}
23792380

2381+
pragma[nomagic]
2382+
private predicate isAssignExprLValueDescendant(Expr e) {
2383+
e = any(AssignExpr ae).getLValue()
2384+
or
2385+
exists(Expr parent |
2386+
isAssignExprLValueDescendant(parent) and
2387+
e = parent.getAChildExpr()
2388+
)
2389+
}
2390+
23802391
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
23812392
ReadStepConfiguration() { this = "ReadStepConfiguration" }
23822393

@@ -2432,7 +2443,7 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
24322443
scope =
24332444
any(AssignExpr ae |
24342445
ae = defTo.(AssignableDefinitions::TupleAssignmentDefinition).getAssignment() and
2435-
e = ae.getLValue().getAChildExpr*().(TupleExpr) and
2446+
isAssignExprLValueDescendant(e.(TupleExpr)) and
24362447
exactScope = false and
24372448
isSuccessor = true
24382449
)
@@ -2488,7 +2499,7 @@ private predicate readContentStep(Node node1, Content c, Node node2) {
24882499
)
24892500
or
24902501
// item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
2491-
te = any(PatternExpr pe).getAChildExpr*() and
2502+
isPatternExprDescendant(te) and
24922503
exists(AssignableDefinitions::LocalVariableDefinition lvd |
24932504
node2.(AssignableDefinitionNode).getDefinition() = lvd and
24942505
lvd.getDeclaration() = item and

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

Lines changed: 14 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,24 @@ class Expr extends ControlFlowElement, @expr {
6465
/** Gets the enclosing callable of this expression, if any. */
6566
override Callable getEnclosingCallable() { enclosingCallable(this, result) }
6667

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+
6779
/**
6880
* Holds if this expression is generated by the compiler and does not appear
6981
* explicitly in the source code.
7082
*/
7183
final predicate isImplicit() {
7284
compiler_generated(this) or
73-
this =
74-
any(AssignOperation op).getExpandedAssignment().getRValue().getChildExpr(0).getAChildExpr+()
85+
this.isExpandedAssignmentRValueDescendant()
7586
}
7687

7788
/**
@@ -1133,7 +1144,7 @@ class TupleExpr extends Expr, @tuple_expr {
11331144
/** Holds if this expression is a tuple construction. */
11341145
predicate isConstruction() {
11351146
not this = getAnAssignOrForeachChild() and
1136-
not this = any(PatternExpr pe).getAChildExpr*()
1147+
not isPatternExprDescendant(this)
11371148
}
11381149

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

0 commit comments

Comments
 (0)