|
// 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
}
}
|