Skip to content

Commit 2b90b50

Browse files
authored
Merge pull request github#3528 from hvitved/csharp/cfg/cs6-initializers
C#: Fix CFG for C# 6 initializers
2 parents 499e349 + 7a54a90 commit 2b90b50

File tree

9 files changed

+1188
-514
lines changed

9 files changed

+1188
-514
lines changed

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ module ControlFlow {
501501
private class WriteAccessNoNodeExpr extends WriteAccess, NoNodeExpr {
502502
WriteAccessNoNodeExpr() {
503503
// For example a write to a static field, `Foo.Bar = 0`.
504-
forall(Expr e | e = this.(QualifiableExpr).getQualifier() | e instanceof NoNodeExpr)
504+
forall(Expr e | e = this.getAChildExpr() | e instanceof NoNodeExpr)
505505
}
506506
}
507507

@@ -553,7 +553,17 @@ module ControlFlow {
553553
* not evaluated, only the qualifier and the indexer arguments (if any).
554554
*/
555555
private class QualifiedWriteAccess extends WriteAccess, QualifiableExpr {
556-
QualifiedWriteAccess() { this.hasQualifier() }
556+
QualifiedWriteAccess() {
557+
this.hasQualifier()
558+
or
559+
// Member initializers like
560+
// ```
561+
// new Dictionary<int, string>() { [0] = "Zero", [1] = "One", [2] = "Two" }
562+
// ```
563+
// need special treatment, because the the accesses `[0]`, `[1]`, and `[2]`
564+
// have no qualifier.
565+
this = any(MemberInitializer mi).getLValue()
566+
}
557567
}
558568

559569
/** A normal or a (potential) dynamic call to an accessor. */

csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -400,14 +400,15 @@
400400
| Foreach.cs:36:10:36:11 | exit M6 | Foreach.cs:36:10:36:11 | exit M6 | 1 |
401401
| Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | 1 |
402402
| Foreach.cs:38:26:38:26 | String x | Foreach.cs:39:11:39:11 | ; | 4 |
403-
| Initializers.cs:6:5:6:16 | enter Initializers | Initializers.cs:6:5:6:16 | exit Initializers | 14 |
404403
| Initializers.cs:8:5:8:16 | enter Initializers | Initializers.cs:8:5:8:16 | exit Initializers | 14 |
405-
| Initializers.cs:10:10:10:10 | enter M | Initializers.cs:10:10:10:10 | exit M | 20 |
406-
| Initializers.cs:16:20:16:20 | 1 | Initializers.cs:16:16:16:20 | ... = ... | 2 |
407-
| Initializers.cs:18:11:18:23 | enter NoConstructor | Initializers.cs:18:11:18:23 | exit NoConstructor | 8 |
408-
| Initializers.cs:29:9:29:11 | enter Sub | Initializers.cs:29:9:29:11 | exit Sub | 11 |
409-
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | exit Sub | 8 |
410-
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | exit Sub | 18 |
404+
| Initializers.cs:10:5:10:16 | enter Initializers | Initializers.cs:10:5:10:16 | exit Initializers | 14 |
405+
| Initializers.cs:12:10:12:10 | enter M | Initializers.cs:12:10:12:10 | exit M | 20 |
406+
| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:20 | ... = ... | 2 |
407+
| Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:20:11:20:23 | exit NoConstructor | 8 |
408+
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | exit Sub | 11 |
409+
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | exit Sub | 8 |
410+
| Initializers.cs:35:9:35:11 | enter Sub | Initializers.cs:35:9:35:11 | exit Sub | 18 |
411+
| Initializers.cs:51:10:51:13 | enter Test | Initializers.cs:51:10:51:13 | exit Test | 104 |
411412
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:9:13:9:28 | ... == ... | 7 |
412413
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | exit M1 | 1 |
413414
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:10:13:10:19 | return ...; | 1 |

csharp/ql/test/library-tests/controlflow/graph/Dominance.expected

Lines changed: 392 additions & 184 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected

Lines changed: 196 additions & 91 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected

Lines changed: 175 additions & 68 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected

Lines changed: 175 additions & 68 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/Initializers.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Collections.Generic;
2+
13
class Initializers
24
{
35
int F = H + 1;
@@ -33,3 +35,33 @@ class Sub : NoConstructor
3335
Sub(int i, int j) { I = i + j; }
3436
}
3537
}
38+
39+
class IndexInitializers
40+
{
41+
class Compound
42+
{
43+
public Dictionary<int, string> DictionaryField;
44+
public Dictionary<int, string> DictionaryProperty { get; set; }
45+
public string[] ArrayField;
46+
public string[] ArrayProperty { get; set; }
47+
public string[,] ArrayField2;
48+
public string[,] ArrayProperty2 { get; set; }
49+
}
50+
51+
void Test(int i)
52+
{
53+
// Collection initializer
54+
var dict = new Dictionary<int, string>() { [0] = "Zero", [1] = "One", [i + 2] = "Two" };
55+
56+
// Indexed initializer
57+
var compound = new Compound()
58+
{
59+
DictionaryField = { [0] = "Zero", [1] = "One", [i + 2] = "Two" },
60+
DictionaryProperty = { [3] = "Three", [2] = "Two", [i + 1] = "One" },
61+
ArrayField = { [0] = "Zero", [i + 1] = "One" },
62+
ArrayField2 = { [0, 1] = "i", [1, i + 0] = "1" },
63+
ArrayProperty = { [1] = "One", [i + 2] = "Two" },
64+
ArrayProperty2 = { [0, 1] = "i", [1, i + 0] = "1" },
65+
};
66+
}
67+
}

csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected

Lines changed: 190 additions & 87 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/Nodes.expected

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -717,13 +717,14 @@ entryPoint
717717
| Foreach.cs:24:10:24:11 | M4 | Foreach.cs:25:5:28:5 | {...} |
718718
| Foreach.cs:30:10:30:11 | M5 | Foreach.cs:31:5:34:5 | {...} |
719719
| Foreach.cs:36:10:36:11 | M6 | Foreach.cs:37:5:40:5 | {...} |
720-
| Initializers.cs:6:5:6:16 | Initializers | Initializers.cs:3:9:3:9 | this access |
721-
| Initializers.cs:8:5:8:16 | Initializers | Initializers.cs:3:9:3:9 | this access |
722-
| Initializers.cs:10:10:10:10 | M | Initializers.cs:11:5:14:5 | {...} |
723-
| Initializers.cs:18:11:18:23 | NoConstructor | Initializers.cs:20:23:20:23 | this access |
724-
| Initializers.cs:29:9:29:11 | Sub | Initializers.cs:29:17:29:20 | call to constructor NoConstructor |
725-
| Initializers.cs:31:9:31:11 | Sub | Initializers.cs:31:22:31:25 | call to constructor Sub |
726-
| Initializers.cs:33:9:33:11 | Sub | Initializers.cs:20:23:20:23 | this access |
720+
| Initializers.cs:8:5:8:16 | Initializers | Initializers.cs:5:9:5:9 | this access |
721+
| Initializers.cs:10:5:10:16 | Initializers | Initializers.cs:5:9:5:9 | this access |
722+
| Initializers.cs:12:10:12:10 | M | Initializers.cs:13:5:16:5 | {...} |
723+
| Initializers.cs:20:11:20:23 | NoConstructor | Initializers.cs:22:23:22:23 | this access |
724+
| Initializers.cs:31:9:31:11 | Sub | Initializers.cs:31:17:31:20 | call to constructor NoConstructor |
725+
| Initializers.cs:33:9:33:11 | Sub | Initializers.cs:33:22:33:25 | call to constructor Sub |
726+
| Initializers.cs:35:9:35:11 | Sub | Initializers.cs:22:23:22:23 | this access |
727+
| Initializers.cs:51:10:51:13 | Test | Initializers.cs:52:5:66:5 | {...} |
727728
| LoopUnrolling.cs:7:10:7:11 | M1 | LoopUnrolling.cs:8:5:13:5 | {...} |
728729
| LoopUnrolling.cs:15:10:15:11 | M2 | LoopUnrolling.cs:16:5:20:5 | {...} |
729730
| LoopUnrolling.cs:22:10:22:11 | M3 | LoopUnrolling.cs:23:5:27:5 | {...} |

0 commit comments

Comments
 (0)