/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit3/FlowAnalysis/TryLockUsingStatementTests.cs
1 746 строк
61 KB
Tomáš Matoušek
Move some emit tests from Emit2 to Emit3 to avoid hitting UserString heap limit (#75091)
13 сен 2024, 12:01
Не верифицирован
13 сен 2024, 12:01
814c61c
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class TryLockUsingStatementTests : FlowTestBase { #region "try-catch-finally" [Fact] public void TestAssignmentInCatch() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" class C { static void F() { } static void M(out int x, out int y) { /*<bind>*/ try { F(); x = 1; y = 0; } catch (System.Exception) { x = 0; } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Empty(controlFlowAnalysisResults.EntryPoints); Assert.Empty(controlFlowAnalysisResults.ExitPoints); Assert.Empty(controlFlowAnalysisResults.ReturnStatements); Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestAssignmentInFinally() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" class C { static void M(out int x, out int y) { /*<bind>*/ try { y = 0; return; } finally { x = 0; } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(1, controlFlowAnalysisResults.ExitPoints.Count()); Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestBreakContinueInTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" public class TryCatchFinally { public byte TryMethod(byte para) { byte by = 9; while (by > 0) { by--; /*<bind>*/ try { if (by % 7 == 0) continue; } catch (System.Exception) { if (by % 11 == 0) { break; } } finally { try { break; // CS0157 } catch { } } /*</bind>*/ } return by; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(3, controlFlowAnalysisResults.ExitPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ReturnStatements.Count()); Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para, by", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(528296, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528296")] [Fact] public void TestReturnInTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" public class TryCatchFinally { public byte TryMethod(ref byte para) { byte by = 10; /*<bind>*/ try { if (by % 13 == 0) { return 13; } else if (by % 17 == 0) { return 17; } } catch (System.Exception) { try { return 123; } finally { if (by % 11 == 0) { return 11; // CS0157 } } return 7; } /*</bind>*/ return by; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(5, controlFlowAnalysisResults.ExitPoints.Count()); Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("para, by", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para, by", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para, by", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestGotoInTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" public class TryCatchFinally { public void TryMethod(out byte para) { byte by = 10; L1: para = by; /*<bind>*/ try { by = (byte)(by + by); L2: by = (byte)(by / by); if (by / 13 == 0) { goto L1; // ok } else if (by / 17 == 0) { goto L2; // ok } } finally { by = by--; try { L3: ; } catch (System.Exception) { goto L3; // CS0159 } goto L1; // CS0157 } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(2, controlFlowAnalysisResults.ExitPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ReturnStatements.Count()); Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para, by", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("by", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para, by", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestThrowInTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(uint para) { try { /*<bind>*/ throw new DivideByZeroException(); /*</bind>*/ } catch (IndexOutOfRangeException) { para++; } finally { para--;} } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ExitPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ReturnStatements.Count()); Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(541724, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541724")] [Fact] public void TestThrowInTry02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(ref uint para) { try { throw new DivideByZeroException(); } catch (IndexOutOfRangeException) { para++; } catch (DivideByZeroException) { /*<bind>*/ para--; /*</bind>*/ // rethrow throw; } finally { } } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ExitPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ReturnStatements.Count()); Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestThrowInTry03() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { sbyte sb; /*<bind>*/ try { sb = 0; try { // int x = (100 / sb); throw new DivideByZeroException(); } catch (IndexOutOfRangeException) { sb++; } catch (DivideByZeroException) { // rethrow throw; } finally { sb--; } } catch (DivideByZeroException) { throw new NullReferenceException(); } catch (NullReferenceException) { sb = -128; } finally { throw; // CS0156 } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ExitPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ReturnStatements.Count()); Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("sb", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("sb", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestAlwaysAssignedInTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(out ulong para) { string local; /*<bind>*/ try { local = ""try""; throw new DivideByZeroException(); } catch (IndexOutOfRangeException) { local = ""ex""; para = 12345; } catch (DivideByZeroException) { throw; } finally { } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal(0, controlFlowAnalysisResults.EntryPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ExitPoints.Count()); Assert.Equal(0, controlFlowAnalysisResults.ReturnStatements.Count()); Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("para, local", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("para, local", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestAlwaysAssignedInTry02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(ref long? para) { long? local; /*<bind>*/ try { if (para > 0) local = 12345; } catch (IndexOutOfRangeException) { local = -1; throw; para = local; } finally { } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("para, local", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("para, local", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(528567, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528567")] [WorkItem(541723, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541723")] [Fact] public void TestAlwaysAssignedInTry03() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(ref string para) { string local; try { if (!String.IsNullOrEmpty(para)) local = ""try""; else para = local; } catch (ArgumentException ax) { /*<bind>*/ para = -0; Console.WriteLine(ax); /*</bind>*/ // throw; } finally { } } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("ax", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("ax", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("para, local", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("para", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, para, local, ax", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestDataFlowsInOut01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { protected void TryMethod(long p) { long x = 0, y = 1, z; /*<bind>*/ try { if (p > 0) z = x; } catch (Exception) { throw; z = y; } finally { if (false) x = y*y; } /*</bind>*/ x = z * y; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("p, x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("z", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("p, x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("y, z", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, z", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, p, x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(540797, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540797")] [Fact] public void TestDataFlowsInOut02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(long p) { long? x = null, y = 1, z; /*<bind>*/ try { x = p; } catch (Exception) { } finally { z = x; } /*</bind>*/ p = x.Value * y.Value; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("z", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("p, x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("p, x", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, z", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, p, x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(540798, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540798")] [Fact] public void TestDataFlowsInOut03() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(ref long p) { long x, y, z = 111; L1: x = z; /*<bind>*/ try { L2: y = x + x; goto L2; } catch (ArgumentException ax) { p = y * y; goto L1; } finally { z = x; } /*</bind>*/ p = y; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("ax", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("p, z, ax", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); // y flows out as follows: the assignment in the try block, followed by an exception taking it into the catch // block, then goto L1, (now the value is outside the region), followed by flowing back in to the try block, // then another exception arising before executing the assignment to y, then reading y in the catch block. Assert.Equal("p, y, z", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("p, y, z", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("p, y, z, ax", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, p, x, z", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(541655, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541655")] [WorkItem(541723, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541723")] [Fact] public void TestVariablesDeclaredInTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { /*<bind>*/ try { if (false) { string s = ""SOS""; } } catch (ArgumentException ax) { throw; ushort s = 123; } finally { short s = 456; } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("s, ax, s, s", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("s", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("s, ax, s, s", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestFlowsOutTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" public class TryCatchFinally { public static void Main() { int x = 12; try { /*<bind>*/ x = 12; return; /*</bind>*/ } finally { int z = x; } } } "); var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); } [Fact] public void TestFlowsOutTry02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@" public class TryCatchFinally { public static void M(int n) { L1: try { try { L2: /*<bind>*/ n++; if (n < 99) goto L1; /*</bind>*/ if (n < 999) goto L2; } catch (Exception x) { } } finally { n = 0; } } } "); var dataFlowAnalysisResults = analysisResults.Item2; Assert.Equal("n", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("n", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("n", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); } [Fact] public void TestVariableInCatch01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { sbyte x = 111, y = 222; try { sbyte s = x; } catch (ArgumentException ax) { /*<bind>*/ Console.Write(ax); goto L; // unreachable is ALWAYS assigned sbyte s = y; /*</bind>*/ } finally { x= y; } L: y = x; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("s", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); // unreachable is ALWAYS assigned Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("ax", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("y, ax", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("s", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, x, y, s, ax", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestVariableInCatch02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { sbyte x = 111, y = 222; /*<bind>*/ try { sbyte s = x; } catch (ArgumentException ax) { Console.Write(ax); goto L; } catch (Exception ex) { Console.Write(ex); } finally { x = s; } /*</bind>*/ L: y = x; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("s, ax, ex", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); // s? Assert.Equal("x, ax, ex", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, s, ax, ex", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact, WorkItem(528297, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528297")] public void TestTryInWhile() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { sbyte x = 111, y; /*<bind>*/ while (x-- > 0) { try { y = (sbyte)(x / 2); } finally { throw new Exception(); // this makes while end-ptr unreachable } } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); // possible if while (false)... Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, x", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact, WorkItem(528298, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528298")] public void TestTryInDoWhile() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { sbyte x = 111, y; /*<bind>*/ do { try { y = x; break; } catch (Exception) { continue; } finally { // return; throw new Exception(); } // unreachable } while (x++ < 121) /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("x, y", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, x", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestTryInFor() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(short p) { sbyte y; /*<bind>*/ for (short i = 0; i < p; i++) { try { y = GetVal(i); continue; } catch (Exception) { break; } finally { throw new Exception(); } // unreachable } /*</bind>*/ } sbyte GetVal(sbyte n) { return n++; } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; // Bug#7263 (BD) - if the whole 'try' somehow unreachable, the end of 'for' is reachable Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("i", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("i", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("this, p", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("this, p, i", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("y, i", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("this, p", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(540835, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540835")] [Fact] public void TestBracketRegionsInTry() { var analysisResults01 = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(ushort p) { ulong x= 0, y; try /*<bind>*/ { y = x + p; } /*</bind>*/ catch (Exception ex) { Console.Write(ex); } } } "); var analysisResults02 = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod(ushort p) { ulong x= 0, y; try { /*<bind>*/ y = x + p; /*</bind>*/ } catch (Exception ex) { Console.Write(ex); } } } "); var dataFlowResults01 = analysisResults01.Item2; var dataFlowResults02 = analysisResults02.Item2; Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.VariablesDeclared), GetSymbolNamesJoined(dataFlowResults01.VariablesDeclared)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.AlwaysAssigned), GetSymbolNamesJoined(dataFlowResults01.AlwaysAssigned)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.DataFlowsIn), GetSymbolNamesJoined(dataFlowResults01.DataFlowsIn)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.DataFlowsOut), GetSymbolNamesJoined(dataFlowResults01.DataFlowsOut)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.ReadInside), GetSymbolNamesJoined(dataFlowResults01.ReadInside)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.ReadOutside), GetSymbolNamesJoined(dataFlowResults01.ReadOutside)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.WrittenInside), GetSymbolNamesJoined(dataFlowResults01.WrittenInside)); Assert.Equal(GetSymbolNamesJoined(dataFlowResults02.WrittenOutside), GetSymbolNamesJoined(dataFlowResults01.WrittenOutside)); } [Fact] public void TestTryWithLambda01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { delegate long D01(long dp); void M(ref long refp, out long outp) { /*<bind>*/ try { outp = refp++; } catch (Exception e) { D01 d = (ap) => { e = new ArgumentException(ap.ToString()); return e.Message.Length; }; outp = d(refp); } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("outp", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("e", GetSymbolNamesJoined(dataFlowAnalysisResults.Captured)); Assert.Equal("refp", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("refp, outp", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("refp, e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("refp, outp, e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("refp, outp", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("this, refp", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [WorkItem(541723, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541723")] [Fact] public void TestTryWithLambda02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { delegate long D01(long dp); static void M(ref long refp, out long outp) { try { outp = refp++; } catch (Exception e) { /*<bind>*/ D01 d = delegate (long ap) { e = new ArgumentException(ap.ToString()); return e.Message.Length; }; outp = d(refp); /*</bind>*/ } } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("outp, d", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("e", GetSymbolNamesJoined(dataFlowAnalysisResults.Captured)); Assert.Equal("refp", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Equal("outp", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("refp, e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("outp, e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("refp, outp", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("refp, outp, e", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestTryWithLambda03() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { delegate string D02(byte dp); static string M(ushort p) { byte local = (byte)(p % byte.MaxValue); /*<bind>*/ try { if (local == p) { return null; } return local.ToString(); } catch (Exception e) { D02 d = delegate (byte ap) { return (ap + local + p).ToString() + e.Message; }; return d(local); } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("p, local, e", GetSymbolNamesJoined(dataFlowAnalysisResults.Captured)); Assert.Equal("p, local", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("p, local, e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("p", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("p, local", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestTryWithLambda04() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { delegate string D02(byte? dp); internal string M(ushort p) { byte? local = (byte)(p % byte.MaxValue); try { if (local.Value == p) { return null; } return local.Value.ToString(); } catch (Exception e) { /*<bind>*/ D02 d = (ap) => { return (ap.Value + local.Value + p).ToString() + e.Message; }; return d(local); /*</bind>*/ } } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.False(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared)); Assert.Equal("d", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); Assert.Equal("p, local, e", GetSymbolNamesJoined(dataFlowAnalysisResults.Captured)); Assert.Equal("p, local, e", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); Assert.Equal("p, local, e, d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadInside)); Assert.Equal("d, ap", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenInside)); Assert.Equal("p, local", GetSymbolNamesJoined(dataFlowAnalysisResults.ReadOutside)); Assert.Equal("this, p, local, e", GetSymbolNamesJoined(dataFlowAnalysisResults.WrittenOutside)); } [Fact] public void TestIncompleteCatch() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class Program { public static void Main(string[] args) { int x = 12; try { M1(); } catch (Exception ex) { /*<bind>*/ if (args.Length == 2) { x = 14; throw; } /*</bind>*/ } M2(x); } public static void M1() {} public static void M2(int x) {} } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Null(GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); } [Fact] public void TestNestedTry01() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class Program { public static void Main(string[] args) { int x = 12; /*<bind>*/ try { M1(); } catch (Exception ex) { } finally { try { x = 14; } catch (Exception ex) { } } /*</bind>*/ M2(x); } public static void M1() {} public static void M2(int x) {} } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); } [Fact] public void TestNestedTry02() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class Program { public static void Main(string[] args) { int x = 12; /*<bind>*/ try { M1(); } catch (Exception ex) { try { x = 14; } catch (Exception ex) { } } finally { } /*</bind>*/ M2(x); } public static void M1() {} public static void M2(int x) {} } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); } [Fact] public void TestNestedTry03() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class Program { public static void Main(string[] args) { int x = 12; /*<bind>*/ try { M1(); try { x = 14; } catch (Exception ex) { } } catch (Exception ex) { } finally { } /*</bind>*/ M2(x); } public static void M1() {} public static void M2(int x) {} } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.DataFlowsOut)); } [Fact, WorkItem(529180, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529180")] public void AlwaysAssignedInTry() { var analysisResults = CompileAndAnalyzeControlAndDataFlowStatements(@"using System; public class TryCatchFinally { public void TryMethod() { int x, y; /*<bind>*/ try { x = 123; } finally { } try { y = 123; } catch(Exception) { } /*</bind>*/ } } "); var controlFlowAnalysisResults = analysisResults.Item1; var dataFlowAnalysisResults = analysisResults.Item2; Assert.True(controlFlowAnalysisResults.EndPointIsReachable); Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.AlwaysAssigned)); } #endregion [Fact] public void TestVariablesDeclaredInUsingStatement1() { var analysis = CompileAndAnalyzeDataFlowStatements(@" class C { public void F(int x) { int a; /*<bind>*/ using (var c = new System.IO.StreamWriter()) { F(x); } /*</bind>*/ int b; } }"); Assert.Equal("c", GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Equal("c", GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Null(GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Equal("c", GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact] public void TestVariablesDeclaredInUsingStatement2() { var analysis = CompileAndAnalyzeDataFlowStatements(@" class C { public void F(int x) { int a; using (var c = new System.IO.StreamWriter()) { /*<bind>*/ F(x); /*</bind>*/ } int b; } }"); Assert.Null(GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Equal("c", GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Null(GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact] public void TestVariablesDeclaredInAwaitUsingStatement() { var (analysisControlFlow, analysis) = CompileAndAnalyzeControlAndDataFlowStatements(@" namespace System { public interface IAsyncDisposable { System.Threading.Tasks.Task DisposeAsync(); } } class C : System.IAsyncDisposable { public void F(int x) { int a; /*<bind>*/ await using (var c = new C()) { F(x); } /*</bind>*/ int b; } }"); Assert.Equal("c", GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Equal("c", GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Null(GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Equal("c", GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); Assert.Empty(analysisControlFlow.EntryPoints); Assert.Empty(analysisControlFlow.ExitPoints); Assert.Equal(0, analysisControlFlow.ReturnStatements.Count()); Assert.True(analysisControlFlow.EndPointIsReachable); } #region "lock statement" [Fact] public void TestLockStatement1() { var analysis = CompileAndAnalyzeDataFlowStatements(@" class C { public void F(int x) { int a; C c = new C(); /*<bind>*/ lock (c) { F(x); } /*</bind>*/ int b; } }"); Assert.Null(GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Null(GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Null(GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact] public void TestLockStatement2() { var analysis = CompileAndAnalyzeDataFlowStatements(@" class C { public void F(int x) { int a; C c = new C(); lock (c) { /*<bind>*/ F(x); /*</bind>*/ } int b; } }"); Assert.Null(GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("this, x, c", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Equal("c", GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Null(GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("this, x", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact()] public void NestedLock() { var analysis = CompileAndAnalyzeDataFlowStatements( @" class Test { public void Main() { /*<bind>*/ lock (typeof(Test)) { lock (new Test()) { } } /*</bind>*/ } } "); Assert.Null(GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("this", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Null(GetSymbolNamesJoined(analysis.ReadInside)); Assert.Null(GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Null(GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact()] public void LockAnonymousTypes() { var analysis = CompileAndAnalyzeDataFlowStatements( @" class Test { public static void Main() { string name = ""; object obj = new object(); /*<bind>*/ lock (new { p1 = name, p2 = goo(obj) }) { } /*</bind>*/ } static int goo(object x) { return 1; } } "); Assert.Null(GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Null(GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("name, obj", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("name, obj", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Null(GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Null(GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("name, obj", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact()] public void AssignmentInLock() { var analysis = CompileAndAnalyzeDataFlowStatements( @" class Test { public static void Main() { string str = string.Empty; object obj; /*<bind>*/ lock (obj = new string[][] { new string[] { """" }, new string[] { str } }) { } /*</bind>*/ System.Console.Write(obj); } } "); Assert.Null(GetSymbolNamesJoined(analysis.VariablesDeclared)); Assert.Equal("obj", GetSymbolNamesJoined(analysis.WrittenInside)); Assert.Equal("str", GetSymbolNamesJoined(analysis.WrittenOutside)); Assert.Equal("str", GetSymbolNamesJoined(analysis.ReadInside)); Assert.Equal("obj", GetSymbolNamesJoined(analysis.ReadOutside)); Assert.Equal("obj", GetSymbolNamesJoined(analysis.AlwaysAssigned)); Assert.Equal("str", GetSymbolNamesJoined(analysis.DataFlowsIn)); Assert.Equal("obj", GetSymbolNamesJoined(analysis.DataFlowsOut)); } [Fact()] public void BranchOutFromLock() { var analysis = CompileAndAnalyzeControlAndDataFlowStatements( @" class Test { public static void Main() { string str = string.Empty; object obj; /*<bind>*/ lock (new string[][] { new string[] { """" }, new string[] { str } }) { obj = new object(); return; } /*</bind>*/ System.Console.Write(obj); } } "); var analysisControlFlow = analysis.Item1; var analysisDataflow = analysis.Item2; Assert.Null(GetSymbolNamesJoined(analysisDataflow.VariablesDeclared)); Assert.Equal("obj", GetSymbolNamesJoined(analysisDataflow.WrittenInside)); Assert.Equal("str", GetSymbolNamesJoined(analysisDataflow.WrittenOutside)); Assert.Equal("str", GetSymbolNamesJoined(analysisDataflow.ReadInside)); Assert.Equal("obj", GetSymbolNamesJoined(analysisDataflow.ReadOutside)); Assert.Equal("obj", GetSymbolNamesJoined(analysisDataflow.AlwaysAssigned)); Assert.Equal("str", GetSymbolNamesJoined(analysisDataflow.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysisDataflow.DataFlowsOut)); Assert.Equal(1, analysisControlFlow.ExitPoints.Count()); Assert.Equal(0, analysisControlFlow.EntryPoints.Count()); } [Fact()] public void BranchInLock() { var analysis = CompileAndAnalyzeControlAndDataFlowStatements( @" class Test { static int x; public static void Main() { object obj; /*<bind>*/ lock (obj = new object()) { if (x > 1) { goto lab1; } else { System.Console.Write(obj);} lab1: System.Console.WriteLine(); } /*</bind>*/ } } "); var analysisControlFlow = analysis.Item1; var analysisDataflow = analysis.Item2; Assert.Null(GetSymbolNamesJoined(analysisDataflow.VariablesDeclared)); Assert.Equal("obj", GetSymbolNamesJoined(analysisDataflow.WrittenInside)); Assert.Null(GetSymbolNamesJoined(analysisDataflow.WrittenOutside)); Assert.Equal("obj", GetSymbolNamesJoined(analysisDataflow.ReadInside)); Assert.Null(GetSymbolNamesJoined(analysisDataflow.ReadOutside)); Assert.Equal("obj", GetSymbolNamesJoined(analysisDataflow.AlwaysAssigned)); Assert.Null(GetSymbolNamesJoined(analysisDataflow.DataFlowsIn)); Assert.Null(GetSymbolNamesJoined(analysisDataflow.DataFlowsOut)); Assert.Equal(0, analysisControlFlow.ExitPoints.Count()); Assert.Equal(0, analysisControlFlow.EntryPoints.Count()); Assert.Equal(0, analysisControlFlow.ReturnStatements.Count()); } #endregion } }