Skip to content

Commit 0e62377

Browse files
committed
C#: Treat _ as an ordinary variable in a foreach.
1 parent 8aeeec0 commit 0e62377

File tree

4 files changed

+40
-18
lines changed

4 files changed

+40
-18
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ protected override void Populate()
2626

2727
var location = cx.Create(Stmt.Identifier.GetLocation());
2828

29-
if (typeSymbol.Name != "_")
30-
Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, location, Stmt.Type.IsVar, this, 0);
31-
else
32-
TypeMention.Create(cx, Stmt.Type, this, type);
29+
Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, location, Stmt.Type.IsVar, this, 0);
3330

3431
Statement.Create(cx, Stmt.Statement, this, 2);
3532
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,39 @@ class TypeMention : FreshEntity
2222
Loc = loc;
2323
}
2424

25-
static TypeSyntax GetArrayElementType(ArrayTypeSyntax array)
25+
static TypeSyntax GetElementType(TypeSyntax type)
2626
{
27-
return array.ElementType is ArrayTypeSyntax a ?
28-
GetArrayElementType(a) :
29-
array.ElementType;
27+
switch(type)
28+
{
29+
case ArrayTypeSyntax ats:
30+
return GetElementType(ats.ElementType);
31+
case NullableTypeSyntax nts:
32+
return GetElementType(nts.ElementType);
33+
default:
34+
return type;
35+
}
3036
}
3137

32-
static Type GetArrayElementType(Type t)
38+
static Type GetElementType(Type t)
3339
{
34-
return t is ArrayType a ? GetArrayElementType(a.ElementType.Type) : t;
40+
switch(t)
41+
{
42+
case ArrayType at:
43+
return GetElementType(at.ElementType.Type);
44+
case NamedType nt when nt.symbol.IsBoundNullable():
45+
return nt.TypeArguments.Single();
46+
default:
47+
return t;
48+
}
3549
}
3650

3751
void Populate()
3852
{
3953
switch (Syntax.Kind())
4054
{
4155
case SyntaxKind.ArrayType:
42-
var ats = (ArrayTypeSyntax)Syntax;
43-
var at = (ArrayType)Type;
4456
Emit(Loc ?? Syntax.GetLocation(), Parent, Type);
45-
Create(cx, GetArrayElementType(ats), this, GetArrayElementType(at));
57+
Create(cx, GetElementType(Syntax), this, GetElementType(Type));
4658
return;
4759
case SyntaxKind.NullableType:
4860
var nts = (NullableTypeSyntax)Syntax;

csharp/ql/test/library-tests/regressions/Program.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,23 @@ class EmbeddedTypesManager<
161161

162162
unsafe class ArrayTypesTest
163163
{
164-
int*[][] field;
164+
int*[][] field;
165165
}
166166

167167
class NameofNamespace
168168
{
169169
string s = nameof(System);
170170
}
171171

172-
// semmle-extractor-options: /r:System.Dynamic.Runtime.dll
172+
class UsingDiscard
173+
{
174+
void F()
175+
{
176+
foreach(var _ in new IDisposable[] { })
177+
using(_)
178+
{
179+
}
180+
}
181+
}
182+
183+
// semmle-extractor-options: /r:System.Dynamic.Runtime.dll /langversion:8.0

csharp/ql/test/library-tests/regressions/TypeMentions.expected

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
| Program.cs:157:31:157:50 | EmbeddedTypesManager<,> |
7777
| Program.cs:157:52:157:72 | TEmbeddedTypesManager |
7878
| Program.cs:157:75:157:87 | TEmbeddedType |
79-
| Program.cs:164:3:164:5 | Int32 |
80-
| Program.cs:164:3:164:6 | Int32* |
81-
| Program.cs:164:3:164:10 | Int32*[][] |
79+
| Program.cs:164:5:164:7 | Int32 |
80+
| Program.cs:164:5:164:8 | Int32* |
81+
| Program.cs:164:5:164:12 | Int32*[][] |
8282
| Program.cs:169:5:169:10 | String |
83+
| Program.cs:174:5:174:8 | Void |
84+
| Program.cs:176:17:176:19 | IDisposable |

0 commit comments

Comments
 (0)