From 0e62377dd2f9917d090bb508577e7b9f27a1fc8a Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 4 Jul 2019 16:29:36 +0100 Subject: [PATCH] C#: Treat _ as an ordinary variable in a foreach. --- .../Entities/Statements/ForEach.cs | 5 +--- .../Entities/TypeMention.cs | 30 +++++++++++++------ .../test/library-tests/regressions/Program.cs | 15 ++++++++-- .../regressions/TypeMentions.expected | 8 +++-- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs index dbc6f5694eb..3404203ace0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs @@ -26,10 +26,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements var location = cx.Create(Stmt.Identifier.GetLocation()); - if (typeSymbol.Name != "_") - Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, location, Stmt.Type.IsVar, this, 0); - else - TypeMention.Create(cx, Stmt.Type, this, type); + Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, location, Stmt.Type.IsVar, this, 0); Statement.Create(cx, Stmt.Statement, this, 2); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs index f65307706c5..f57401984e2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs @@ -22,16 +22,30 @@ namespace Semmle.Extraction.CSharp.Entities Loc = loc; } - static TypeSyntax GetArrayElementType(ArrayTypeSyntax array) + static TypeSyntax GetElementType(TypeSyntax type) { - return array.ElementType is ArrayTypeSyntax a ? - GetArrayElementType(a) : - array.ElementType; + switch(type) + { + case ArrayTypeSyntax ats: + return GetElementType(ats.ElementType); + case NullableTypeSyntax nts: + return GetElementType(nts.ElementType); + default: + return type; + } } - static Type GetArrayElementType(Type t) + static Type GetElementType(Type t) { - return t is ArrayType a ? GetArrayElementType(a.ElementType.Type) : t; + switch(t) + { + case ArrayType at: + return GetElementType(at.ElementType.Type); + case NamedType nt when nt.symbol.IsBoundNullable(): + return nt.TypeArguments.Single(); + default: + return t; + } } void Populate() @@ -39,10 +53,8 @@ namespace Semmle.Extraction.CSharp.Entities switch (Syntax.Kind()) { case SyntaxKind.ArrayType: - var ats = (ArrayTypeSyntax)Syntax; - var at = (ArrayType)Type; Emit(Loc ?? Syntax.GetLocation(), Parent, Type); - Create(cx, GetArrayElementType(ats), this, GetArrayElementType(at)); + Create(cx, GetElementType(Syntax), this, GetElementType(Type)); return; case SyntaxKind.NullableType: var nts = (NullableTypeSyntax)Syntax; diff --git a/csharp/ql/test/library-tests/regressions/Program.cs b/csharp/ql/test/library-tests/regressions/Program.cs index a5b24b7385e..047c24164ad 100644 --- a/csharp/ql/test/library-tests/regressions/Program.cs +++ b/csharp/ql/test/library-tests/regressions/Program.cs @@ -161,7 +161,7 @@ namespace NoPia unsafe class ArrayTypesTest { - int*[][] field; + int*[][] field; } class NameofNamespace @@ -169,4 +169,15 @@ class NameofNamespace string s = nameof(System); } -// semmle-extractor-options: /r:System.Dynamic.Runtime.dll +class UsingDiscard +{ + void F() + { + foreach(var _ in new IDisposable[] { }) + using(_) + { + } + } +} + +// semmle-extractor-options: /r:System.Dynamic.Runtime.dll /langversion:8.0 diff --git a/csharp/ql/test/library-tests/regressions/TypeMentions.expected b/csharp/ql/test/library-tests/regressions/TypeMentions.expected index 9bdeafa2d87..69a57a1059d 100644 --- a/csharp/ql/test/library-tests/regressions/TypeMentions.expected +++ b/csharp/ql/test/library-tests/regressions/TypeMentions.expected @@ -76,7 +76,9 @@ | Program.cs:157:31:157:50 | EmbeddedTypesManager<,> | | Program.cs:157:52:157:72 | TEmbeddedTypesManager | | Program.cs:157:75:157:87 | TEmbeddedType | -| Program.cs:164:3:164:5 | Int32 | -| Program.cs:164:3:164:6 | Int32* | -| Program.cs:164:3:164:10 | Int32*[][] | +| Program.cs:164:5:164:7 | Int32 | +| Program.cs:164:5:164:8 | Int32* | +| Program.cs:164:5:164:12 | Int32*[][] | | Program.cs:169:5:169:10 | String | +| Program.cs:174:5:174:8 | Void | +| Program.cs:176:17:176:19 | IDisposable |