|
// 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;
using System.IO;
using System.Linq;
using System.Threading;
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
public class CodeGenTests : CSharpTestBase
{
[Fact]
public void EmitWithSuppressedWarnAsError()
{
var src = @"
#pragma warning disable 1591
public class P {
public static void Main() {}
}";
var parseOptions = TestOptions.RegularWithDocumentationComments;
var options = TestOptions.ReleaseDll
.WithXmlReferenceResolver(XmlFileResolver.Default)
.WithGeneralDiagnosticOption(ReportDiagnostic.Error);
var comp = CreateCompilation(src, parseOptions: parseOptions, options: options);
comp.VerifyEmitDiagnostics();
CompileAndVerify(comp);
}
[Fact()]
[WorkItem(776642, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/776642")]
public void Bug776642a()
{
const string source = @"
using System;
using System.Collections.Generic;
struct TwoInteger
{
public int x;
public int y;
}
struct DoubleAndStruct
{
public double x;
public TwoInteger y;
}
class Program
{
static void Main(string[] args)
{
}
static void Main(object[] args)
{
Object trackArg1, trackArg2;
DoubleAndStruct localArg1 = default(DoubleAndStruct);
DoubleAndStruct localArg2 = default(DoubleAndStruct);
args = new Object[] { localArg1, localArg2 };
trackArg1 = args[0];
trackArg2 = args[1];
Console.WriteLine((((DoubleAndStruct)args[0]).y).x);
}
}";
// ILVerify: Unexpected type on the stack. { Offset = 59, Found = readonly address of '[...]DoubleAndStruct', Expected = address of '[...]DoubleAndStruct' }
var result = CompileAndVerify(source, verify: Verification.FailsILVerify, options: TestOptions.DebugDll);
result.VerifyIL("Program.Main(object[])",
@"
{
// Code size 76 (0x4c)
.maxstack 4
.locals init (object V_0, //trackArg1
object V_1, //trackArg2
DoubleAndStruct V_2, //localArg1
DoubleAndStruct V_3) //localArg2
IL_0000: nop
IL_0001: ldloca.s V_2
IL_0003: initobj ""DoubleAndStruct""
IL_0009: ldloca.s V_3
IL_000b: initobj ""DoubleAndStruct""
IL_0011: ldc.i4.2
IL_0012: newarr ""object""
IL_0017: dup
IL_0018: ldc.i4.0
IL_0019: ldloc.2
IL_001a: box ""DoubleAndStruct""
IL_001f: stelem.ref
IL_0020: dup
IL_0021: ldc.i4.1
IL_0022: ldloc.3
IL_0023: box ""DoubleAndStruct""
IL_0028: stelem.ref
IL_0029: starg.s V_0
IL_002b: ldarg.0
IL_002c: ldc.i4.0
IL_002d: ldelem.ref
IL_002e: stloc.0
IL_002f: ldarg.0
IL_0030: ldc.i4.1
IL_0031: ldelem.ref
IL_0032: stloc.1
IL_0033: ldarg.0
IL_0034: ldc.i4.0
IL_0035: ldelem.ref
IL_0036: unbox ""DoubleAndStruct""
IL_003b: ldflda ""TwoInteger DoubleAndStruct.y""
IL_0040: ldfld ""int TwoInteger.x""
IL_0045: call ""void System.Console.WriteLine(int)""
IL_004a: nop
IL_004b: ret
}
");
}
[Fact()]
[WorkItem(776642, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/776642")]
public void Bug776642b()
{
const string source = @"
using System;
using System.Collections.Generic;
struct TwoInteger
{
public int x;
public int y;
}
struct DoubleAndStruct
{
public double x;
public TwoInteger y;
}
struct OuterStruct
{
public DoubleAndStruct z;
}
class Program
{
static void Main(string[] args)
{
}
static void Main(object[] args)
{
args = new Object[] { default(OuterStruct) };
Console.WriteLine(((((OuterStruct)args[0]).z).y).x);
}
}";
// ILVerify: Unexpected type on the stack. { Offset = 34, Found = readonly address of '[...]OuterStruct', Expected = address of '[...]OuterStruct' }
var result = CompileAndVerify(source, verify: Verification.FailsILVerify, options: TestOptions.DebugDll);
result.VerifyIL("Program.Main(object[])",
@"
{
// Code size 56 (0x38)
.maxstack 4
.locals init (OuterStruct V_0)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: newarr ""object""
IL_0007: dup
IL_0008: ldc.i4.0
IL_0009: ldloca.s V_0
IL_000b: initobj ""OuterStruct""
IL_0011: ldloc.0
IL_0012: box ""OuterStruct""
IL_0017: stelem.ref
IL_0018: starg.s V_0
IL_001a: ldarg.0
IL_001b: ldc.i4.0
IL_001c: ldelem.ref
IL_001d: unbox ""OuterStruct""
IL_0022: ldflda ""DoubleAndStruct OuterStruct.z""
IL_0027: ldflda ""TwoInteger DoubleAndStruct.y""
IL_002c: ldfld ""int TwoInteger.x""
IL_0031: call ""void System.Console.WriteLine(int)""
IL_0036: nop
IL_0037: ret
}
");
}
[Fact()]
[WorkItem(776642, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/776642")]
public void Bug776642c()
{
const string source = @"
using System;
using System.Collections.Generic;
struct TwoInteger
{
public int x;
public int y;
}
struct DoubleAndStruct
{
public double x;
public TwoInteger y;
}
class OuterStruct
{
public DoubleAndStruct z;
}
class Program
{
static void Main(string[] args)
{
}
static void Main(object[] args)
{
args = new Object[] { default(OuterStruct) };
Console.WriteLine(((((OuterStruct)args[0]).z).y).x);
}
}";
var result = CompileAndVerify(source, options: TestOptions.DebugDll);
result.VerifyIL("Program.Main(object[])",
@"
{
// Code size 39 (0x27)
.maxstack 2
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: newarr ""object""
IL_0007: starg.s V_0
IL_0009: ldarg.0
IL_000a: ldc.i4.0
IL_000b: ldelem.ref
IL_000c: castclass ""OuterStruct""
IL_0011: ldflda ""DoubleAndStruct OuterStruct.z""
IL_0016: ldflda ""TwoInteger DoubleAndStruct.y""
IL_001b: ldfld ""int TwoInteger.x""
IL_0020: call ""void System.Console.WriteLine(int)""
IL_0025: nop
IL_0026: ret
}
");
}
[Fact()]
[WorkItem(776642, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/776642")]
public void Bug776642_static()
{
const string source = @"
using System;
using System.Collections.Generic;
struct TwoInteger
{
public int x;
public int y;
}
struct DoubleAndStruct
{
public double x;
public TwoInteger y;
}
class OuterStruct
{
public static DoubleAndStruct z;
}
class Program
{
static void Main(string[] args)
{
}
static void Main(object[] args)
{
Console.WriteLine(((OuterStruct.z).y).x);
}
}";
var result = CompileAndVerify(source, options: TestOptions.DebugDll);
result.VerifyIL("Program.Main(object[])",
@"
{
// Code size 23 (0x17)
.maxstack 1
IL_0000: nop
IL_0001: ldsflda ""DoubleAndStruct OuterStruct.z""
IL_0006: ldflda ""TwoInteger DoubleAndStruct.y""
IL_000b: ldfld ""int TwoInteger.x""
IL_0010: call ""void System.Console.WriteLine(int)""
IL_0015: nop
IL_0016: ret
}
");
}
[Fact()]
[WorkItem(531366, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531366")]
public void Bug18015()
{
const string source = @"
class P
{
public object X { get; set; }
public void Y() { }
public object M<T>(T t) where T : C
{
((P)(object)t).Y();
return ((P)(object)t).X;
}
}
public class C { }
";
var result = CompileAndVerify(source, options: TestOptions.ReleaseDll);
result.VerifyIL("P.M<T>(T)",
@"
{
// Code size 33 (0x21)
.maxstack 1
IL_0000: ldarg.1
IL_0001: box ""T""
IL_0006: castclass ""P""
IL_000b: callvirt ""void P.Y()""
IL_0010: ldarg.1
IL_0011: box ""T""
IL_0016: castclass ""P""
IL_001b: callvirt ""object P.X.get""
IL_0020: ret
}
");
}
[Fact()]
[WorkItem(546857, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546857")]
public void Bug16996_MissingReturnValue()
{
string source = @"
using System;
public class C
{
public static bool f;
public static int x;
public bool M()
{
bool success = f;
if (success)
{
x = 1;
}
else
{
throw null;
}
return success;
}
}";
var result = CompileAndVerify(source, options: TestOptions.ReleaseDll);
result.VerifyIL("C.M",
@"
{
// Code size 17 (0x11)
.maxstack 2
IL_0000: ldsfld ""bool C.f""
IL_0005: dup
IL_0006: brfalse.s IL_000f
IL_0008: ldc.i4.1
IL_0009: stsfld ""int C.x""
IL_000e: ret
IL_000f: ldnull
IL_0010: throw
}
");
}
[Fact()]
[WorkItem(546857, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546857")]
public void Bug16996_MissingReturnValue01()
{
string source = @"
using System;
public class C
{
public static bool f;
public static int x;
public void M()
{
bool success = f;
if (success)
{
x = 1;
}
else
{
x = 2;
goto L1;
}
return;
L1:
throw null;
}
}
";
var result = CompileAndVerify(source, options: TestOptions.ReleaseDll);
result.VerifyIL("C.M",
@"
{
// Code size 22 (0x16)
.maxstack 1
IL_0000: ldsfld ""bool C.f""
IL_0005: brfalse.s IL_000e
IL_0007: ldc.i4.1
IL_0008: stsfld ""int C.x""
IL_000d: ret
IL_000e: ldc.i4.2
IL_000f: stsfld ""int C.x""
IL_0014: ldnull
IL_0015: throw
}
");
}
[WorkItem(546412, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546412")]
[ConditionalFact(typeof(DesktopOnly))]
public void TestBug15818()
{
var source =
@"using System;
class C
{
public static void Main(string[] args)
{
string s = ""Nothing"";
string[] ss = s.Split(',');
if(ss.Length != 4){
}
if(ss.Rank != 4){
}
Console.Write('k');
}
}";
var tree = Parse(source);
var compilation = CreateEmptyCompilation(tree, [Net461.References.mscorlib], TestOptions.ReleaseExe, assemblyName: "Test");
compilation.MakeMemberMissing(SpecialMember.System_Array__LongLength);
CompileAndVerify(compilation, expectedOutput: "k");
}
[WorkItem(546853, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546853")]
[Fact]
public void TestBug16981()
{
var il = @"
.class public auto ansi beforefieldinit B
extends [mscorlib]System.Object
{
.method public hidebysig newslot specialname virtual instance bool get_M1() cil managed
{
.maxstack 1
IL_0000: ldc.i4.0
IL_0001: ret
}
.method public hidebysig newslot specialname virtual final instance bool get_M2() cil managed
{
.maxstack 1
IL_0000: ldc.i4.0
IL_0001: ret
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}
.property instance bool M1()
{
.get instance bool B::get_M1()
}
.property instance bool M2()
{
.get instance bool B::get_M2()
}
}
";
var source = @"
using System;
class C
{
static void A()
{
var x = new B().M1 && new B().M2;
}
}
";
var compilation = CreateCompilationWithILAndMscorlib40(source, il, TargetFramework.Mscorlib461, options: TestOptions.ReleaseDll);
var result = CompileAndVerify(compilation);
result.VerifyIL("C.A", @"
{
// Code size 27 (0x1b)
.maxstack 1
IL_0000: newobj ""B..ctor()""
IL_0005: callvirt ""bool B.M1.get""
IL_000a: brfalse.s IL_0018
IL_000c: newobj ""B..ctor()""
IL_0011: call ""bool B.M2.get""
IL_0016: br.s IL_0019
IL_0018: ldc.i4.0
IL_0019: pop
IL_001a: ret
}
");
}
[WorkItem(546853, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546853")]
[Fact]
public void TestBug16981b()
{
var il = @"
.class public auto ansi beforefieldinit B
extends [mscorlib]System.Object
{
.method public hidebysig newslot specialname virtual instance bool get_M1() cil managed
{
.maxstack 1
IL_0000: ldc.i4.0
IL_0001: ret
}
.method public hidebysig newslot specialname virtual final instance bool get_M2() cil managed
{
.maxstack 1
IL_0000: ldc.i4.0
IL_0001: ret
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}
.property instance bool M1()
{
.get instance bool B::get_M1()
}
.property instance bool M2()
{
.get instance bool B::get_M2()
}
}
";
var source = @"
using System;
class C
{
static void A()
{
var b = new B();
var x = b.M1 && b.M2;
}
}
";
var compilation = CreateCompilationWithILAndMscorlib40(source, il, TargetFramework.Mscorlib461, options: TestOptions.DebugDll);
var result = CompileAndVerify(compilation);
result.VerifyIL("C.A",
@"{
// Code size 26 (0x1a)
.maxstack 1
.locals init (B V_0, //b
bool V_1) //x
IL_0000: nop
IL_0001: newobj ""B..ctor()""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt ""bool B.M1.get""
IL_000d: brfalse.s IL_0017
IL_000f: ldloc.0
IL_0010: callvirt ""bool B.M2.get""
IL_0015: br.s IL_0018
IL_0017: ldc.i4.0
IL_0018: stloc.1
IL_0019: ret
}
");
}
[Fact, WorkItem(540019, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540019")]
public void TestBug6156()
{
// Note: this test originally required a mismatch between the compile-time view of what the
// program should do and the runtime view. The runtime considers `ref` and `out` to be the
// same, so it had a different view of what one method was overriding than C# did. However,
// in the context of implementing the covariant return types feature, we added code in the compiler to
// cause the compiler to emit methodimpl records whenever there is a mismatch. As a consequence
// of that, we updated this test to now require that the runtime behavior and the compile-time behavior
// of this program match, so that at runtime it obeys the behavior specified by the C#
// language specification.
var source = @"
class Ref1
{ public virtual void M(ref int x) { x = 1; } }
class Out1 : Ref1
{ public virtual void M(out int x) { x = 2; } }
class Ref2 : Out1
{ public override void M(ref int x) { x = 3; } }
class Out2 : Ref2
{ public override void M(out int x) { x = 4; } }
class M
{
static void Main()
{
int x = 0;
Ref1 r1;
r1 = new Ref1();
r1.M(ref x);
System.Console.Write(x); // 1
r1 = new Out1();
r1.M(ref x);
System.Console.Write(x); // 1
r1 = new Ref2();
r1.M(ref x);
System.Console.Write(x); // 3
r1 = new Out2();
r1.M(ref x);
System.Console.WriteLine(x); // 3
Out1 o1;
o1 = new Out1();
o1.M(ref x);
System.Console.Write(x); // 1
o1 = new Ref2();
o1.M(ref x);
System.Console.Write(x); // 3
o1 = new Out2();
o1.M(ref x);
System.Console.WriteLine(x); // 3
Ref2 r2;
r2 = new Ref2();
r2.M(ref x);
System.Console.Write(x); // 3
r2 = new Out2();
r2.M(ref x);
System.Console.WriteLine(x); // 3
Out2 o2;
o2 = new Out2();
o2.M(ref x);
System.Console.WriteLine(x); // 3
o1 = new Out1();
o1.M(out x);
System.Console.Write(x); // 2
o1 = new Ref2();
o1.M(out x);
System.Console.Write(x); // 2
o1 = new Out2();
o1.M(out x);
System.Console.WriteLine(x); // 4
r2 = new Ref2();
r2.M(out x);
System.Console.Write(x); // 2
r2 = new Out2();
r2.M(out x);
System.Console.WriteLine(x); // 4
o2 = new Out2();
o2.M(out x);
System.Console.WriteLine(x); // 4
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
1133
133
33
3
224
24
4
");
}
[Fact]
public void TestGeneratingLocals()
{
var source = @"
using System.Globalization;
class C
{
public static void Main()
{
int i = 0, j, k = 2147483647;
long l = 0, m = 9200000000000000000L;
int b = -10;
byte c = 200;
float f = 3.14159F;
double d = 2.71828;
string s = ""abcdef"";
bool x = true;
System.Console.WriteLine(i);
System.Console.WriteLine(k);
System.Console.WriteLine(b);
System.Console.WriteLine(c);
System.Console.WriteLine(f.ToString(CultureInfo.InvariantCulture));
System.Console.WriteLine(d.ToString(CultureInfo.InvariantCulture));
System.Console.WriteLine(s);
System.Console.WriteLine(x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
0
2147483647
-10
200
3.14159
2.71828
abcdef
True
");
compilation.VerifyIL("C.Main", """
{
// Code size 115 (0x73)
.maxstack 2
.locals init (int V_0, //i
int V_1, //k
byte V_2, //c
float V_3, //f
double V_4, //d
string V_5, //s
bool V_6) //x
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4 0x7fffffff
IL_0007: stloc.1
IL_0008: ldc.i4.s -10
IL_000a: ldc.i4 0xc8
IL_000f: stloc.2
IL_0010: ldc.r4 3.14159
IL_0015: stloc.3
IL_0016: ldc.r8 2.71828
IL_001f: stloc.s V_4
IL_0021: ldstr "abcdef"
IL_0026: stloc.s V_5
IL_0028: ldc.i4.1
IL_0029: stloc.s V_6
IL_002b: ldloc.0
IL_002c: call "void System.Console.WriteLine(int)"
IL_0031: ldloc.1
IL_0032: call "void System.Console.WriteLine(int)"
IL_0037: call "void System.Console.WriteLine(int)"
IL_003c: ldloc.2
IL_003d: call "void System.Console.WriteLine(int)"
IL_0042: ldloca.s V_3
IL_0044: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_0049: call "string float.ToString(System.IFormatProvider)"
IL_004e: call "void System.Console.WriteLine(string)"
IL_0053: ldloca.s V_4
IL_0055: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_005a: call "string double.ToString(System.IFormatProvider)"
IL_005f: call "void System.Console.WriteLine(string)"
IL_0064: ldloc.s V_5
IL_0066: call "void System.Console.WriteLine(string)"
IL_006b: ldloc.s V_6
IL_006d: call "void System.Console.WriteLine(bool)"
IL_0072: ret
}
""");
}
[WorkItem(546749, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546749")]
[Fact()]
public void TestToStringOnStruct()
{
var il = @"
.class sequential ansi sealed public Struct1
extends [mscorlib]System.ValueType
{
.method public hidebysig virtual instance string
ToString() cil managed
{
// Code size 11 (0xb)
.maxstack 1
.locals init (string V_0)
IL_0000: nop
IL_0001: ldstr ""Struct1 ""
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
}
}
.class sequential ansi sealed public Struct2
extends [mscorlib]System.ValueType
{
.method public strict virtual instance string
ToString() cil managed
{
// Code size 11 (0xb)
.maxstack 1
.locals init (string V_0)
IL_0000: nop
IL_0001: ldstr ""Struct2 ""
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
}
}
";
var source = @"
using System;
class Clazz
{
public static void Main(string[] args)
{
Struct1 s1 = new Struct1();
Console.Write(s1.ToString());
Struct2 s2 = new Struct2();
Console.Write(s2.ToString());
}
}
";
var compilation = CreateCompilationWithILAndMscorlib40(source, il, TargetFramework.Mscorlib461, options: TestOptions.ReleaseExe);
var result = CompileAndVerify(compilation, expectedOutput: "Struct1 Struct2 ");
result.VerifyIL("Clazz.Main", @"
{
// Code size 47 (0x2f)
.maxstack 1
.locals init (Struct1 V_0, //s1
Struct2 V_1) //s2
IL_0000: ldloca.s V_0
IL_0002: initobj ""Struct1""
IL_0008: ldloca.s V_0
IL_000a: constrained. ""Struct1""
IL_0010: callvirt ""string object.ToString()""
IL_0015: call ""void System.Console.Write(string)""
IL_001a: ldloca.s V_1
IL_001c: initobj ""Struct2""
IL_0022: ldloca.s V_1
IL_0024: call ""string Struct2.ToString()""
IL_0029: call ""void System.Console.Write(string)""
IL_002e: ret
}
");
}
[Fact, WorkItem(543499, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543499")]
public void TestGeneratingImplicitConstructor()
{
var source = @"
public class H
{
public static void Main()
{
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("H..ctor",
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""object..ctor()""
IL_0006: ret
}
");
}
[Fact, WorkItem(543499, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543499")]
public void TestGeneratingImplicitStaticConstructor()
{
var source = @"
public class H
{
public static bool value = false;
public static void Main()
{
bool val = value;
}
}
";
CompileAndVerify(
source,
symbolValidator: validator,
options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
void validator(ModuleSymbol module)
{
var type = module.ContainingAssembly.GetTypeByMetadataName("H");
Assert.Null(type.GetMember(".cctor"));
}
}
[Fact]
public void TestGeneratingStaticMethod()
{
var source = @"
class C
{
void M()
{
System.Console.WriteLine(123);
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldc.i4.s 123
IL_0002: call ""void System.Console.WriteLine(int)""
IL_0007: ret
}
");
}
[Fact]
public void TestUncheckedNumericConversions()
{
var source = @"
class C
{
void M()
{
sbyte local_sbyte = (sbyte)0;
byte local_byte = (byte)0;
short local_short = (short)0;
ushort local_ushort = (ushort)0;
int local_int = (int)0;
uint local_uint = (uint)0;
long local_long = (long)0;
ulong local_ulong = (ulong)0;
char local_char = (char)0;
float local_float = (float)0;
double local_double = (double)0;
local_sbyte = (sbyte)local_sbyte;
local_sbyte = (sbyte)local_byte;
local_sbyte = (sbyte)local_short;
local_sbyte = (sbyte)local_ushort;
local_sbyte = (sbyte)local_int;
local_sbyte = (sbyte)local_uint;
local_sbyte = (sbyte)local_long;
local_sbyte = (sbyte)local_ulong;
local_sbyte = (sbyte)local_char;
local_sbyte = (sbyte)local_float;
local_sbyte = (sbyte)local_double;
local_byte = (byte)local_sbyte;
local_byte = (byte)local_byte;
local_byte = (byte)local_short;
local_byte = (byte)local_ushort;
local_byte = (byte)local_int;
local_byte = (byte)local_uint;
local_byte = (byte)local_long;
local_byte = (byte)local_ulong;
local_byte = (byte)local_char;
local_byte = (byte)local_float;
local_byte = (byte)local_double;
local_short = (short)local_sbyte;
local_short = (short)local_byte;
local_short = (short)local_short;
local_short = (short)local_ushort;
local_short = (short)local_int;
local_short = (short)local_uint;
local_short = (short)local_long;
local_short = (short)local_ulong;
local_short = (short)local_char;
local_short = (short)local_float;
local_short = (short)local_double;
local_ushort = (ushort)local_sbyte;
local_ushort = (ushort)local_byte;
local_ushort = (ushort)local_short;
local_ushort = (ushort)local_ushort;
local_ushort = (ushort)local_int;
local_ushort = (ushort)local_uint;
local_ushort = (ushort)local_long;
local_ushort = (ushort)local_ulong;
local_ushort = (ushort)local_char;
local_ushort = (ushort)local_float;
local_ushort = (ushort)local_double;
local_int = (int)local_sbyte;
local_int = (int)local_byte;
local_int = (int)local_short;
local_int = (int)local_ushort;
local_int = (int)local_int;
local_int = (int)local_uint;
local_int = (int)local_long;
local_int = (int)local_ulong;
local_int = (int)local_char;
local_int = (int)local_float;
local_int = (int)local_double;
local_uint = (uint)local_sbyte;
local_uint = (uint)local_byte;
local_uint = (uint)local_short;
local_uint = (uint)local_ushort;
local_uint = (uint)local_int;
local_uint = (uint)local_uint;
local_uint = (uint)local_long;
local_uint = (uint)local_ulong;
local_uint = (uint)local_char;
local_uint = (uint)local_float;
local_uint = (uint)local_double;
local_long = (long)local_sbyte;
local_long = (long)local_byte;
local_long = (long)local_short;
local_long = (long)local_ushort;
local_long = (long)local_int;
local_long = (long)local_uint;
local_long = (long)local_long;
local_long = (long)local_ulong;
local_long = (long)local_char;
local_long = (long)local_float;
local_long = (long)local_double;
local_ulong = (ulong)local_sbyte;
local_ulong = (ulong)local_byte;
local_ulong = (ulong)local_short;
local_ulong = (ulong)local_ushort;
local_ulong = (ulong)local_int;
local_ulong = (ulong)local_uint;
local_ulong = (ulong)local_long;
local_ulong = (ulong)local_ulong;
local_ulong = (ulong)local_char;
local_ulong = (ulong)local_float;
local_ulong = (ulong)local_double;
local_char = (char)local_sbyte;
local_char = (char)local_byte;
local_char = (char)local_short;
local_char = (char)local_ushort;
local_char = (char)local_int;
local_char = (char)local_uint;
local_char = (char)local_long;
local_char = (char)local_ulong;
local_char = (char)local_char;
local_char = (char)local_float;
local_char = (char)local_double;
local_float = (float)local_sbyte;
local_float = (float)local_byte;
local_float = (float)local_short;
local_float = (float)local_ushort;
local_float = (float)local_int;
local_float = (float)local_uint;
local_float = (float)local_long;
local_float = (float)local_ulong;
local_float = (float)local_char;
local_float = (float)local_float;
local_float = (float)local_double;
local_double = (double)local_sbyte;
local_double = (double)local_byte;
local_double = (double)local_short;
local_double = (double)local_ushort;
local_double = (double)local_int;
local_double = (double)local_uint;
local_double = (double)local_long;
local_double = (double)local_ulong;
local_double = (double)local_char;
local_double = (double)local_float;
local_double = (double)local_double;
}
}
";
var compilation = CompileAndVerify(source);
// TODO: There is unusual behavior here in the loading of constants, e.g. that they load
// the int 0 and then do a conversion if appropriate, rather than say just loading a float
// 0.0 to begin with. This is because the conversions in initialization expressions don't
// fold the 0 literal to a 0.0 constant in place. We might need to look at that; but after
// the initialization of the locals this IL is otherwise correct.
compilation.VerifyIL("C.M",
@"{
// Code size 536 (0x218)
.maxstack 1
.locals init (sbyte V_0, //local_sbyte
byte V_1, //local_byte
short V_2, //local_short
ushort V_3, //local_ushort
int V_4, //local_int
uint V_5, //local_uint
long V_6, //local_long
ulong V_7, //local_ulong
char V_8, //local_char
float V_9, //local_float
double V_10) //local_double
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4.0
IL_0003: stloc.1
IL_0004: ldc.i4.0
IL_0005: stloc.2
IL_0006: ldc.i4.0
IL_0007: stloc.3
IL_0008: ldc.i4.0
IL_0009: stloc.s V_4
IL_000b: ldc.i4.0
IL_000c: stloc.s V_5
IL_000e: ldc.i4.0
IL_000f: conv.i8
IL_0010: stloc.s V_6
IL_0012: ldc.i4.0
IL_0013: conv.i8
IL_0014: stloc.s V_7
IL_0016: ldc.i4.0
IL_0017: stloc.s V_8
IL_0019: ldc.r4 0
IL_001e: stloc.s V_9
IL_0020: ldc.r8 0
IL_0029: stloc.s V_10
IL_002b: ldloc.0
IL_002c: stloc.0
IL_002d: ldloc.1
IL_002e: conv.i1
IL_002f: stloc.0
IL_0030: ldloc.2
IL_0031: conv.i1
IL_0032: stloc.0
IL_0033: ldloc.3
IL_0034: conv.i1
IL_0035: stloc.0
IL_0036: ldloc.s V_4
IL_0038: conv.i1
IL_0039: stloc.0
IL_003a: ldloc.s V_5
IL_003c: conv.i1
IL_003d: stloc.0
IL_003e: ldloc.s V_6
IL_0040: conv.i1
IL_0041: stloc.0
IL_0042: ldloc.s V_7
IL_0044: conv.i1
IL_0045: stloc.0
IL_0046: ldloc.s V_8
IL_0048: conv.i1
IL_0049: stloc.0
IL_004a: ldloc.s V_9
IL_004c: conv.i1
IL_004d: stloc.0
IL_004e: ldloc.s V_10
IL_0050: conv.i1
IL_0051: stloc.0
IL_0052: ldloc.0
IL_0053: conv.u1
IL_0054: stloc.1
IL_0055: ldloc.1
IL_0056: stloc.1
IL_0057: ldloc.2
IL_0058: conv.u1
IL_0059: stloc.1
IL_005a: ldloc.3
IL_005b: conv.u1
IL_005c: stloc.1
IL_005d: ldloc.s V_4
IL_005f: conv.u1
IL_0060: stloc.1
IL_0061: ldloc.s V_5
IL_0063: conv.u1
IL_0064: stloc.1
IL_0065: ldloc.s V_6
IL_0067: conv.u1
IL_0068: stloc.1
IL_0069: ldloc.s V_7
IL_006b: conv.u1
IL_006c: stloc.1
IL_006d: ldloc.s V_8
IL_006f: conv.u1
IL_0070: stloc.1
IL_0071: ldloc.s V_9
IL_0073: conv.u1
IL_0074: stloc.1
IL_0075: ldloc.s V_10
IL_0077: conv.u1
IL_0078: stloc.1
IL_0079: ldloc.0
IL_007a: stloc.2
IL_007b: ldloc.1
IL_007c: stloc.2
IL_007d: ldloc.2
IL_007e: stloc.2
IL_007f: ldloc.3
IL_0080: conv.i2
IL_0081: stloc.2
IL_0082: ldloc.s V_4
IL_0084: conv.i2
IL_0085: stloc.2
IL_0086: ldloc.s V_5
IL_0088: conv.i2
IL_0089: stloc.2
IL_008a: ldloc.s V_6
IL_008c: conv.i2
IL_008d: stloc.2
IL_008e: ldloc.s V_7
IL_0090: conv.i2
IL_0091: stloc.2
IL_0092: ldloc.s V_8
IL_0094: conv.i2
IL_0095: stloc.2
IL_0096: ldloc.s V_9
IL_0098: conv.i2
IL_0099: stloc.2
IL_009a: ldloc.s V_10
IL_009c: conv.i2
IL_009d: stloc.2
IL_009e: ldloc.0
IL_009f: conv.u2
IL_00a0: stloc.3
IL_00a1: ldloc.1
IL_00a2: stloc.3
IL_00a3: ldloc.2
IL_00a4: conv.u2
IL_00a5: stloc.3
IL_00a6: ldloc.3
IL_00a7: stloc.3
IL_00a8: ldloc.s V_4
IL_00aa: conv.u2
IL_00ab: stloc.3
IL_00ac: ldloc.s V_5
IL_00ae: conv.u2
IL_00af: stloc.3
IL_00b0: ldloc.s V_6
IL_00b2: conv.u2
IL_00b3: stloc.3
IL_00b4: ldloc.s V_7
IL_00b6: conv.u2
IL_00b7: stloc.3
IL_00b8: ldloc.s V_8
IL_00ba: stloc.3
IL_00bb: ldloc.s V_9
IL_00bd: conv.u2
IL_00be: stloc.3
IL_00bf: ldloc.s V_10
IL_00c1: conv.u2
IL_00c2: stloc.3
IL_00c3: ldloc.0
IL_00c4: stloc.s V_4
IL_00c6: ldloc.1
IL_00c7: stloc.s V_4
IL_00c9: ldloc.2
IL_00ca: stloc.s V_4
IL_00cc: ldloc.3
IL_00cd: stloc.s V_4
IL_00cf: ldloc.s V_4
IL_00d1: stloc.s V_4
IL_00d3: ldloc.s V_5
IL_00d5: stloc.s V_4
IL_00d7: ldloc.s V_6
IL_00d9: conv.i4
IL_00da: stloc.s V_4
IL_00dc: ldloc.s V_7
IL_00de: conv.i4
IL_00df: stloc.s V_4
IL_00e1: ldloc.s V_8
IL_00e3: stloc.s V_4
IL_00e5: ldloc.s V_9
IL_00e7: conv.i4
IL_00e8: stloc.s V_4
IL_00ea: ldloc.s V_10
IL_00ec: conv.i4
IL_00ed: stloc.s V_4
IL_00ef: ldloc.0
IL_00f0: stloc.s V_5
IL_00f2: ldloc.1
IL_00f3: stloc.s V_5
IL_00f5: ldloc.2
IL_00f6: stloc.s V_5
IL_00f8: ldloc.3
IL_00f9: stloc.s V_5
IL_00fb: ldloc.s V_4
IL_00fd: stloc.s V_5
IL_00ff: ldloc.s V_5
IL_0101: stloc.s V_5
IL_0103: ldloc.s V_6
IL_0105: conv.u4
IL_0106: stloc.s V_5
IL_0108: ldloc.s V_7
IL_010a: conv.u4
IL_010b: stloc.s V_5
IL_010d: ldloc.s V_8
IL_010f: stloc.s V_5
IL_0111: ldloc.s V_9
IL_0113: conv.u4
IL_0114: stloc.s V_5
IL_0116: ldloc.s V_10
IL_0118: conv.u4
IL_0119: stloc.s V_5
IL_011b: ldloc.0
IL_011c: conv.i8
IL_011d: stloc.s V_6
IL_011f: ldloc.1
IL_0120: conv.u8
IL_0121: stloc.s V_6
IL_0123: ldloc.2
IL_0124: conv.i8
IL_0125: stloc.s V_6
IL_0127: ldloc.3
IL_0128: conv.u8
IL_0129: stloc.s V_6
IL_012b: ldloc.s V_4
IL_012d: conv.i8
IL_012e: stloc.s V_6
IL_0130: ldloc.s V_5
IL_0132: conv.u8
IL_0133: stloc.s V_6
IL_0135: ldloc.s V_6
IL_0137: stloc.s V_6
IL_0139: ldloc.s V_7
IL_013b: stloc.s V_6
IL_013d: ldloc.s V_8
IL_013f: conv.u8
IL_0140: stloc.s V_6
IL_0142: ldloc.s V_9
IL_0144: conv.i8
IL_0145: stloc.s V_6
IL_0147: ldloc.s V_10
IL_0149: conv.i8
IL_014a: stloc.s V_6
IL_014c: ldloc.0
IL_014d: conv.i8
IL_014e: stloc.s V_7
IL_0150: ldloc.1
IL_0151: conv.u8
IL_0152: stloc.s V_7
IL_0154: ldloc.2
IL_0155: conv.i8
IL_0156: stloc.s V_7
IL_0158: ldloc.3
IL_0159: conv.u8
IL_015a: stloc.s V_7
IL_015c: ldloc.s V_4
IL_015e: conv.i8
IL_015f: stloc.s V_7
IL_0161: ldloc.s V_5
IL_0163: conv.u8
IL_0164: stloc.s V_7
IL_0166: ldloc.s V_6
IL_0168: stloc.s V_7
IL_016a: ldloc.s V_7
IL_016c: stloc.s V_7
IL_016e: ldloc.s V_8
IL_0170: conv.u8
IL_0171: stloc.s V_7
IL_0173: ldloc.s V_9
IL_0175: conv.u8
IL_0176: stloc.s V_7
IL_0178: ldloc.s V_10
IL_017a: conv.u8
IL_017b: stloc.s V_7
IL_017d: ldloc.0
IL_017e: conv.u2
IL_017f: stloc.s V_8
IL_0181: ldloc.1
IL_0182: stloc.s V_8
IL_0184: ldloc.2
IL_0185: conv.u2
IL_0186: stloc.s V_8
IL_0188: ldloc.3
IL_0189: stloc.s V_8
IL_018b: ldloc.s V_4
IL_018d: conv.u2
IL_018e: stloc.s V_8
IL_0190: ldloc.s V_5
IL_0192: conv.u2
IL_0193: stloc.s V_8
IL_0195: ldloc.s V_6
IL_0197: conv.u2
IL_0198: stloc.s V_8
IL_019a: ldloc.s V_7
IL_019c: conv.u2
IL_019d: stloc.s V_8
IL_019f: ldloc.s V_8
IL_01a1: stloc.s V_8
IL_01a3: ldloc.s V_9
IL_01a5: conv.u2
IL_01a6: stloc.s V_8
IL_01a8: ldloc.s V_10
IL_01aa: conv.u2
IL_01ab: stloc.s V_8
IL_01ad: ldloc.0
IL_01ae: conv.r4
IL_01af: stloc.s V_9
IL_01b1: ldloc.1
IL_01b2: conv.r4
IL_01b3: stloc.s V_9
IL_01b5: ldloc.2
IL_01b6: conv.r4
IL_01b7: stloc.s V_9
IL_01b9: ldloc.3
IL_01ba: conv.r4
IL_01bb: stloc.s V_9
IL_01bd: ldloc.s V_4
IL_01bf: conv.r4
IL_01c0: stloc.s V_9
IL_01c2: ldloc.s V_5
IL_01c4: conv.r.un
IL_01c5: conv.r4
IL_01c6: stloc.s V_9
IL_01c8: ldloc.s V_6
IL_01ca: conv.r4
IL_01cb: stloc.s V_9
IL_01cd: ldloc.s V_7
IL_01cf: conv.r.un
IL_01d0: conv.r4
IL_01d1: stloc.s V_9
IL_01d3: ldloc.s V_8
IL_01d5: conv.r4
IL_01d6: stloc.s V_9
IL_01d8: ldloc.s V_9
IL_01da: conv.r4
IL_01db: stloc.s V_9
IL_01dd: ldloc.s V_10
IL_01df: conv.r4
IL_01e0: stloc.s V_9
IL_01e2: ldloc.0
IL_01e3: conv.r8
IL_01e4: stloc.s V_10
IL_01e6: ldloc.1
IL_01e7: conv.r8
IL_01e8: stloc.s V_10
IL_01ea: ldloc.2
IL_01eb: conv.r8
IL_01ec: stloc.s V_10
IL_01ee: ldloc.3
IL_01ef: conv.r8
IL_01f0: stloc.s V_10
IL_01f2: ldloc.s V_4
IL_01f4: conv.r8
IL_01f5: stloc.s V_10
IL_01f7: ldloc.s V_5
IL_01f9: conv.r.un
IL_01fa: conv.r8
IL_01fb: stloc.s V_10
IL_01fd: ldloc.s V_6
IL_01ff: conv.r8
IL_0200: stloc.s V_10
IL_0202: ldloc.s V_7
IL_0204: conv.r.un
IL_0205: conv.r8
IL_0206: stloc.s V_10
IL_0208: ldloc.s V_8
IL_020a: conv.r8
IL_020b: stloc.s V_10
IL_020d: ldloc.s V_9
IL_020f: conv.r8
IL_0210: stloc.s V_10
IL_0212: ldloc.s V_10
IL_0214: conv.r8
IL_0215: stloc.s V_10
IL_0217: ret
}
");
}
[Fact]
public void TestGeneratingClassConstructor()
{
var source = @"
class C
{
void M()
{
new System.Collections.ArrayList(4);
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldc.i4.4
IL_0001: newobj ""System.Collections.ArrayList..ctor(int)""
IL_0006: pop
IL_0007: ret
}
");
}
[Fact]
public void TestMaxStack()
{
var source = @"
class C
{
static void Long(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15, int i16, int i17, int i18, int i19, int i20) { }
void M()
{
Long(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 38 (0x26)
.maxstack 20
IL_0000: ldc.i4.1
IL_0001: ldc.i4.2
IL_0002: ldc.i4.3
IL_0003: ldc.i4.4
IL_0004: ldc.i4.5
IL_0005: ldc.i4.6
IL_0006: ldc.i4.7
IL_0007: ldc.i4.8
IL_0008: ldc.i4.s 9
IL_000a: ldc.i4.s 10
IL_000c: ldc.i4.s 11
IL_000e: ldc.i4.s 12
IL_0010: ldc.i4.s 13
IL_0012: ldc.i4.s 14
IL_0014: ldc.i4.s 15
IL_0016: ldc.i4.s 16
IL_0018: ldc.i4.s 17
IL_001a: ldc.i4.s 18
IL_001c: ldc.i4.s 19
IL_001e: ldc.i4.s 20
IL_0020: call ""void C.Long(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int)""
IL_0025: ret
}
");
}
[Fact]
public void TestReturn()
{
var source = @"
class C
{
double M()
{
int x = 3;
return x;
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldc.i4.3
IL_0001: conv.r8
IL_0002: ret
}
");
}
[Fact]
public void TestBranch()
{
var source = @"
class C
{
static void M()
{
bool b = false;
if (b)
{
System.Console.WriteLine(""1"");
}
else
{
System.Console.WriteLine(""2"");
}
while (b)
{
System.Console.WriteLine(""3"");
b = false;
}
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 45 (0x2d)
.maxstack 1
.locals init (bool V_0) //b
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: brfalse.s IL_0011
IL_0005: ldstr ""1""
IL_000a: call ""void System.Console.WriteLine(string)""
IL_000f: br.s IL_0029
IL_0011: ldstr ""2""
IL_0016: call ""void System.Console.WriteLine(string)""
IL_001b: br.s IL_0029
IL_001d: ldstr ""3""
IL_0022: call ""void System.Console.WriteLine(string)""
IL_0027: ldc.i4.0
IL_0028: stloc.0
IL_0029: ldloc.0
IL_002a: brtrue.s IL_001d
IL_002c: ret
}
");
}
[Fact]
public void TestConst()
{
string source = @"
public class D
{
static int M()
{
return 42;
}
public static void Main()
{
System.Console.Write(M());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "42");
compilation.VerifyIL("D.M",
@"{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldc.i4.s 42
IL_0002: ret
}
");
}
[Fact]
public void TestArg()
{
string source = @"
public class D
{
static int M(int x)
{
return x;
}
public static void Main()
{
System.Console.Write(M(42));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "42");
compilation.VerifyIL("D.M",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}
");
}
[Fact]
public void TestArgs()
{
string source = @"
public class C
{
static int M(int x, int y, int z)
{
return y;
}
public static void Main()
{
System.Console.Write(M(0, 42, 1));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "42");
compilation.VerifyIL("C.M",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.1
IL_0001: ret
}
");
}
[Fact]
public void TestLocalAccess()
{
string source = @"
public class C
{
static int M(bool getLocal, int arg)
{
int y = 123;
System.Exception ex; // just for fun
return y;
}
public static void Main()
{
System.Console.Write(M(false, 42));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "123");
compilation.VerifyIL("C.M",
@"{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldc.i4.s 123
IL_0002: ret
}
");
}
[Fact]
public void TestConditionalLocalAccess()
{
string source = @"
public class D
{
static int M(bool getLocal, int arg)
{
System.Exception ex; // just for fun
int y = 123;
if (getLocal)
{
return y;
}
else
{
return arg;
}
}
public static void Main()
{
System.Console.Write(M(false, 42));
System.Console.Write(M(true, 42));
}
}
";
CompileAndVerify(source, expectedOutput: "42123").
VerifyIL("D.M",
@"{
// Code size 10 (0xa)
.maxstack 1
.locals init (int V_0) //y
IL_0000: ldc.i4.s 123
IL_0002: stloc.0
IL_0003: ldarg.0
IL_0004: brfalse.s IL_0008
IL_0006: ldloc.0
IL_0007: ret
IL_0008: ldarg.1
IL_0009: ret
}
");
var v = CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: "42123");
v.VerifyIL("D.M",
@"{
// Code size 21 (0x15)
.maxstack 1
.locals init (System.Exception V_0, //ex
int V_1, //y
bool V_2,
int V_3)
-IL_0000: nop
-IL_0001: ldc.i4.s 123
IL_0003: stloc.1
-IL_0004: ldarg.0
IL_0005: stloc.2
~IL_0006: ldloc.2
IL_0007: brfalse.s IL_000e
-IL_0009: nop
-IL_000a: ldloc.1
IL_000b: stloc.3
IL_000c: br.s IL_0013
-IL_000e: nop
-IL_000f: ldarg.1
IL_0010: stloc.3
IL_0011: br.s IL_0013
-IL_0013: ldloc.3
IL_0014: ret
}
", sequencePoints: "D.M");
}
[Fact]
public void TestAssignRefNull()
{
string source = @"
public class D
{
static System.Exception M()
{
System.Exception y = null;
return y;
}
public static void Main()
{
System.Console.Write(M());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "");
compilation.VerifyIL("D.M",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldnull
IL_0001: ret
}
");
}
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.TestExecutionNeedsWindowsTypes)]
public void TestAssignIdentity()
{
string source = @"
public class D
{
static System.Object M()
{
System.AppDomain y = System.AppDomain.CreateDomain(""qq"");
return y;
}
public static void Main()
{
System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
try
{
System.Console.Write(M());
}
finally
{
System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
Name:qq
There are no context policies.
");
compilation.VerifyIL("D.M",
@"{
// Code size 11 (0xb)
.maxstack 1
IL_0000: ldstr ""qq""
IL_0005: call ""System.AppDomain System.AppDomain.CreateDomain(string)""
IL_000a: ret
}
");
}
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.TestExecutionNeedsWindowsTypes)]
public void TestRefCast()
{
string source = @"
public class D
{
static System.AppDomain M()
{
object y = System.AppDomain.CreateDomain(""qq"");
System.AppDomain z = (System.AppDomain)y;
return z;
}
public static void Main()
{
System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
try
{
System.Console.Write(M());
}
finally
{
System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
Name:qq
There are no context policies.
");
compilation.VerifyIL("D.M",
@"{
// Code size 16 (0x10)
.maxstack 1
IL_0000: ldstr ""qq""
IL_0005: call ""System.AppDomain System.AppDomain.CreateDomain(string)""
IL_000a: castclass ""System.AppDomain""
IL_000f: ret
}
");
}
[Fact]
public void TestRefCtor()
{
string source = @"
public class D
{
static System.Exception M()
{
System.Exception y = new System.Exception(""hello"");
return y;
}
public static void Main()
{
System.Console.Write(M());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"System.Exception: hello");
compilation.VerifyIL("D.M",
@"{
// Code size 11 (0xb)
.maxstack 1
IL_0000: ldstr ""hello""
IL_0005: newobj ""System.Exception..ctor(string)""
IL_000a: ret
}");
}
[Fact]
public void MethodParameterAccess()
{
string source = @"
public class D
{
public class Moo
{
public Moo()
{
}
public string Boo(int x, string y, object z)
{
return y;
}
}
public static void Main()
{
Moo obj = new Moo();
string s = obj.Boo(1, ""hi"", obj);
System.Console.Write(s);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"hi");
compilation.VerifyIL("D.Moo.Boo",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.2
IL_0001: ret
}
");
}
[Fact]
public void PropertyGet()
{
string source = @"
class C
{
int P { get { return 0; } }
void M()
{
int p = P;
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""int C.P.get""
IL_0006: pop
IL_0007: ret
}
");
}
[Fact]
public void PropertyGetAndSet()
{
string source = @"
class C
{
private int p;
C This { get { return this; } }
string S { get { return string.Empty; } }
int P
{
get { return p; }
set { p = value; }
}
void M(string s)
{
This.This.P = This.S.Length;
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 33 (0x21)
.maxstack 2
IL_0000: ldarg.0
IL_0001: call ""C C.This.get""
IL_0006: callvirt ""C C.This.get""
IL_000b: ldarg.0
IL_000c: call ""C C.This.get""
IL_0011: callvirt ""string C.S.get""
IL_0016: callvirt ""int string.Length.get""
IL_001b: callvirt ""void C.P.set""
IL_0020: ret
}
");
}
[Fact]
public void PropertyStaticGetAndSet()
{
string source = @"
class C
{
private static string s;
public static string S
{
get { return s; }
set { s = value; }
}
static void Main()
{
C.S = ""S"";
System.Console.Write(C.S);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "S");
compilation.VerifyIL("C.Main",
@"{
// Code size 21 (0x15)
.maxstack 1
IL_0000: ldstr ""S""
IL_0005: call ""void C.S.set""
IL_000a: call ""string C.S.get""
IL_000f: call ""void System.Console.Write(string)""
IL_0014: ret
}
");
}
[Fact]
public void PropertyAutoGetAndSet()
{
string source = @"
class C
{
int P { get; set; }
static void Main()
{
C c = new C();
c.P = 2;
System.Console.Write(""{0}"", c.P);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "2");
compilation.VerifyIL("C.P.set",
@"{
// Code size 8 (0x8)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld ""int C.<P>k__BackingField""
IL_0007: ret
}
");
}
[Fact]
public void PropertyStaticAutoGetAndSet()
{
string source = @"
class C
{
static string S { get; set; }
static void Main()
{
S = ""S"";
System.Console.Write(S);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "S");
compilation.VerifyIL("C.S.set",
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: stsfld ""string C.<S>k__BackingField""
IL_0006: ret
}
");
}
[Fact]
public void PropertyOfTGetAndSet()
{
string source = @"
class C<T>
{
private T t;
public T T2
{
get { return t; }
set { t = value; }
}
}
class P
{
static void Main()
{
C<string> c = new C<string>();
c.T2 = ""T2"";
System.Console.Write(c.T2);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "T2");
compilation.VerifyIL("P.Main",
@"{
// Code size 27 (0x1b)
.maxstack 3
IL_0000: newobj ""C<string>..ctor()""
IL_0005: dup
IL_0006: ldstr ""T2""
IL_000b: callvirt ""void C<string>.T2.set""
IL_0010: callvirt ""string C<string>.T2.get""
IL_0015: call ""void System.Console.Write(string)""
IL_001a: ret
}
");
}
[Fact]
public void PropertyStaticOfTGetAndSet()
{
string source = @"
class C<T>
{
public static string S { get; set; }
public static T T2 { get; set; }
}
class P
{
static void Main()
{
C<int>.S = ""C<int>.S"";
C<string>.S = ""C<string>.S"";
C<string>.T2 = ""C<string>.T2"";
System.Console.Write(""{0};{1};{2}"", C<int>.S, C<string>.S, C<string>.T2);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "C<int>.S;C<string>.S;C<string>.T2");
compilation.VerifyIL("C<T>.S.set",
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: stsfld ""string C<T>.<S>k__BackingField""
IL_0006: ret
}
");
}
[WorkItem(538677, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538677")]
[Fact]
public void PropertyAssignmentExpression()
{
string source = @"
class C
{
static C F() { return new C(); }
static string P { set { } }
string Q { set { } }
static void Main()
{
string p = P = ""p"";
string q = F().Q = ""q"";
System.Console.Write(""{0}, {1}"", p, q);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "p, q");
compilation.VerifyIL("C.Main",
@"{
// Code size 44 (0x2c)
.maxstack 3
.locals init (string V_0, //p
string V_1, //q
string V_2)
IL_0000: ldstr ""p""
IL_0005: dup
IL_0006: call ""void C.P.set""
IL_000b: stloc.0
IL_000c: call ""C C.F()""
IL_0011: ldstr ""q""
IL_0016: dup
IL_0017: stloc.2
IL_0018: callvirt ""void C.Q.set""
IL_001d: ldloc.2
IL_001e: stloc.1
IL_001f: ldstr ""{0}, {1}""
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: call ""void System.Console.Write(string, object, object)""
IL_002b: ret
}
");
}
[Fact]
public void CallVirtualMethods()
{
string source = @"
abstract class A
{
public virtual void F() { }
public abstract void G();
}
abstract class B : A
{
public abstract override void F();
public override void G() { }
}
class C : B
{
public override void F() { }
}
class D : C
{
public override void G() { }
}
class Program
{
static void M(D d)
{
d.F();
d.G();
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("Program.M",
@"{
// Code size 13 (0xd)
.maxstack 1
IL_0000: ldarg.0
IL_0001: callvirt ""void A.F()""
IL_0006: ldarg.0
IL_0007: callvirt ""void A.G()""
IL_000c: ret
}
");
}
[Fact]
public void CallVirtualProperties()
{
string source = @"
abstract class A
{
public abstract int Q { get; internal set; }
}
abstract class B : A
{
public virtual int P { get; internal set; }
public abstract override int Q { get; internal set; }
}
class C : B
{
public override int P { internal set { } }
public override int Q { get { return 0; } internal set { } }
}
class D : C
{
public override int Q { internal set { } }
}
class E : D
{
public override int P { get { return 0; } }
}
class Program
{
static void M(E e)
{
e.Q = e.P;
e.P = e.Q;
}
}
";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("Program.M",
@"
{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: callvirt ""int B.P.get""
IL_0007: callvirt ""void A.Q.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: callvirt ""int A.Q.get""
IL_0013: callvirt ""void B.P.set""
IL_0018: ret
}
");
}
[Fact]
public void CallBaseMethods()
{
string source = @"
using System;
class A
{
public virtual void M()
{
Console.Write(""A.M, "");
}
public virtual object P
{
get { return null; }
set
{
Console.Write(""A.P, "");
}
}
}
class B : A
{
public override void M()
{
Console.Write(""B.M, "");
}
public override object P
{
get { return null; }
set
{
Console.Write(""B.P, "");
}
}
public void N()
{
this.M();
this.P = 0;
base.M();
base.P = 1;
}
}
class Program
{
static void Main()
{
new B().N();
}
}
";
CompileAndVerify(source, expectedOutput: "B.M, B.P, A.M, A.P, ").
VerifyIL("B.N",
@"{
// Code size 37 (0x25)
.maxstack 2
IL_0000: ldarg.0
IL_0001: callvirt ""void A.M()""
IL_0006: ldarg.0
IL_0007: ldc.i4.0
IL_0008: box ""int""
IL_000d: callvirt ""void A.P.set""
IL_0012: ldarg.0
IL_0013: call ""void A.M()""
IL_0018: ldarg.0
IL_0019: ldc.i4.1
IL_001a: box ""int""
IL_001f: call ""void A.P.set""
IL_0024: ret
}
");
}
[Fact]
public void CallBaseMethods_VirtualSimple()
{
string source = @"
using System;
class A
{
public virtual string M()
{
return ""A.M()"";
}
}
class B : A
{
public override string M()
{
return ""B.M()"";
}
}
class C : B
{
public string Test()
{
return this.M() + "":"" + base.M();
}
}
class D : C
{
public override string M()
{
return ""D.M()"";
}
public new string Test()
{
return this.M() + "":"" + base.M();
}
}
class Program
{
static void Main()
{
Console.Write(new C().Test());
Console.Write("", "");
Console.WriteLine(new D().Test());
}
}";
CompileAndVerify(source, expectedOutput: "B.M():B.M(), D.M():B.M()").
VerifyIL("C.Test",
@"
{
// Code size 23 (0x17)
.maxstack 3
IL_0000: ldarg.0
IL_0001: callvirt ""string A.M()""
IL_0006: ldstr "":""
IL_000b: ldarg.0
IL_000c: call ""string B.M()""
IL_0011: call ""string string.Concat(string, string, string)""
IL_0016: ret
}
").
VerifyIL("D.Test",
@"
{
// Code size 23 (0x17)
.maxstack 3
IL_0000: ldarg.0
IL_0001: callvirt ""string A.M()""
IL_0006: ldstr "":""
IL_000b: ldarg.0
IL_000c: call ""string B.M()""
IL_0011: call ""string string.Concat(string, string, string)""
IL_0016: ret
}
");
}
[Fact]
public void CallBaseProperties_VirtualSimple()
{
string source = @"
using System;
class A
{
public virtual string P
{
get { Console.Write(""A.P.get;""); return null; }
set { Console.Write(""A.P.set;""); }
}
}
class B : A
{
public override string P
{
//get { Console.Write(""B.P.get;""); return null; }
set { Console.Write(""B.P.set;""); }
}
}
class C : B
{
public void Test()
{
this.P = base.P;
base.P = this.P;
}
}
class D : C
{
public override string P
{
get { Console.Write(""D.P.get;""); return null; }
//set { Console.Write(""D.P.set;""); }
}
public new void Test()
{
this.P = base.P;
base.P = this.P;
}
}
class Program
{
static void Main()
{
new C().Test();
Console.WriteLine();
new D().Test();
}
}";
CompileAndVerify(source, expectedOutput: $"A.P.get;B.P.set;A.P.get;B.P.set;{Environment.NewLine}A.P.get;B.P.set;D.P.get;B.P.set;").
VerifyIL("C.Test",
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""string A.P.get""
IL_0007: callvirt ""void A.P.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: callvirt ""string A.P.get""
IL_0013: call ""void B.P.set""
IL_0018: ret
}").
VerifyIL("D.Test",
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""string A.P.get""
IL_0007: callvirt ""void A.P.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: callvirt ""string A.P.get""
IL_0013: call ""void B.P.set""
IL_0018: ret
}
");
}
[Fact]
public void CallBaseMethods_Virtual_WithPrivate()
{
string source = @"
using System;
class A
{
public virtual string M()
{
return ""A.M()"";
}
}
class B : A
{
public override string M()
{
return ""B.M()"";
}
}
class C : B
{
private new string M()
{
return ""C.M()"";
}
public string Test()
{
return this.M() + "":"" + base.M();
}
}
class D : C
{
public override string M()
{
return ""D.M()"";
}
public new string Test()
{
return this.M() + "":"" + base.M();
}
}
class Program
{
static void Main()
{
Console.Write(new C().Test());
Console.Write("", "");
Console.WriteLine(new D().Test());
}
}";
CompileAndVerify(source, expectedOutput: "C.M():B.M(), D.M():B.M()").
VerifyIL("C.Test",
@"
{
// Code size 23 (0x17)
.maxstack 3
IL_0000: ldarg.0
IL_0001: call ""string C.M()""
IL_0006: ldstr "":""
IL_000b: ldarg.0
IL_000c: call ""string B.M()""
IL_0011: call ""string string.Concat(string, string, string)""
IL_0016: ret
}
").
VerifyIL("D.Test",
@"
{
// Code size 23 (0x17)
.maxstack 3
IL_0000: ldarg.0
IL_0001: callvirt ""string A.M()""
IL_0006: ldstr "":""
IL_000b: ldarg.0
IL_000c: call ""string B.M()""
IL_0011: call ""string string.Concat(string, string, string)""
IL_0016: ret
}
");
}
[Fact]
public void CallBaseProperties_Virtual_WithPrivate()
{
string source = @"
using System;
class A
{
public virtual string P
{
get { Console.Write(""A.P.get;""); return null; }
set { Console.Write(""A.P.set;""); }
}
}
class B : A
{
public override string P
{
//get { Console.Write(""B.P.get;""); return null; }
set { Console.Write(""B.P.set;""); }
}
}
class C : B
{
private new string P
{
get { Console.Write(""C.P.get;""); return null; }
set { Console.Write(""C.P.set;""); }
}
public void Test()
{
this.P = base.P;
base.P = this.P;
}
}
class D : C
{
public override string P
{
get { Console.Write(""D.P.get;""); return null; }
//set { Console.Write(""D.P.set;""); }
}
public new void Test()
{
this.P = base.P;
base.P = this.P;
}
}
class Program
{
static void Main()
{
new C().Test();
Console.WriteLine();
new D().Test();
}
}";
CompileAndVerify(source, expectedOutput: $"A.P.get;C.P.set;C.P.get;B.P.set;{Environment.NewLine}A.P.get;B.P.set;D.P.get;B.P.set;").
VerifyIL("C.Test",
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""string A.P.get""
IL_0007: call ""void C.P.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: call ""string C.P.get""
IL_0013: call ""void B.P.set""
IL_0018: ret
}").
VerifyIL("D.Test",
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""string A.P.get""
IL_0007: callvirt ""void A.P.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: callvirt ""string A.P.get""
IL_0013: call ""void B.P.set""
IL_0018: ret
}
");
}
[Fact]
public void CallBaseMethods_NonVirtual_WithPrivate()
{
string source = @"
using System;
class A
{
public string M()
{
return ""A.M()"";
}
}
class B : A
{
public new string M()
{
return ""B.M()"";
}
}
class C : B
{
private new string M()
{
return ""C.M()"";
}
public string Test()
{
return this.M() + "":"" + base.M();
}
}
class D : C
{
public new string M()
{
return ""D.M()"";
}
public new string Test()
{
return this.M() + "":"" + base.M();
}
}
class Program
{
static void Main()
{
Console.Write(new C().Test());
Console.Write("", "");
Console.WriteLine(new D().Test());
}
}";
CompileAndVerify(source, expectedOutput: "C.M():B.M(), D.M():B.M()").
VerifyIL("C.Test",
@"
{
// Code size 23 (0x17)
.maxstack 3
IL_0000: ldarg.0
IL_0001: call ""string C.M()""
IL_0006: ldstr "":""
IL_000b: ldarg.0
IL_000c: call ""string B.M()""
IL_0011: call ""string string.Concat(string, string, string)""
IL_0016: ret
}
").
VerifyIL("D.Test",
@"
{
// Code size 23 (0x17)
.maxstack 3
IL_0000: ldarg.0
IL_0001: call ""string D.M()""
IL_0006: ldstr "":""
IL_000b: ldarg.0
IL_000c: call ""string B.M()""
IL_0011: call ""string string.Concat(string, string, string)""
IL_0016: ret
}
");
}
[Fact]
public void CallBaseProperties_NonVirtual_WithPrivate()
{
string source = @"
using System;
class A
{
public string P
{
get { Console.Write(""A.P.get;""); return null; }
set { Console.Write(""A.P.set;""); }
}
}
class B : A
{
public new string P
{
get { Console.Write(""B.P.get;""); return null; }
set { Console.Write(""B.P.set;""); }
}
}
class C : B
{
private new string P
{
get { Console.Write(""C.P.get;""); return null; }
set { Console.Write(""C.P.set;""); }
}
public void Test()
{
this.P = base.P;
base.P = this.P;
}
}
class D : C
{
public new string P
{
get { Console.Write(""D.P.get;""); return null; }
set { Console.Write(""D.P.set;""); }
}
public new void Test()
{
this.P = base.P;
base.P = this.P;
}
}
class Program
{
static void Main()
{
new C().Test();
Console.WriteLine();
new D().Test();
}
}";
CompileAndVerify(source, expectedOutput: $"B.P.get;C.P.set;C.P.get;B.P.set;{Environment.NewLine}B.P.get;D.P.set;D.P.get;B.P.set;").
VerifyIL("C.Test",
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""string B.P.get""
IL_0007: call ""void C.P.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: call ""string C.P.get""
IL_0013: call ""void B.P.set""
IL_0018: ret
}").
VerifyIL("D.Test",
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""string B.P.get""
IL_0007: call ""void D.P.set""
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: call ""string D.P.get""
IL_0013: call ""void B.P.set""
IL_0018: ret
}
");
}
[Fact]
public void StaticFieldLoad()
{
string source = @"
public class D
{
public static void Main()
{
System.Console.Write(System.Decimal.One);
System.Console.Write(System.Type.Missing);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "1System.Reflection.Missing");
compilation.VerifyIL("D.Main",
@"
{
// Code size 21 (0x15)
.maxstack 1
IL_0000: ldsfld ""decimal decimal.One""
IL_0005: call ""void System.Console.Write(decimal)""
IL_000a: ldsfld ""object System.Type.Missing""
IL_000f: call ""void System.Console.Write(object)""
IL_0014: ret
}");
}
[Fact]
public void ConstFieldLoad()
{
string source = @"
public class D
{
public static void Main()
{
System.Console.Write(System.Int32.MaxValue);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "2147483647");
compilation.VerifyIL("D.Main",
@"{
// Code size 11 (0xb)
.maxstack 1
IL_0000: ldc.i4 0x7fffffff
IL_0005: call ""void System.Console.Write(int)""
IL_000a: ret
}
");
}
[Fact]
public void StaticFieldStore()
{
string source = @"
public class D
{
public class Moo
{
public static int I;
}
public static void Goo()
{
Moo.I = 42;
}
public static void Main()
{
Goo();
System.Console.Write(Moo.I);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "42");
compilation.VerifyIL("D.Goo",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldc.i4.s 42
IL_0002: stsfld ""int D.Moo.I""
IL_0007: ret
}
");
}
[Fact]
public void RefInstanceField()
{
string source = @"
public class D
{
public class Moo
{
public int I;
public Moo()
{
}
}
public static void Main()
{
Moo obj = new Moo();
System.Console.Write(obj.I);
obj.I = 42;
System.Console.Write(obj.I);
obj.I = 7;
System.Console.Write(obj.I);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "0427");
compilation.VerifyIL("D.Main",
@"{
// Code size 53 (0x35)
.maxstack 3
IL_0000: newobj ""D.Moo..ctor()""
IL_0005: dup
IL_0006: ldfld ""int D.Moo.I""
IL_000b: call ""void System.Console.Write(int)""
IL_0010: dup
IL_0011: ldc.i4.s 42
IL_0013: stfld ""int D.Moo.I""
IL_0018: dup
IL_0019: ldfld ""int D.Moo.I""
IL_001e: call ""void System.Console.Write(int)""
IL_0023: dup
IL_0024: ldc.i4.7
IL_0025: stfld ""int D.Moo.I""
IL_002a: ldfld ""int D.Moo.I""
IL_002f: call ""void System.Console.Write(int)""
IL_0034: ret
}
");
}
[Fact]
public void RefInstanceFieldA()
{
string source = @"
public class D
{
public class Moo
{
public int I;
public Moo()
{
}
}
public static void Main()
{
Moo obj = new Moo();
System.Console.Write(obj.I);
obj.I = 42;
System.Console.Write(obj.I);
obj.I = 7;
System.Console.Write(obj.I);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseDebugExe, expectedOutput: "0427");
compilation.VerifyIL("D.Main",
@"
{
// Code size 55 (0x37)
.maxstack 2
.locals init (D.Moo V_0) //obj
IL_0000: newobj ""D.Moo..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldfld ""int D.Moo.I""
IL_000c: call ""void System.Console.Write(int)""
IL_0011: ldloc.0
IL_0012: ldc.i4.s 42
IL_0014: stfld ""int D.Moo.I""
IL_0019: ldloc.0
IL_001a: ldfld ""int D.Moo.I""
IL_001f: call ""void System.Console.Write(int)""
IL_0024: ldloc.0
IL_0025: ldc.i4.7
IL_0026: stfld ""int D.Moo.I""
IL_002b: ldloc.0
IL_002c: ldfld ""int D.Moo.I""
IL_0031: call ""void System.Console.Write(int)""
IL_0036: ret
}
");
}
[Fact]
public void RefStaticField()
{
string source = @"
public class D
{
public class Moo
{
public static int S;
public Moo()
{
}
}
public static void Main()
{
System.Console.Write(Moo.S);
Moo.S = 42;
System.Console.Write(Moo.S);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "042");
compilation.VerifyIL("D.Main",
@"{
// Code size 28 (0x1c)
.maxstack 1
IL_0000: ldsfld ""int D.Moo.S""
IL_0005: call ""void System.Console.Write(int)""
IL_000a: ldc.i4.s 42
IL_000c: stsfld ""int D.Moo.S""
IL_0011: ldsfld ""int D.Moo.S""
IL_0016: call ""void System.Console.Write(int)""
IL_001b: ret
}
");
}
[Fact]
public void AssignExprUsed()
{
string source = @"
public class D
{
public class Moo
{
public int I;
public static int IS;
public Moo()
{
}
}
public static void Main()
{
Moo obj1 = new Moo();
Moo obj2 = new Moo();
int x = 0;
int y = x = obj2.I = Moo.IS = obj1.I = x = 123;
System.Console.Write(Moo.IS);
System.Console.Write(obj1.I);
System.Console.Write(obj2.I);
System.Console.Write(x);
System.Console.Write(y);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "123123123123123");
compilation.VerifyIL("D.Main",
@"{
// Code size 88 (0x58)
.maxstack 4
.locals init (D.Moo V_0, //obj1
D.Moo V_1, //obj2
int V_2, //x
int V_3)
IL_0000: newobj ""D.Moo..ctor()""
IL_0005: stloc.0
IL_0006: newobj ""D.Moo..ctor()""
IL_000b: stloc.1
IL_000c: ldc.i4.0
IL_000d: stloc.2
IL_000e: ldloc.1
IL_000f: ldloc.0
IL_0010: ldc.i4.s 123
IL_0012: dup
IL_0013: stloc.2
IL_0014: dup
IL_0015: stloc.3
IL_0016: stfld ""int D.Moo.I""
IL_001b: ldloc.3
IL_001c: dup
IL_001d: stsfld ""int D.Moo.IS""
IL_0022: dup
IL_0023: stloc.3
IL_0024: stfld ""int D.Moo.I""
IL_0029: ldloc.3
IL_002a: dup
IL_002b: stloc.2
IL_002c: ldsfld ""int D.Moo.IS""
IL_0031: call ""void System.Console.Write(int)""
IL_0036: ldloc.0
IL_0037: ldfld ""int D.Moo.I""
IL_003c: call ""void System.Console.Write(int)""
IL_0041: ldloc.1
IL_0042: ldfld ""int D.Moo.I""
IL_0047: call ""void System.Console.Write(int)""
IL_004c: ldloc.2
IL_004d: call ""void System.Console.Write(int)""
IL_0052: call ""void System.Console.Write(int)""
IL_0057: ret
}");
}
[WorkItem(9229, "DevDiv_Projects/Roslyn")]
[Fact]
public void ArrayAccess()
{
string source = @"
public class D
{
public static void Main()
{
int[] arr = new int[] {111, 222, 333, 444};
System.Console.Write(arr[1]);
arr[1] = arr[2];
System.Console.Write(arr[1]);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"), expectedOutput: "222333");
compilation.VerifyIL("D.Main",
@"{
// Code size 41 (0x29)
.maxstack 4
.locals init (int[] V_0) //arr
IL_0000: ldc.i4.4
IL_0001: newarr ""int""
IL_0006: dup
IL_0007: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=16 <PrivateImplementationDetails>.3A3BFDE71B9585833F60BB15A5652D56C97FE581EBE272B5474558E92A26BE0A""
IL_000c: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: ldc.i4.1
IL_0014: ldelem.i4
IL_0015: call ""void System.Console.Write(int)""
IL_001a: ldloc.0
IL_001b: ldc.i4.1
IL_001c: ldloc.0
IL_001d: ldc.i4.2
IL_001e: ldelem.i4
IL_001f: stelem.i4
IL_0020: ldloc.0
IL_0021: ldc.i4.1
IL_0022: ldelem.i4
IL_0023: call ""void System.Console.Write(int)""
IL_0028: ret
}
");
}
[Fact]
public void ArrayLong()
{
string source = @"
public class D
{
public static void Main()
{
int[] arr = new int[4L];
arr[0L] = 111;
ulong t = 1UL;
arr[t] = 222;
arr[3L] = 333;
System.Console.Write(arr[t].ToString());
t = 3L;
long tl = 2;
arr[tl] = arr[t];
System.Console.Write(arr[tl].ToString());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "222333");
compilation.VerifyIL("D.Main",
@"{
// Code size 89 (0x59)
.maxstack 4
.locals init (int[] V_0, //arr
ulong V_1, //t
long V_2) //tl
IL_0000: ldc.i4.4
IL_0001: conv.i8
IL_0002: conv.ovf.i
IL_0003: newarr ""int""
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.0
IL_000b: conv.i8
IL_000c: conv.ovf.i
IL_000d: ldc.i4.s 111
IL_000f: stelem.i4
IL_0010: ldc.i4.1
IL_0011: conv.i8
IL_0012: stloc.1
IL_0013: ldloc.0
IL_0014: ldloc.1
IL_0015: conv.ovf.i.un
IL_0016: ldc.i4 0xde
IL_001b: stelem.i4
IL_001c: ldloc.0
IL_001d: ldc.i4.3
IL_001e: conv.i8
IL_001f: conv.ovf.i
IL_0020: ldc.i4 0x14d
IL_0025: stelem.i4
IL_0026: ldloc.0
IL_0027: ldloc.1
IL_0028: conv.ovf.i.un
IL_0029: ldelema ""int""
IL_002e: call ""string int.ToString()""
IL_0033: call ""void System.Console.Write(string)""
IL_0038: ldc.i4.3
IL_0039: conv.i8
IL_003a: stloc.1
IL_003b: ldc.i4.2
IL_003c: conv.i8
IL_003d: stloc.2
IL_003e: ldloc.0
IL_003f: ldloc.2
IL_0040: conv.ovf.i
IL_0041: ldloc.0
IL_0042: ldloc.1
IL_0043: conv.ovf.i.un
IL_0044: ldelem.i4
IL_0045: stelem.i4
IL_0046: ldloc.0
IL_0047: ldloc.2
IL_0048: conv.ovf.i
IL_0049: ldelema ""int""
IL_004e: call ""string int.ToString()""
IL_0053: call ""void System.Console.Write(string)""
IL_0058: ret
}
");
}
[Fact]
public void ArrayStructFieldAccess()
{
string source = @"
public class D
{
public struct Boo
{
public int I1;
public int I2;
}
public static void Main()
{
Boo b = new Boo();
b.I1 = 345;
b.I2 = 678;
Boo[] arr = new Boo[]{new Boo(), new Boo(), b};
System.Console.Write(arr[1].I1);
arr[1].I1 = arr[2].I1;
System.Console.Write(arr[1].I1);
System.Console.Write(arr[1].I2);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "03450");
compilation.VerifyIL("D.Main",
@"
{
// Code size 123 (0x7b)
.maxstack 4
.locals init (D.Boo V_0, //b
D.Boo[] V_1) //arr
IL_0000: ldloca.s V_0
IL_0002: initobj ""D.Boo""
IL_0008: ldloca.s V_0
IL_000a: ldc.i4 0x159
IL_000f: stfld ""int D.Boo.I1""
IL_0014: ldloca.s V_0
IL_0016: ldc.i4 0x2a6
IL_001b: stfld ""int D.Boo.I2""
IL_0020: ldc.i4.3
IL_0021: newarr ""D.Boo""
IL_0026: dup
IL_0027: ldc.i4.2
IL_0028: ldloc.0
IL_0029: stelem ""D.Boo""
IL_002e: stloc.1
IL_002f: ldloc.1
IL_0030: ldc.i4.1
IL_0031: ldelema ""D.Boo""
IL_0036: ldfld ""int D.Boo.I1""
IL_003b: call ""void System.Console.Write(int)""
IL_0040: ldloc.1
IL_0041: ldc.i4.1
IL_0042: ldelema ""D.Boo""
IL_0047: ldloc.1
IL_0048: ldc.i4.2
IL_0049: ldelema ""D.Boo""
IL_004e: ldfld ""int D.Boo.I1""
IL_0053: stfld ""int D.Boo.I1""
IL_0058: ldloc.1
IL_0059: ldc.i4.1
IL_005a: ldelema ""D.Boo""
IL_005f: ldfld ""int D.Boo.I1""
IL_0064: call ""void System.Console.Write(int)""
IL_0069: ldloc.1
IL_006a: ldc.i4.1
IL_006b: ldelema ""D.Boo""
IL_0070: ldfld ""int D.Boo.I2""
IL_0075: call ""void System.Console.Write(int)""
IL_007a: ret
}
");
}
[Fact]
public void ArrayClassFieldAccess()
{
string source = @"
public class D
{
public class Boo
{
public int I1;
public int I2;
public Boo()
{
}
}
public static void Main()
{
Boo b = new Boo();
b.I1 = 345;
b.I2 = 678;
Boo[] arr = new Boo[] {new Boo(), new Boo(), b};
System.Console.Write(arr[1].I1);
arr[1].I1 = arr[2].I1;
System.Console.Write(arr[1].I1);
System.Console.Write(arr[1].I2);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "03450");
compilation.VerifyIL("D.Main",
@"{
// Code size 111 (0x6f)
.maxstack 4
.locals init (D.Boo V_0, //b
D.Boo[] V_1) //arr
IL_0000: newobj ""D.Boo..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4 0x159
IL_000c: stfld ""int D.Boo.I1""
IL_0011: ldloc.0
IL_0012: ldc.i4 0x2a6
IL_0017: stfld ""int D.Boo.I2""
IL_001c: ldc.i4.3
IL_001d: newarr ""D.Boo""
IL_0022: dup
IL_0023: ldc.i4.0
IL_0024: newobj ""D.Boo..ctor()""
IL_0029: stelem.ref
IL_002a: dup
IL_002b: ldc.i4.1
IL_002c: newobj ""D.Boo..ctor()""
IL_0031: stelem.ref
IL_0032: dup
IL_0033: ldc.i4.2
IL_0034: ldloc.0
IL_0035: stelem.ref
IL_0036: stloc.1
IL_0037: ldloc.1
IL_0038: ldc.i4.1
IL_0039: ldelem.ref
IL_003a: ldfld ""int D.Boo.I1""
IL_003f: call ""void System.Console.Write(int)""
IL_0044: ldloc.1
IL_0045: ldc.i4.1
IL_0046: ldelem.ref
IL_0047: ldloc.1
IL_0048: ldc.i4.2
IL_0049: ldelem.ref
IL_004a: ldfld ""int D.Boo.I1""
IL_004f: stfld ""int D.Boo.I1""
IL_0054: ldloc.1
IL_0055: ldc.i4.1
IL_0056: ldelem.ref
IL_0057: ldfld ""int D.Boo.I1""
IL_005c: call ""void System.Console.Write(int)""
IL_0061: ldloc.1
IL_0062: ldc.i4.1
IL_0063: ldelem.ref
IL_0064: ldfld ""int D.Boo.I2""
IL_0069: call ""void System.Console.Write(int)""
IL_006e: ret
}
");
}
[Fact, WorkItem(538674, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538674")]
public void ArrayOneDimensionWithNoIntIndex()
{
string source = @"
using System;
public class MyArray
{
static uint fidx;
static void Main()
{
fidx = 2;
const long idx = 9;
// 12
sbyte[] a1 = new sbyte[(ulong)5];
a1[0] = a1[fidx + 1] = 123;
Console.WriteLine(a1[3]);
// 124
byte[] a2 = new byte[1+2] { 127, 0, 1 };
Console.WriteLine(a2[0]);
// 123
ushort[][,] a3 = new ushort[idx][,];
// 1234
short[][] a4 = new short[9 - 7][] { new short[1] { -1 }, new short[3] { short.MinValue, 0, short.MaxValue } };
Console.WriteLine(a4[1][fidx - 2]);
// 134
string[][] a5 = new string[][] { new string[] { ""A"" }, new string[] { ""B"", ""b"" }, new string[] { ""C"", null, ""CCC"" } };
Console.WriteLine(a5[fidx][2]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
123
127
-32768
CCC
");
#region IL
// Can NOT compare IL because the Guid is different every time - <PrivateImplementationDetails>{a6c2d596-042b-4294-99ab-d34a2758ec15}
#if false
compilation.VerifyIL("MyArray.Main",
@"{
// Code size 219 (0xdb)
.maxstack 7
.locals init (sbyte[] V_0, //a1
sbyte V_1)
IL_0000: ldc.i4.2
IL_0001: stsfld ""uint MyArray.fidx""
IL_0006: ldc.i4.5
IL_0007: conv.i8
IL_0008: conv.ovf.i.un
IL_0009: newarr ""sbyte""
IL_000e: stloc.0
IL_000f: ldloc.0
IL_0010: ldc.i4.0
IL_0011: ldloc.0
IL_0012: ldsfld ""uint MyArray.fidx""
IL_0017: ldc.i4.1
IL_0018: add
IL_0019: ldc.i4.s 123
IL_001b: dup
IL_001c: stloc.1
IL_001d: stelem.i1
IL_001e: ldloc.1
IL_001f: stelem.i1
IL_0020: ldloc.0
IL_0021: ldc.i4.3
IL_0022: ldelem.i1
IL_0023: call ""void System.Console.WriteLine(int)""
IL_0028: ldc.i4.3
IL_0029: newarr ""byte""
IL_002e: dup
IL_002f: ldtoken ""<PrivateImplementationDetails>{a6c2d596-042b-4294-99ab-d34a2758ec15}.__StaticArrayInitTypeSize=3 <PrivateImplementationDetails>{a6c2d596-042b-4294-99ab-d34a2758ec15}.0""
IL_0034: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0039: ldc.i4.0
IL_003a: ldelem.u1
IL_003b: call ""void System.Console.WriteLine(int)""
IL_0040: ldc.i4.s 9
IL_0042: conv.i8
IL_0043: conv.ovf.i
IL_0044: newarr ""ushort[,]""
IL_0049: pop
IL_004a: ldc.i4.2
IL_004b: newarr ""short[]""
IL_0050: dup
IL_0051: ldc.i4.0
IL_0052: ldc.i4.1
IL_0053: newarr ""short""
IL_0058: dup
IL_0059: ldc.i4.0
IL_005a: ldc.i4.m1
IL_005b: stelem.i2
IL_005c: stelem.ref
IL_005d: dup
IL_005e: ldc.i4.1
IL_005f: ldc.i4.3
IL_0060: newarr ""short""
IL_0065: dup
IL_0066: ldtoken ""<PrivateImplementationDetails>{a6c2d596-042b-4294-99ab-d34a2758ec15}.__StaticArrayInitTypeSize=6 <PrivateImplementationDetails>{a6c2d596-042b-4294-99ab-d34a2758ec15}.1""
IL_006b: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0070: stelem.ref
IL_0071: ldc.i4.1
IL_0072: ldelem.ref
IL_0073: ldsfld ""uint MyArray.fidx""
IL_0078: ldc.i4.2
IL_0079: sub
IL_007a: ldelem.i2
IL_007b: call ""void System.Console.WriteLine(int)""
IL_0080: ldc.i4.3
IL_0081: newarr ""string[]""
IL_0086: dup
IL_0087: ldc.i4.0
IL_0088: ldc.i4.1
IL_0089: newarr ""string""
IL_008e: dup
IL_008f: ldc.i4.0
IL_0090: ldstr ""A""
IL_0095: stelem.ref
IL_0096: stelem.ref
IL_0097: dup
IL_0098: ldc.i4.1
IL_0099: ldc.i4.2
IL_009a: newarr ""string""
IL_009f: dup
IL_00a0: ldc.i4.0
IL_00a1: ldstr ""B""
IL_00a6: stelem.ref
IL_00a7: dup
IL_00a8: ldc.i4.1
IL_00a9: ldstr ""b""
IL_00ae: stelem.ref
IL_00af: stelem.ref
IL_00b0: dup
IL_00b1: ldc.i4.2
IL_00b2: ldc.i4.3
IL_00b3: newarr ""string""
IL_00b8: dup
IL_00b9: ldc.i4.0
IL_00ba: ldstr ""C""
IL_00bf: stelem.ref
IL_00c0: dup
IL_00c1: ldc.i4.1
IL_00c2: ldnull
IL_00c3: stelem.ref
IL_00c4: dup
IL_00c5: ldc.i4.2
IL_00c6: ldstr ""CCC""
IL_00cb: stelem.ref
IL_00cc: stelem.ref
IL_00cd: ldsfld ""uint MyArray.fidx""
IL_00d2: ldelem.ref
IL_00d3: ldc.i4.2
IL_00d4: ldelem.ref
IL_00d5: call ""void System.Console.WriteLine(string)""
IL_00da: ret
}
");
#endif
#endregion
}
[Fact]
public void AccessTypeParam()
{
string source = @"
public class D
{
public class Outer<K> where K : class
{
public class Boo<T, R, U>
where T : class
where R : struct
where U : K
{
public Boo()
{
}
public void Goo(T x, R y, U z)
{
System.Collections.Generic.List<T> lT = new System.Collections.Generic.List<T>();
lT.Add(x);
T[] aT = lT.ToArray();
System.Console.Write(aT[0].ToString());
T eT = aT[0];
System.Console.Write(eT.ToString());
System.Collections.Generic.List<R> lR = new System.Collections.Generic.List<R>();
lR.Add(y);
R[] aR = lR.ToArray();
System.Console.Write(aR[0].ToString());
R eR = aR[0];
System.Console.Write(eR.ToString());
System.Collections.Generic.List<U> lU = new System.Collections.Generic.List<U>();
lU.Add(z);
U[] aU = lU.ToArray();
System.Console.Write(aU[0].ToString());
U eU = aU[0];
System.Console.Write(eU.ToString());
}
}
}
public static void Main()
{
Outer<object>.Boo<string, int, int> b = new Outer<object>.Boo<string, int, int>();
b.Goo(""hi"", 42, 123);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "hihi4242123123");
compilation.VerifyIL("D.Outer<K>.Boo<T, R, U>.Goo",
@"
{
// Code size 195 (0xc3)
.maxstack 3
.locals init (R V_0, //eR
U V_1) //eU
IL_0000: newobj ""System.Collections.Generic.List<T>..ctor()""
IL_0005: dup
IL_0006: ldarg.1
IL_0007: callvirt ""void System.Collections.Generic.List<T>.Add(T)""
IL_000c: callvirt ""T[] System.Collections.Generic.List<T>.ToArray()""
IL_0011: dup
IL_0012: ldc.i4.0
IL_0013: ldelem ""T""
IL_0018: box ""T""
IL_001d: callvirt ""string object.ToString()""
IL_0022: call ""void System.Console.Write(string)""
IL_0027: ldc.i4.0
IL_0028: ldelem ""T""
IL_002d: box ""T""
IL_0032: callvirt ""string object.ToString()""
IL_0037: call ""void System.Console.Write(string)""
IL_003c: newobj ""System.Collections.Generic.List<R>..ctor()""
IL_0041: dup
IL_0042: ldarg.2
IL_0043: callvirt ""void System.Collections.Generic.List<R>.Add(R)""
IL_0048: callvirt ""R[] System.Collections.Generic.List<R>.ToArray()""
IL_004d: dup
IL_004e: ldc.i4.0
IL_004f: readonly.
IL_0051: ldelema ""R""
IL_0056: constrained. ""R""
IL_005c: callvirt ""string object.ToString()""
IL_0061: call ""void System.Console.Write(string)""
IL_0066: ldc.i4.0
IL_0067: ldelem ""R""
IL_006c: stloc.0
IL_006d: ldloca.s V_0
IL_006f: constrained. ""R""
IL_0075: callvirt ""string object.ToString()""
IL_007a: call ""void System.Console.Write(string)""
IL_007f: newobj ""System.Collections.Generic.List<U>..ctor()""
IL_0084: dup
IL_0085: ldarg.3
IL_0086: callvirt ""void System.Collections.Generic.List<U>.Add(U)""
IL_008b: callvirt ""U[] System.Collections.Generic.List<U>.ToArray()""
IL_0090: dup
IL_0091: ldc.i4.0
IL_0092: readonly.
IL_0094: ldelema ""U""
IL_0099: constrained. ""U""
IL_009f: callvirt ""string object.ToString()""
IL_00a4: call ""void System.Console.Write(string)""
IL_00a9: ldc.i4.0
IL_00aa: ldelem ""U""
IL_00af: stloc.1
IL_00b0: ldloca.s V_1
IL_00b2: constrained. ""U""
IL_00b8: callvirt ""string object.ToString()""
IL_00bd: call ""void System.Console.Write(string)""
IL_00c2: ret
}
");
}
[Fact]
public void ConstrainedCalls()
{
string source = @"
public class D
{
public class Boo
{
public int I1;
public int I2;
public Boo()
{
}
}
public class Boo<T>
{
public Boo()
{
}
public void Moo(T x, T y)
{
T[] arr = new T[]{x, y, x, y};
// constrained generic
string s = arr[1].ToString();
System.Console.Write(s);
}
}
public static void Main()
{
Boo x = new Boo();
Boo y = new Boo();
Boo<Boo> b = new Boo<Boo>();
b.Moo(x, y);
int iii = 123;
// constrained nongeneric
System.Console.Write(iii.GetType());
// regular call
System.Console.Write(iii.ToString());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "D+BooSystem.Int32123");
compilation.VerifyIL("D.Boo<T>.Moo",
@"{
// Code size 63 (0x3f)
.maxstack 4
IL_0000: ldc.i4.4
IL_0001: newarr ""T""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldarg.1
IL_0009: stelem ""T""
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: ldarg.2
IL_0011: stelem ""T""
IL_0016: dup
IL_0017: ldc.i4.2
IL_0018: ldarg.1
IL_0019: stelem ""T""
IL_001e: dup
IL_001f: ldc.i4.3
IL_0020: ldarg.2
IL_0021: stelem ""T""
IL_0026: ldc.i4.1
IL_0027: readonly.
IL_0029: ldelema ""T""
IL_002e: constrained. ""T""
IL_0034: callvirt ""string object.ToString()""
IL_0039: call ""void System.Console.Write(string)""
IL_003e: ret
}
");
compilation.VerifyIL("D.Main",
@"{
// Code size 56 (0x38)
.maxstack 3
.locals init (D.Boo V_0, //x
D.Boo V_1, //y
int V_2) //iii
IL_0000: newobj ""D.Boo..ctor()""
IL_0005: stloc.0
IL_0006: newobj ""D.Boo..ctor()""
IL_000b: stloc.1
IL_000c: newobj ""D.Boo<D.Boo>..ctor()""
IL_0011: ldloc.0
IL_0012: ldloc.1
IL_0013: callvirt ""void D.Boo<D.Boo>.Moo(D.Boo, D.Boo)""
IL_0018: ldc.i4.s 123
IL_001a: stloc.2
IL_001b: ldloc.2
IL_001c: box ""int""
IL_0021: call ""System.Type object.GetType()""
IL_0026: call ""void System.Console.Write(object)""
IL_002b: ldloca.s V_2
IL_002d: call ""string int.ToString()""
IL_0032: call ""void System.Console.Write(string)""
IL_0037: ret
}
");
}
[Fact]
public void TestConstructor()
{
string source = @"
public class P
{
public class B
{
public B()
{
System.Console.Write(""B ctor-"");
}
}
public class D : B
{
public D()
{
System.Console.Write(""D ctor"");
}
}
public static void Main()
{
new D();
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "B ctor-D ctor");
compilation.VerifyIL("P.D..ctor",
@"{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""P.B..ctor()""
IL_0006: ldstr ""D ctor""
IL_000b: call ""void System.Console.Write(string)""
IL_0010: ret
}
");
}
[Fact]
public void BinderTemps()
{
string source = @"
public class D
{
public class C1
{
public int Goo(int x, int y)
{
System.Console.Write(""["");
System.Console.Write(x);
System.Console.Write(y);
System.Console.Write(""]"");
return 8;
}
public C1()
{
}
}
public static int GetInt(int i)
{
System.Console.Write(""["");
System.Console.Write(i);
System.Console.Write(""]"");
return i;
}
public static void Main()
{
C1 c = new C1();
c.Goo(y: GetInt(2),
x: GetInt(3));
System.Console.Write("" "");
c.Goo( GetInt(1),
c.Goo(y: GetInt(2),
x: GetInt(3)));
System.Console.Write("" "");
c.Goo(y: GetInt(1),
x: c.Goo(y: GetInt(2),
x: GetInt(3)));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
[2][3][32] [1][2][3][32][18] [1][2][3][32][81]
");
compilation.VerifyIL("D.Main",
@"
{
// Code size 116 (0x74)
.maxstack 5
.locals init (D.C1 V_0, //c
int V_1,
int V_2)
IL_0000: newobj ""D.C1..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.2
IL_0008: call ""int D.GetInt(int)""
IL_000d: stloc.1
IL_000e: ldc.i4.3
IL_000f: call ""int D.GetInt(int)""
IL_0014: ldloc.1
IL_0015: callvirt ""int D.C1.Goo(int, int)""
IL_001a: pop
IL_001b: ldstr "" ""
IL_0020: call ""void System.Console.Write(string)""
IL_0025: ldloc.0
IL_0026: ldc.i4.1
IL_0027: call ""int D.GetInt(int)""
IL_002c: ldloc.0
IL_002d: ldc.i4.2
IL_002e: call ""int D.GetInt(int)""
IL_0033: stloc.1
IL_0034: ldc.i4.3
IL_0035: call ""int D.GetInt(int)""
IL_003a: ldloc.1
IL_003b: callvirt ""int D.C1.Goo(int, int)""
IL_0040: callvirt ""int D.C1.Goo(int, int)""
IL_0045: pop
IL_0046: ldstr "" ""
IL_004b: call ""void System.Console.Write(string)""
IL_0050: ldloc.0
IL_0051: ldc.i4.1
IL_0052: call ""int D.GetInt(int)""
IL_0057: stloc.1
IL_0058: ldloc.0
IL_0059: ldc.i4.2
IL_005a: call ""int D.GetInt(int)""
IL_005f: stloc.2
IL_0060: ldc.i4.3
IL_0061: call ""int D.GetInt(int)""
IL_0066: ldloc.2
IL_0067: callvirt ""int D.C1.Goo(int, int)""
IL_006c: ldloc.1
IL_006d: callvirt ""int D.C1.Goo(int, int)""
IL_0072: pop
IL_0073: ret
}
");
}
[Fact]
public void BinderTempsNestedScopes()
{
string source = @"
public class D
{
public class C1
{
public int Goo(int x, int y)
{
System.Console.Write(""["");
System.Console.Write(x);
System.Console.Write(y);
System.Console.Write(""]"");
return 8;
}
public C1()
{
}
}
public static int GetInt(int i)
{
System.Console.Write(""["");
System.Console.Write(i);
System.Console.Write(""]"");
return i;
}
public static void Main()
{
C1 c = new C1();
c.Goo(y: GetInt(1),
x: c.Goo(y: c.Goo(y: GetInt(1),
x: c.Goo(y: GetInt(2),
x: GetInt(3))),
x: GetInt(3)));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
[1][1][2][3][32][81][3][38][81]
");
compilation.VerifyIL("D.Main",
@"
{
// Code size 68 (0x44)
.maxstack 6
.locals init (int V_0,
int V_1,
int V_2,
int V_3)
IL_0000: newobj ""D.C1..ctor()""
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: call ""int D.GetInt(int)""
IL_000c: stloc.0
IL_000d: dup
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: call ""int D.GetInt(int)""
IL_0015: stloc.2
IL_0016: ldc.i4.2
IL_0017: call ""int D.GetInt(int)""
IL_001c: stloc.3
IL_001d: ldc.i4.3
IL_001e: call ""int D.GetInt(int)""
IL_0023: ldloc.3
IL_0024: callvirt ""int D.C1.Goo(int, int)""
IL_0029: ldloc.2
IL_002a: callvirt ""int D.C1.Goo(int, int)""
IL_002f: stloc.1
IL_0030: ldc.i4.3
IL_0031: call ""int D.GetInt(int)""
IL_0036: ldloc.1
IL_0037: callvirt ""int D.C1.Goo(int, int)""
IL_003c: ldloc.0
IL_003d: callvirt ""int D.C1.Goo(int, int)""
IL_0042: pop
IL_0043: ret
}");
}
//This is mostly to test array creation.
//param call will certainly create one.
[Fact]
public void ParamCallCreatesArray()
{
string source = @"
public class D
{
public static void Main()
{
System.Console.Write(""{0}{1}{2}{3}{4}{5}"", ""a"", ""b"", ""c"", ""d"", ""e"", ""f"");
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"abcdef");
compilation.VerifyIL("D.Main",
@"{
// Code size 65 (0x41)
.maxstack 5
IL_0000: ldstr ""{0}{1}{2}{3}{4}{5}""
IL_0005: ldc.i4.6
IL_0006: newarr ""object""
IL_000b: dup
IL_000c: ldc.i4.0
IL_000d: ldstr ""a""
IL_0012: stelem.ref
IL_0013: dup
IL_0014: ldc.i4.1
IL_0015: ldstr ""b""
IL_001a: stelem.ref
IL_001b: dup
IL_001c: ldc.i4.2
IL_001d: ldstr ""c""
IL_0022: stelem.ref
IL_0023: dup
IL_0024: ldc.i4.3
IL_0025: ldstr ""d""
IL_002a: stelem.ref
IL_002b: dup
IL_002c: ldc.i4.4
IL_002d: ldstr ""e""
IL_0032: stelem.ref
IL_0033: dup
IL_0034: ldc.i4.5
IL_0035: ldstr ""f""
IL_003a: stelem.ref
IL_003b: call ""void System.Console.Write(string, params object[])""
IL_0040: ret
}
");
}
// Test that Array.Empty<T>() is used instead of "new T[0]" when Array.Empty<T>() is available.
[Fact]
public void ParamCallUsesCachedArray()
{
var verifier = CompileAndVerify(@"
public class Program
{
public static void Callee1(params object[] values) { }
public static void Callee2(params int[] values) { }
public static void Callee3<T>(params T[] values) { }
public static void Main() { }
public static void M<T>()
{
Callee1();
Callee1(System.Array.Empty<object>());
Callee1(null);
Callee1(new object[0]);
Callee1(""Hello"");
Callee1(""Hello"", ""World"");
Callee2();
Callee2(System.Array.Empty<int>());
Callee2(null);
Callee2(new int[0]);
Callee2(1);
Callee2(1, 2);
Callee3<string>();
Callee3<string>(System.Array.Empty<string>());
Callee3<string>(null);
Callee3<string>(new string[0]);
Callee3<string>(""Hello"");
Callee3<string>(""Hello"", ""World"");
Callee3<T>();
Callee3<T>(System.Array.Empty<T>());
Callee3<T>(null);
Callee3<T>(new T[0]);
Callee3<T>(default(T));
Callee3<T>(default(T), default(T));
}
}
", options: TestOptions.ReleaseExe);
verifier.VerifyIL("Program.M<T>()",
@"{
// Code size 297 (0x129)
.maxstack 4
IL_0000: call ""object[] System.Array.Empty<object>()""
IL_0005: call ""void Program.Callee1(params object[])""
IL_000a: call ""object[] System.Array.Empty<object>()""
IL_000f: call ""void Program.Callee1(params object[])""
IL_0014: ldnull
IL_0015: call ""void Program.Callee1(params object[])""
IL_001a: ldc.i4.0
IL_001b: newarr ""object""
IL_0020: call ""void Program.Callee1(params object[])""
IL_0025: ldc.i4.1
IL_0026: newarr ""object""
IL_002b: dup
IL_002c: ldc.i4.0
IL_002d: ldstr ""Hello""
IL_0032: stelem.ref
IL_0033: call ""void Program.Callee1(params object[])""
IL_0038: ldc.i4.2
IL_0039: newarr ""object""
IL_003e: dup
IL_003f: ldc.i4.0
IL_0040: ldstr ""Hello""
IL_0045: stelem.ref
IL_0046: dup
IL_0047: ldc.i4.1
IL_0048: ldstr ""World""
IL_004d: stelem.ref
IL_004e: call ""void Program.Callee1(params object[])""
IL_0053: call ""int[] System.Array.Empty<int>()""
IL_0058: call ""void Program.Callee2(params int[])""
IL_005d: call ""int[] System.Array.Empty<int>()""
IL_0062: call ""void Program.Callee2(params int[])""
IL_0067: ldnull
IL_0068: call ""void Program.Callee2(params int[])""
IL_006d: ldc.i4.0
IL_006e: newarr ""int""
IL_0073: call ""void Program.Callee2(params int[])""
IL_0078: ldc.i4.1
IL_0079: newarr ""int""
IL_007e: dup
IL_007f: ldc.i4.0
IL_0080: ldc.i4.1
IL_0081: stelem.i4
IL_0082: call ""void Program.Callee2(params int[])""
IL_0087: ldc.i4.2
IL_0088: newarr ""int""
IL_008d: dup
IL_008e: ldc.i4.0
IL_008f: ldc.i4.1
IL_0090: stelem.i4
IL_0091: dup
IL_0092: ldc.i4.1
IL_0093: ldc.i4.2
IL_0094: stelem.i4
IL_0095: call ""void Program.Callee2(params int[])""
IL_009a: call ""string[] System.Array.Empty<string>()""
IL_009f: call ""void Program.Callee3<string>(params string[])""
IL_00a4: call ""string[] System.Array.Empty<string>()""
IL_00a9: call ""void Program.Callee3<string>(params string[])""
IL_00ae: ldnull
IL_00af: call ""void Program.Callee3<string>(params string[])""
IL_00b4: ldc.i4.0
IL_00b5: newarr ""string""
IL_00ba: call ""void Program.Callee3<string>(params string[])""
IL_00bf: ldc.i4.1
IL_00c0: newarr ""string""
IL_00c5: dup
IL_00c6: ldc.i4.0
IL_00c7: ldstr ""Hello""
IL_00cc: stelem.ref
IL_00cd: call ""void Program.Callee3<string>(params string[])""
IL_00d2: ldc.i4.2
IL_00d3: newarr ""string""
IL_00d8: dup
IL_00d9: ldc.i4.0
IL_00da: ldstr ""Hello""
IL_00df: stelem.ref
IL_00e0: dup
IL_00e1: ldc.i4.1
IL_00e2: ldstr ""World""
IL_00e7: stelem.ref
IL_00e8: call ""void Program.Callee3<string>(params string[])""
IL_00ed: call ""T[] System.Array.Empty<T>()""
IL_00f2: call ""void Program.Callee3<T>(params T[])""
IL_00f7: call ""T[] System.Array.Empty<T>()""
IL_00fc: call ""void Program.Callee3<T>(params T[])""
IL_0101: ldnull
IL_0102: call ""void Program.Callee3<T>(params T[])""
IL_0107: ldc.i4.0
IL_0108: newarr ""T""
IL_010d: call ""void Program.Callee3<T>(params T[])""
IL_0112: ldc.i4.1
IL_0113: newarr ""T""
IL_0118: call ""void Program.Callee3<T>(params T[])""
IL_011d: ldc.i4.2
IL_011e: newarr ""T""
IL_0123: call ""void Program.Callee3<T>(params T[])""
IL_0128: ret
}
");
var comp = CreateCompilation(@"
public class Program
{
public static void Callee1(params object[] values) { }
public static void Callee2(params int[] values) { }
public static void Callee3<T>(params T[] values) { }
public static void Main() { }
public static void M<T>()
{
Callee1();
Callee2();
Callee3<string>();
}
}
", options: TestOptions.ReleaseExe);
comp.MakeMemberMissing(SpecialMember.System_Array__Empty);
verifier = CompileAndVerify(comp);
verifier.VerifyIL("Program.M<T>()",
@"{
// Code size 34 (0x22)
.maxstack 1
IL_0000: ldc.i4.0
IL_0001: newarr ""object""
IL_0006: call ""void Program.Callee1(params object[])""
IL_000b: ldc.i4.0
IL_000c: newarr ""int""
IL_0011: call ""void Program.Callee2(params int[])""
IL_0016: ldc.i4.0
IL_0017: newarr ""string""
IL_001c: call ""void Program.Callee3<string>(params string[])""
IL_0021: ret
}
");
}
[Fact]
public void BoxingConversions()
{
string source = @"
public class D
{
public static void Main()
{
object o = 123;
int i = (int)o;
System.Console.Write(i);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"123");
compilation.VerifyIL("D.Main",
@"{
// Code size 18 (0x12)
.maxstack 1
IL_0000: ldc.i4.s 123
IL_0002: box ""int""
IL_0007: unbox.any ""int""
IL_000c: call ""void System.Console.Write(int)""
IL_0011: ret
}
");
}
[Fact]
public void AccessingThis()
{
string source = @"
public class D
{
public class Goo
{
public int x;
public void Bar()
{
x = 1234;
}
}
public struct GooS
{
public int x;
public void Bar()
{
x = 1234;
}
}
public static void Main()
{
Goo f = new Goo();
System.Console.Write(f.x);
f.Bar();
System.Console.Write(f.x);
GooS fs = new GooS();
System.Console.Write(fs.x);
fs.Bar();
System.Console.Write(fs.x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"0123401234");
compilation.VerifyIL("D.Goo.Bar",
@"{
// Code size 12 (0xc)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4 0x4d2
IL_0006: stfld ""int D.Goo.x""
IL_000b: ret
}
");
compilation.VerifyIL("D.GooS.Bar",
@"{
// Code size 12 (0xc)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4 0x4d2
IL_0006: stfld ""int D.GooS.x""
IL_000b: ret
}
");
}
[Fact]
public void AccessingThis1()
{
string source = @"
public class D
{
public class Moo<T>
{
private string[] y;
private T[] z;
public void Assign(string[] y, T[] z, string y1, T z1)
{
this.y = y;
this.z = z;
this.y[1] = y1;
this.z[1] = z1;
}
public void Print()
{
System.Console.Write(this.y[0].ToString());
System.Console.Write(this.z[0].ToString());
System.Console.Write(this.y[1].ToString());
System.Console.Write(this.z[1].ToString());
}
public Moo()
{
}
}
public struct MooS<T>
{
private string[] y;
private T[] z;
public void Assign(string[] y, T[] z, string y1, T z1)
{
this.y = y;
this.z = z;
this.y[1] = y1;
this.z[1] = z1;
MooS<T> tmp = this;
this = tmp;
}
public void Print()
{
System.Console.Write(this.y[0].ToString());
System.Console.Write(this.z[0].ToString());
System.Console.Write(this.y[1].ToString());
System.Console.Write(this.z[1].ToString());
}
}
public static void Main()
{
System.ApplicationException[] earr = new System.ApplicationException[]
{
new System.ApplicationException(""hello""),
new System.ApplicationException(""hi"")
};
string[] sarr = new string[] {""aaaa"", ""bbbb"", ""aaaa"", ""bbbb"", ""aaaa"", ""bbbb"",};
Moo<System.Exception> obj = new Moo<System.Exception>();
obj.Assign(sarr, earr, ""bye"", new System.ApplicationException(""cccc""));
obj.Print();
MooS<System.Exception> objS = new MooS<System.Exception>();
objS.Assign(sarr, earr, ""bye"", new System.ApplicationException(""cccc""));
objS.Print();
}}";
// If we ever stop verifying the execution of this, we need to add IL verification for some of the method bodies.
var compilation = CompileAndVerify(source, expectedOutput: @"
aaaaSystem.ApplicationException: hellobyeSystem.ApplicationException: ccccaaaaSystem.ApplicationException: hellobyeSystem.ApplicationException: cccc
");
}
[Fact]
public void AccessingBase()
{
string source = @"
public class D
{
public class Goo
{
public int x;
public void Bar()
{
x = 1234;
}
}
public class GooD : Goo
{
public new int x = 5555;
public void Baz()
{
base.x = 4321;
x = 7777;
}
}
public static void Main()
{
GooD fd = new GooD();
System.Console.Write(((Goo)fd).x);
fd.Bar();
System.Console.Write(((Goo)fd).x);
fd.Baz();
System.Console.Write(((Goo)fd).x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"012344321");
compilation.VerifyIL("D.GooD.Baz",
@"{
// Code size 23 (0x17)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4 0x10e1
IL_0006: stfld ""int D.Goo.x""
IL_000b: ldarg.0
IL_000c: ldc.i4 0x1e61
IL_0011: stfld ""int D.GooD.x""
IL_0016: ret
}
");
}
[Fact]
public void UnaryOp()
{
string source = @"
public class D
{
public static void Main()
{
int x = 1;
x = -x;
System.Console.Write(x);
x = ~x;
System.Console.Write(x);
long y = -x;
System.Console.Write(y);
y = ~y;
System.Console.Write(y);
double z = -y;
System.Console.Write(z);
z = -z;
System.Console.Write(z);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"-100-11-1");
compilation.VerifyIL("D.Main",
@"{
// Code size 45 (0x2d)
.maxstack 2
IL_0000: ldc.i4.1
IL_0001: neg
IL_0002: dup
IL_0003: call ""void System.Console.Write(int)""
IL_0008: not
IL_0009: dup
IL_000a: call ""void System.Console.Write(int)""
IL_000f: neg
IL_0010: conv.i8
IL_0011: dup
IL_0012: call ""void System.Console.Write(long)""
IL_0017: not
IL_0018: dup
IL_0019: call ""void System.Console.Write(long)""
IL_001e: neg
IL_001f: conv.r8
IL_0020: dup
IL_0021: call ""void System.Console.Write(double)""
IL_0026: neg
IL_0027: call ""void System.Console.Write(double)""
IL_002c: ret
}
");
}
[Fact]
public void BinaryOp()
{
string source = @"
public class D
{
public static void Main()
{
int x = 1;
x = x + x;
System.Console.Write(x);
System.Console.Write("" "");
x = x << x;
System.Console.Write(x);
System.Console.Write("" "");
long y = x + x;
System.Console.Write(y);
System.Console.Write("" "");
y = y + x;
System.Console.Write(y);
System.Console.Write("" "");
double z = y;
z = z * z;
System.Console.Write(z);
System.Console.Write("" "");
z = z / 2;
System.Console.Write(z);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2 8 16 24 576 288");
compilation.VerifyIL("D.Main",
@"
{
// Code size 119 (0x77)
.maxstack 3
.locals init (int V_0) //x
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldloc.0
IL_0004: add
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: call ""void System.Console.Write(int)""
IL_000c: ldstr "" ""
IL_0011: call ""void System.Console.Write(string)""
IL_0016: ldloc.0
IL_0017: ldloc.0
IL_0018: ldc.i4.s 31
IL_001a: and
IL_001b: shl
IL_001c: stloc.0
IL_001d: ldloc.0
IL_001e: call ""void System.Console.Write(int)""
IL_0023: ldstr "" ""
IL_0028: call ""void System.Console.Write(string)""
IL_002d: ldloc.0
IL_002e: ldloc.0
IL_002f: add
IL_0030: conv.i8
IL_0031: dup
IL_0032: call ""void System.Console.Write(long)""
IL_0037: ldstr "" ""
IL_003c: call ""void System.Console.Write(string)""
IL_0041: ldloc.0
IL_0042: conv.i8
IL_0043: add
IL_0044: dup
IL_0045: call ""void System.Console.Write(long)""
IL_004a: ldstr "" ""
IL_004f: call ""void System.Console.Write(string)""
IL_0054: conv.r8
IL_0055: dup
IL_0056: mul
IL_0057: dup
IL_0058: call ""void System.Console.Write(double)""
IL_005d: ldstr "" ""
IL_0062: call ""void System.Console.Write(string)""
IL_0067: ldc.r8 2
IL_0070: div
IL_0071: call ""void System.Console.Write(double)""
IL_0076: ret
}
");
}
[Fact]
public void LogOp()
{
string source = @"
public class D
{
public static void Main()
{
int x = 1;
bool b = x == 1;
System.Console.Write(b);
System.Console.Write("" "");
long l = 5;
System.Console.Write(l > 6);
System.Console.Write("" "");
float f = 25;
System.Console.Write(f >= 25);
System.Console.Write("" "");
double d = 3;
System.Console.Write(d <= f);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"True False True True");
compilation.VerifyIL("D.Main",
@"{
// Code size 94 (0x5e)
.maxstack 2
.locals init (float V_0) //f
IL_0000: ldc.i4.1
IL_0001: ldc.i4.1
IL_0002: ceq
IL_0004: call ""void System.Console.Write(bool)""
IL_0009: ldstr "" ""
IL_000e: call ""void System.Console.Write(string)""
IL_0013: ldc.i4.5
IL_0014: conv.i8
IL_0015: ldc.i4.6
IL_0016: conv.i8
IL_0017: cgt
IL_0019: call ""void System.Console.Write(bool)""
IL_001e: ldstr "" ""
IL_0023: call ""void System.Console.Write(string)""
IL_0028: ldc.r4 25
IL_002d: stloc.0
IL_002e: ldloc.0
IL_002f: ldc.r4 25
IL_0034: clt.un
IL_0036: ldc.i4.0
IL_0037: ceq
IL_0039: call ""void System.Console.Write(bool)""
IL_003e: ldstr "" ""
IL_0043: call ""void System.Console.Write(string)""
IL_0048: ldc.r8 3
IL_0051: ldloc.0
IL_0052: conv.r8
IL_0053: cgt.un
IL_0055: ldc.i4.0
IL_0056: ceq
IL_0058: call ""void System.Console.Write(bool)""
IL_005d: ret
}
");
}
[Fact]
public void UnsignedOp()
{
string source = @"
public class D
{
public static void Main()
{
int x = -100;
x = x >> 2;
System.Console.Write(x);
System.Console.Write("" "");
uint ux = 1;
uint uy = ux - ux;
uy = uy - ux;
System.Console.Write(uy);
System.Console.Write("" "");
uy = uy >> 2;
System.Console.Write(uy);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"-25 4294967295 1073741823");
compilation.VerifyIL("D.Main",
@"
{
// Code size 50 (0x32)
.maxstack 2
.locals init (uint V_0) //ux
IL_0000: ldc.i4.s -100
IL_0002: ldc.i4.2
IL_0003: shr
IL_0004: call ""void System.Console.Write(int)""
IL_0009: ldstr "" ""
IL_000e: call ""void System.Console.Write(string)""
IL_0013: ldc.i4.1
IL_0014: stloc.0
IL_0015: ldloc.0
IL_0016: ldloc.0
IL_0017: sub
IL_0018: ldloc.0
IL_0019: sub
IL_001a: dup
IL_001b: call ""void System.Console.Write(uint)""
IL_0020: ldstr "" ""
IL_0025: call ""void System.Console.Write(string)""
IL_002a: ldc.i4.2
IL_002b: shr.un
IL_002c: call ""void System.Console.Write(uint)""
IL_0031: ret
}
");
}
[Fact]
public void ReadonlyAddressConstrained()
{
string source = @"
public class D
{
public class Moo<T>
{
public void Boo(T x)
{
T local = x;
System.Console.Write(local.ToString());
}
public void Goo(T[] x)
{
System.Console.Write(x.ToString()); // no need for readonly
Boo(x[0]); // no need for readonly
System.Console.Write(x[0].ToString()); // readonly
}
public Moo()
{
}
}
public static void Main()
{
Moo<System.Exception> obj = new Moo<System.Exception>();
obj.Goo(new System.ApplicationException[]{new System.ApplicationException(""hello"")});
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
System.ApplicationException[]System.ApplicationException: helloSystem.ApplicationException: hello
");
compilation.VerifyIL("D.Moo<T>.Goo",
@"{
// Code size 50 (0x32)
.maxstack 3
IL_0000: ldarg.1
IL_0001: callvirt ""string object.ToString()""
IL_0006: call ""void System.Console.Write(string)""
IL_000b: ldarg.0
IL_000c: ldarg.1
IL_000d: ldc.i4.0
IL_000e: ldelem ""T""
IL_0013: call ""void D.Moo<T>.Boo(T)""
IL_0018: ldarg.1
IL_0019: ldc.i4.0
IL_001a: readonly.
IL_001c: ldelema ""T""
IL_0021: constrained. ""T""
IL_0027: callvirt ""string object.ToString()""
IL_002c: call ""void System.Console.Write(string)""
IL_0031: ret
}
");
}
[WorkItem(22858, "https://github.com/dotnet/roslyn/issues/22858")]
[Fact]
public void CovariantArrayRefParam()
{
string source = @"
class Program
{
static void Main(string[] args)
{
try
{
Test(ref ((object[])new string[] { ""hi"", ""hello"" })[0]);
}
catch (System.ArrayTypeMismatchException)
{
System.Console.WriteLine(""PASS"");
}
}
static void Test(ref object r)
{
throw null;
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"PASS", verify: Verification.Passes);
compilation.VerifyIL("Program.Main(string[])",
@"
{
// Code size 51 (0x33)
.maxstack 4
.locals init (object[] V_0)
.try
{
IL_0000: ldc.i4.2
IL_0001: newarr ""string""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldstr ""hi""
IL_000d: stelem.ref
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: ldstr ""hello""
IL_0015: stelem.ref
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: ldc.i4.0
IL_0019: ldelema ""object""
IL_001e: call ""void Program.Test(ref object)""
IL_0023: leave.s IL_0032
}
catch System.ArrayTypeMismatchException
{
IL_0025: pop
IL_0026: ldstr ""PASS""
IL_002b: call ""void System.Console.WriteLine(string)""
IL_0030: leave.s IL_0032
}
IL_0032: ret
}
");
}
[WorkItem(22841, "https://github.com/dotnet/roslyn/issues/22841")]
[CompilerTrait(CompilerFeature.PEVerifyCompat)]
[Fact]
public void ReadonlyAddressInParam()
{
string source = @"
class Program
{
static void Main(string[] args)
{
var stringArray = new string[] { ""hi"", ""hello"" };
var objectArray = (object[])stringArray;
Test(objectArray[0]);
}
static void Test(in object r)
{
System.Console.WriteLine(r);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"hi", verify: Verification.Fails);
compilation.VerifyIL("Program.Main(string[])",
@"
{
// Code size 38 (0x26)
.maxstack 4
.locals init (object[] V_0)
IL_0000: ldc.i4.2
IL_0001: newarr ""string""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldstr ""hi""
IL_000d: stelem.ref
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: ldstr ""hello""
IL_0015: stelem.ref
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: ldc.i4.0
IL_0019: readonly.
IL_001b: ldelema ""object""
IL_0020: call ""void Program.Test(in object)""
IL_0025: ret
}
");
compilation = CompileAndVerify(source, expectedOutput: @"hi", verify: Verification.Passes, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
compilation.VerifyIL("Program.Main(string[])",
@"
{
// Code size 35 (0x23)
.maxstack 4
.locals init (object[] V_0,
object V_1)
IL_0000: ldc.i4.2
IL_0001: newarr ""string""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldstr ""hi""
IL_000d: stelem.ref
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: ldstr ""hello""
IL_0015: stelem.ref
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: ldc.i4.0
IL_0019: ldelem.ref
IL_001a: stloc.1
IL_001b: ldloca.s V_1
IL_001d: call ""void Program.Test(in object)""
IL_0022: ret
}
");
}
[WorkItem(22841, "https://github.com/dotnet/roslyn/issues/22841")]
[CompilerTrait(CompilerFeature.PEVerifyCompat)]
[Fact]
public void ReadonlyAddressStrict()
{
string source = @"
class Program
{
static void Main(string[] args)
{
var stringArray = new string[] { ""hi"", ""hello"" };
var objectArray = (object[])stringArray;
Test(GetElementRef(objectArray));
}
static ref readonly T GetElementRef<T>(T[] objectArray)
{
Test(in objectArray[0]);
return ref objectArray[0];
}
static void Test<T>(in T r)
{
System.Console.Write(r);
}
}";
// PEVerify:
// [ : Program::GetElementRef[T]][mdToken=0x6000004][offset 0x00000009][found readonly address of ref ][expected address of ref ] Unexpected type on the stack.
// [ : Program::GetElementRef[T]][mdToken= 0x6000004][offset 0x00000017][found readonly address of ref ][expected address of ref ] Unexpected type on the stack.
// ILVerify:
// Unexpected type on the stack. { Offset = 9, Found = readonly address of 'T', Expected = address of 'T' }
// Unexpected type on the stack. { Offset = 23, Found = readonly address of 'T', Expected = address of 'T' }
var compilation = CompileAndVerify(source, expectedOutput: @"hihi", verify: Verification.Fails);
var expectedIL = @"
{
// Code size 24 (0x18)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: readonly.
IL_0004: ldelema ""T""
IL_0009: call ""void Program.Test<T>(in T)""
IL_000e: ldarg.0
IL_000f: ldc.i4.0
IL_0010: readonly.
IL_0012: ldelema ""T""
IL_0017: ret
}
";
compilation.VerifyIL("Program.GetElementRef<T>(T[])", expectedIL);
// expect the same IL in the compat case since direct references are required and must be emitted with "readonly.", even though unverifiable
compilation = CompileAndVerify(source, expectedOutput: @"hihi", verify: Verification.Fails, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
compilation.VerifyIL("Program.GetElementRef<T>(T[])", expectedIL);
}
[Fact]
public void EnumConv()
{
string source = @"
public class D
{
public static void Main()
{
long l = 1L;
System.Runtime.GCLatencyMode x = (System.Runtime.GCLatencyMode)l;
System.Console.Write(x);
int y = (int)x;
System.Console.Write(y);
short z = (short)x;
System.Console.Write(z);
ushort z1 = (ushort)x;
System.Console.Write(z1);
x = (System.Runtime.GCLatencyMode)z1;
System.StringComparison sc = (System.StringComparison)x;
System.Console.Write(sc);
System.Security.SecurityRuleSet sr = (System.Security.SecurityRuleSet)x;
System.Console.Write(sr);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
Interactive111CurrentCultureIgnoreCaseLevel1
");
compilation.VerifyIL("D.Main",
@"{
// Code size 57 (0x39)
.maxstack 2
IL_0000: ldc.i4.1
IL_0001: conv.i8
IL_0002: conv.i4
IL_0003: dup
IL_0004: box ""System.Runtime.GCLatencyMode""
IL_0009: call ""void System.Console.Write(object)""
IL_000e: dup
IL_000f: call ""void System.Console.Write(int)""
IL_0014: dup
IL_0015: conv.i2
IL_0016: call ""void System.Console.Write(int)""
IL_001b: conv.u2
IL_001c: dup
IL_001d: call ""void System.Console.Write(int)""
IL_0022: dup
IL_0023: box ""System.StringComparison""
IL_0028: call ""void System.Console.Write(object)""
IL_002d: conv.u1
IL_002e: box ""System.Security.SecurityRuleSet""
IL_0033: call ""void System.Console.Write(object)""
IL_0038: ret
}
");
}
[Fact]
public void TestListSample()
{
string source = @"
using System;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyList<int> l = new MyList<int>();
l.Add(1);
l.Add(2);
l.Add(3);
Console.WriteLine(l.ToString());
Console.WriteLine(l.Count());
int[] arr = l.ToArray();
Console.Write(arr[0]);
Console.Write(',');
Console.Write(arr[1]);
Console.Write(',');
Console.Write(arr[2]);
Console.WriteLine();
}
}
}
public class MyList<T>
{
public class Node
{
public T element;
public Node next;
public Node(T element)
{
this.element = element;
}
};
Node head;
public void Add(T element)
{
if (head != null)
{
Node t = head;
while (t.next != null)
t = t.next;
t.next = new Node(element);
}
else
{
head = new Node(element);
}
}
public override string ToString()
{
StringBuilder stbldr = new StringBuilder();
Node t = head;
while (t != null)
{
stbldr.AppendLine(t.element.ToString());
t = t.next;
}
return stbldr.ToString();
}
public int Count()
{
int count = 0;
Node node = head;
while (node != null)
{
count = count + 1;
node = node.next;
}
return count;
}
public T[] ToArray()
{
T[] arr = new T[Count()];
int i = 0;
Node node = head;
while (node != null)
{
arr[i] = node.element;
i = i + 1;
node = node.next;
}
return arr;
}
}";
// If we ever stop verifying the execution of this, we need to add IL verification for some of the method bodies.
CompileAndVerify(source, expectedOutput: @"
1
2
3
3
1,2,3
");
}
[Fact]
public void BranchesAndReturn()
{
string source = @"
public class D
{
static int R;
static void M(bool getLocal, int arg)
{
int y = 123;
if (getLocal)
{
while (getLocal)
{
if (!getLocal)
{
R = y;
}
else
{
R = y;
return;
}
}
return;
}
else
{
R = arg;
return;
}
}
public static void Main()
{
M(false, 42);
System.Console.Write(D.R);
M(true, 42);
System.Console.Write(D.R);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42123");
compilation.VerifyIL("D.Main",
@"{
// Code size 37 (0x25)
.maxstack 2
IL_0000: ldc.i4.0
IL_0001: ldc.i4.s 42
IL_0003: call ""void D.M(bool, int)""
IL_0008: ldsfld ""int D.R""
IL_000d: call ""void System.Console.Write(int)""
IL_0012: ldc.i4.1
IL_0013: ldc.i4.s 42
IL_0015: call ""void D.M(bool, int)""
IL_001a: ldsfld ""int D.R""
IL_001f: call ""void System.Console.Write(int)""
IL_0024: ret
}
");
}
[Fact]
public void UnaryLogOp()
{
string source = @"
public class D
{
public static void Main()
{
bool x = bool.Parse(""true"");
bool y = !!!!!!!!!!!!!!!x;
if (!y)
{
System.Console.Write(x);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"True");
compilation.VerifyIL("D.Main",
@"{
// Code size 24 (0x18)
.maxstack 2
.locals init (bool V_0) //x
IL_0000: ldstr ""true""
IL_0005: call ""bool bool.Parse(string)""
IL_000a: stloc.0
IL_000b: ldloc.0
IL_000c: ldc.i4.0
IL_000d: ceq
IL_000f: brtrue.s IL_0017
IL_0011: ldloc.0
IL_0012: call ""void System.Console.Write(bool)""
IL_0017: ret
}
");
}
[Fact]
public void LogAndOr()
{
string source = @"
public class D
{
public static void Main()
{
bool x = bool.Parse(""true"");
bool y = bool.Parse(""false"");
bool z = !(!(x || y) && x);
if ((x || y) && x)
{
System.Console.Write(z);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"True");
// The last if condition is more compact than in Dev10.
compilation.VerifyIL("D.Main", @"
{
// Code size 48 (0x30)
.maxstack 2
.locals init (bool V_0, //x
bool V_1, //y
bool V_2) //z
IL_0000: ldstr ""true""
IL_0005: call ""bool bool.Parse(string)""
IL_000a: stloc.0
IL_000b: ldstr ""false""
IL_0010: call ""bool bool.Parse(string)""
IL_0015: stloc.1
IL_0016: ldloc.0
IL_0017: ldloc.1
IL_0018: or
IL_0019: ldc.i4.0
IL_001a: ceq
IL_001c: ldloc.0
IL_001d: and
IL_001e: ldc.i4.0
IL_001f: ceq
IL_0021: stloc.2
IL_0022: ldloc.0
IL_0023: ldloc.1
IL_0024: or
IL_0025: ldloc.0
IL_0026: and
IL_0027: brfalse.s IL_002f
IL_0029: ldloc.2
IL_002a: call ""void System.Console.Write(bool)""
IL_002f: ret
}");
}
[Fact]
public void RelationalOps1()
{
string source = @"
public class D
{
public static void Main()
{
int x = 1;
int y = 2;
if (x < y)
{
if (y > x)
{
if (y >= x)
{
if (y != x)
{
System.Console.Write(1);
}
if (y == x)
{
System.Console.Write(1);
}
}
}
}
}
}
";
CompileAndVerify(source, expectedOutput: @"1").
VerifyIL("D.Main",
@"{
// Code size 37 (0x25)
.maxstack 2
.locals init (int V_0, //x
int V_1) //y
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldc.i4.2
IL_0003: stloc.1
IL_0004: ldloc.0
IL_0005: ldloc.1
IL_0006: bge.s IL_0024
IL_0008: ldloc.1
IL_0009: ldloc.0
IL_000a: ble.s IL_0024
IL_000c: ldloc.1
IL_000d: ldloc.0
IL_000e: blt.s IL_0024
IL_0010: ldloc.1
IL_0011: ldloc.0
IL_0012: beq.s IL_001a
IL_0014: ldc.i4.1
IL_0015: call ""void System.Console.Write(int)""
IL_001a: ldloc.1
IL_001b: ldloc.0
IL_001c: bne.un.s IL_0024
IL_001e: ldc.i4.1
IL_001f: call ""void System.Console.Write(int)""
IL_0024: ret
}
");
var v = CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: @"1");
v.VerifyIL("D.Main",
@"{
// Code size 82 (0x52)
.maxstack 2
.locals init (int V_0, //x
int V_1, //y
bool V_2,
bool V_3,
bool V_4,
bool V_5,
bool V_6)
-IL_0000: nop
-IL_0001: ldc.i4.1
IL_0002: stloc.0
-IL_0003: ldc.i4.2
IL_0004: stloc.1
-IL_0005: ldloc.0
IL_0006: ldloc.1
IL_0007: clt
IL_0009: stloc.2
~IL_000a: ldloc.2
IL_000b: brfalse.s IL_0051
-IL_000d: nop
-IL_000e: ldloc.1
IL_000f: ldloc.0
IL_0010: cgt
IL_0012: stloc.3
~IL_0013: ldloc.3
IL_0014: brfalse.s IL_0050
-IL_0016: nop
-IL_0017: ldloc.1
IL_0018: ldloc.0
IL_0019: clt
IL_001b: ldc.i4.0
IL_001c: ceq
IL_001e: stloc.s V_4
~IL_0020: ldloc.s V_4
IL_0022: brfalse.s IL_004f
-IL_0024: nop
-IL_0025: ldloc.1
IL_0026: ldloc.0
IL_0027: ceq
IL_0029: ldc.i4.0
IL_002a: ceq
IL_002c: stloc.s V_5
~IL_002e: ldloc.s V_5
IL_0030: brfalse.s IL_003b
-IL_0032: nop
-IL_0033: ldc.i4.1
IL_0034: call ""void System.Console.Write(int)""
IL_0039: nop
-IL_003a: nop
-IL_003b: ldloc.1
IL_003c: ldloc.0
IL_003d: ceq
IL_003f: stloc.s V_6
~IL_0041: ldloc.s V_6
IL_0043: brfalse.s IL_004e
-IL_0045: nop
-IL_0046: ldc.i4.1
IL_0047: call ""void System.Console.Write(int)""
IL_004c: nop
-IL_004d: nop
-IL_004e: nop
-IL_004f: nop
-IL_0050: nop
-IL_0051: ret
}
", sequencePoints: "D.Main");
}
[Fact]
public void RelationalOps2()
{
string source = @"
public class D
{
public static void Main()
{
uint x = 1;
uint y = 2;
if (x < y)
{
if (!(x > y))
{
if (y >= x)
{
if (y != x)
{
System.Console.Write(1);
}
if (y == x)
{
System.Console.Write(1);
}
}
}
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"1");
compilation.VerifyIL("D.Main",
@"{
// Code size 37 (0x25)
.maxstack 2
.locals init (uint V_0, //x
uint V_1) //y
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldc.i4.2
IL_0003: stloc.1
IL_0004: ldloc.0
IL_0005: ldloc.1
IL_0006: bge.un.s IL_0024
IL_0008: ldloc.0
IL_0009: ldloc.1
IL_000a: bgt.un.s IL_0024
IL_000c: ldloc.1
IL_000d: ldloc.0
IL_000e: blt.un.s IL_0024
IL_0010: ldloc.1
IL_0011: ldloc.0
IL_0012: beq.s IL_001a
IL_0014: ldc.i4.1
IL_0015: call ""void System.Console.Write(int)""
IL_001a: ldloc.1
IL_001b: ldloc.0
IL_001c: bne.un.s IL_0024
IL_001e: ldc.i4.1
IL_001f: call ""void System.Console.Write(int)""
IL_0024: ret
}
");
}
[Fact]
public void SimpleCompareRef()
{
string source = @"
public class D
{
public static void Main()
{
bool x = bool.Parse(""true"");
if (x.ToString() != null)
{
System.Console.Write(x);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"True");
compilation.VerifyIL("D.Main",
@"{
// Code size 27 (0x1b)
.maxstack 1
.locals init (bool V_0) //x
IL_0000: ldstr ""true""
IL_0005: call ""bool bool.Parse(string)""
IL_000a: stloc.0
IL_000b: ldloca.s V_0
IL_000d: call ""string bool.ToString()""
IL_0012: brfalse.s IL_001a
IL_0014: ldloc.0
IL_0015: call ""void System.Console.Write(bool)""
IL_001a: ret
}
");
}
[Fact]
public void SimpleCompare()
{
string source = @"
public class D
{
public static void Main()
{
bool x = bool.Parse(""true"");
if ((!!!!!!!!!!!!!!!!x) == true)
{
System.Console.Write(x);
}
if ((!!!!!!!!!!!!!!!x) == false)
{
System.Console.Write(x);
}
ulong u123 = ulong.Parse(""123"");
if (u123 != 0)
{
System.Console.Write(x);
}
long l123 = long.Parse(""123"");
if (-l123 != 0)
{
System.Console.Write(x);
}
double NaN = 1.0/0;
if (NaN != 0)
{
System.Console.Write(x);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"TrueTrueTrueTrueTrue");
compilation.VerifyIL("D.Main",
@"{
// Code size 93 (0x5d)
.maxstack 2
.locals init (bool V_0) //x
IL_0000: ldstr ""true""
IL_0005: call ""bool bool.Parse(string)""
IL_000a: stloc.0
IL_000b: ldloc.0
IL_000c: brfalse.s IL_0014
IL_000e: ldloc.0
IL_000f: call ""void System.Console.Write(bool)""
IL_0014: ldloc.0
IL_0015: brfalse.s IL_001d
IL_0017: ldloc.0
IL_0018: call ""void System.Console.Write(bool)""
IL_001d: ldstr ""123""
IL_0022: call ""ulong ulong.Parse(string)""
IL_0027: brfalse.s IL_002f
IL_0029: ldloc.0
IL_002a: call ""void System.Console.Write(bool)""
IL_002f: ldstr ""123""
IL_0034: call ""long long.Parse(string)""
IL_0039: neg
IL_003a: brfalse.s IL_0042
IL_003c: ldloc.0
IL_003d: call ""void System.Console.Write(bool)""
IL_0042: ldc.r8 Infinity
IL_004b: ldc.r8 0
IL_0054: beq.s IL_005c
IL_0056: ldloc.0
IL_0057: call ""void System.Console.Write(bool)""
IL_005c: ret
}
");
}
[Fact]
public void ConstBranch()
{
string source = @"
public class D
{
public static void Main()
{
if (!!false) {
System.Console.Write(0);
}else{
System.Console.Write(1);
}
if (!!!!!!!!!!!!!!!!true)
{
System.Console.Write(2);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"12");
compilation.VerifyIL("D.Main",
@"{
// Code size 13 (0xd)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: call ""void System.Console.Write(int)""
IL_0006: ldc.i4.2
IL_0007: call ""void System.Console.Write(int)""
IL_000c: ret
}
");
}
[Fact]
public void ByrefArg()
{
string source = @"
public class D
{
public static void Main()
{
System.Collections.Generic.Dictionary<int, string> dict = new System.Collections.Generic.Dictionary<int, string>();
dict.Add(1, ""one"");
dict.Add(2, ""two"");
string s = """";
dict.TryGetValue(1, out s);
System.Console.Write(s);
dict.TryGetValue(2, out s);
System.Console.Write(s);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"onetwo");
compilation.VerifyIL("D.Main",
@"{
// Code size 67 (0x43)
.maxstack 4
.locals init (string V_0) //s
IL_0000: newobj ""System.Collections.Generic.Dictionary<int, string>..ctor()""
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: ldstr ""one""
IL_000c: callvirt ""void System.Collections.Generic.Dictionary<int, string>.Add(int, string)""
IL_0011: dup
IL_0012: ldc.i4.2
IL_0013: ldstr ""two""
IL_0018: callvirt ""void System.Collections.Generic.Dictionary<int, string>.Add(int, string)""
IL_001d: ldstr """"
IL_0022: stloc.0
IL_0023: dup
IL_0024: ldc.i4.1
IL_0025: ldloca.s V_0
IL_0027: callvirt ""bool System.Collections.Generic.Dictionary<int, string>.TryGetValue(int, out string)""
IL_002c: pop
IL_002d: ldloc.0
IL_002e: call ""void System.Console.Write(string)""
IL_0033: ldc.i4.2
IL_0034: ldloca.s V_0
IL_0036: callvirt ""bool System.Collections.Generic.Dictionary<int, string>.TryGetValue(int, out string)""
IL_003b: pop
IL_003c: ldloc.0
IL_003d: call ""void System.Console.Write(string)""
IL_0042: ret
}
");
}
[Fact]
public void ByrefParam()
{
string source = @"
public class D
{
public static void Inc(ref int x)
{
x = x + 1;
}
public static void Main()
{
int x = 1;
Inc(ref x);
System.Console.Write(x);
Inc(ref x);
System.Console.Write(x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"23");
compilation.VerifyIL("D.Inc",
@"
{
// Code size 7 (0x7)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: ldc.i4.1
IL_0004: add
IL_0005: stind.i4
IL_0006: ret
}
");
}
[Fact]
public void ByrefArg2()
{
string source = @"
public class D
{
public static void ProxyGet(System.Collections.Generic.Dictionary<int, string> dict, int val, out string s)
{
dict.TryGetValue(val, out s);
}
public static void Main()
{
System.Collections.Generic.Dictionary<int, string> dict = new System.Collections.Generic.Dictionary<int, string>();
dict.Add(1, ""one"");
dict.Add(2, ""two"");
string s = """";
ProxyGet(dict, 1, out s);
System.Console.Write(s);
ProxyGet(dict, 2, out s);
System.Console.Write(s);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"onetwo");
compilation.VerifyIL("D.ProxyGet",
@"{
// Code size 10 (0xa)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: callvirt ""bool System.Collections.Generic.Dictionary<int, string>.TryGetValue(int, out string)""
IL_0008: pop
IL_0009: ret
}
");
}
[Fact]
public void ByrefParamRef()
{
string source = @"
public class D
{
public static void Inc(ref object x)
{
string s = (string)x;
x = string.Concat(s, ""#"");
}
public static void Main()
{
object x = ""A"";
Inc(ref x);
System.Console.Write(x);
Inc(ref x);
System.Console.Write(x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"A#A##");
compilation.VerifyIL("D.Inc",
@"{
// Code size 22 (0x16)
.maxstack 3
.locals init (string V_0) //s
IL_0000: ldarg.0
IL_0001: ldind.ref
IL_0002: castclass ""string""
IL_0007: stloc.0
IL_0008: ldarg.0
IL_0009: ldloc.0
IL_000a: ldstr ""#""
IL_000f: call ""string string.Concat(string, string)""
IL_0014: stind.ref
IL_0015: ret
}
");
}
[Fact]
public void ByrefParamStruct()
{
string source = @"
public class D
{
public struct S1
{
public S2 x;
}
public struct S2
{
public int x;
}
public static void Inc(ref S1 x)
{
x.x.x = x.x.x + 1;
}
public static void Main()
{
S1 x = new S1();
Inc(ref x);
System.Console.Write(x.x.x);
Inc(ref x);
System.Console.Write(x.x.x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"12");
compilation.VerifyIL("D.Inc",
@"{
// Code size 25 (0x19)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldflda ""D.S2 D.S1.x""
IL_0006: ldarg.0
IL_0007: ldflda ""D.S2 D.S1.x""
IL_000c: ldfld ""int D.S2.x""
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stfld ""int D.S2.x""
IL_0018: ret
}
");
}
[Fact]
public void ByrefParamEnum()
{
string source = @"
public class D
{
public static void Inc(ref System.StringComparison x)
{
x = x + 1;
}
public static void Main()
{
System.StringComparison x = (System.StringComparison)0;
Inc(ref x);
System.Console.Write(x);
Inc(ref x);
System.Console.Write(x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"CurrentCultureIgnoreCaseInvariantCulture");
compilation.VerifyIL("D.Inc",
@"
{
// Code size 7 (0x7)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: ldc.i4.1
IL_0004: add
IL_0005: stind.i4
IL_0006: ret
}
");
}
[Fact]
public void RefAssign()
{
string source = @"
public class D
{
public static void Inc(ref int x, ref int y)
{
System.Console.Write(x = y); // temp is NOT a ref here.
y = x + 1;
}
public static void Main()
{
int x = 0;
int y = 1;
Inc(ref x, ref y);
Inc(ref x, ref y);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"12");
compilation.VerifyIL("D.Inc",
@"{
// Code size 19 (0x13)
.maxstack 3
.locals init (int V_0)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldind.i4
IL_0003: dup
IL_0004: stloc.0
IL_0005: stind.i4
IL_0006: ldloc.0
IL_0007: call ""void System.Console.Write(int)""
IL_000c: ldarg.1
IL_000d: ldarg.0
IL_000e: ldind.i4
IL_000f: ldc.i4.1
IL_0010: add
IL_0011: stind.i4
IL_0012: ret
}
");
}
[WorkItem(9229, "DevDiv_Projects/Roslyn")]
[Fact]
public void ByrefTemp1()
{
string source = @"
public class D
{
public class DD
{
public int[] a1;
public int[] a2;
public DD()
{
a1 = new int[] {1,2,3,4,5,6};
a2 = new int[] {4,5,6,7,8,9};
}
public int[] B()
{
System.Console.Write(""B"");
return a1;
}
public int C()
{
System.Console.Write(""C"");
return 1;
}
public int[] D()
{
System.Console.Write(""D"");
return a2;
}
public int E()
{
System.Console.Write(""E"");
return 1;
}
public void M(ref int x, ref int y)
{
x = 42;
y = 24;
}
public void Test()
{
// this will require a ref temp for ref B()[C()]
M(y: ref B()[C()], x: ref D()[E()]);
}
}
public static void Main()
{
DD v = new DD();
v.Test();
System.Console.Write(v.a1[1]);
System.Console.Write(v.a2[1]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"BCDE2442");
compilation.VerifyIL("D.DD.Test",
@"{
// Code size 43 (0x2b)
.maxstack 3
.locals init (int& V_0)
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call ""int[] D.DD.B()""
IL_0007: ldarg.0
IL_0008: call ""int D.DD.C()""
IL_000d: ldelema ""int""
IL_0012: stloc.0
IL_0013: ldarg.0
IL_0014: call ""int[] D.DD.D()""
IL_0019: ldarg.0
IL_001a: call ""int D.DD.E()""
IL_001f: ldelema ""int""
IL_0024: ldloc.0
IL_0025: call ""void D.DD.M(ref int, ref int)""
IL_002a: ret
}
");
}
[Fact]
public void LongBranch()
{
string source = @"
public class D
{
public static double x;
public static void Goo(double x)
{
}
public static void Main()
{
if (x == 0) // long branch
{
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
}
else
{
if (x == 0) // short branch
{
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
Goo(1.0);
}
}
System.Console.Write(""hi"");
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"hi");
compilation.VerifyIL("D.Main",
@"{
// Code size 317 (0x13d)
.maxstack 2
IL_0000: ldsfld ""double D.x""
IL_0005: ldc.r8 0
IL_000e: bne.un IL_00a4
IL_0013: ldc.r8 1
IL_001c: call ""void D.Goo(double)""
IL_0021: ldc.r8 1
IL_002a: call ""void D.Goo(double)""
IL_002f: ldc.r8 1
IL_0038: call ""void D.Goo(double)""
IL_003d: ldc.r8 1
IL_0046: call ""void D.Goo(double)""
IL_004b: ldc.r8 1
IL_0054: call ""void D.Goo(double)""
IL_0059: ldc.r8 1
IL_0062: call ""void D.Goo(double)""
IL_0067: ldc.r8 1
IL_0070: call ""void D.Goo(double)""
IL_0075: ldc.r8 1
IL_007e: call ""void D.Goo(double)""
IL_0083: ldc.r8 1
IL_008c: call ""void D.Goo(double)""
IL_0091: ldc.r8 1
IL_009a: call ""void D.Goo(double)""
IL_009f: br IL_0132
IL_00a4: ldsfld ""double D.x""
IL_00a9: ldc.r8 0
IL_00b2: bne.un.s IL_0132
IL_00b4: ldc.r8 1
IL_00bd: call ""void D.Goo(double)""
IL_00c2: ldc.r8 1
IL_00cb: call ""void D.Goo(double)""
IL_00d0: ldc.r8 1
IL_00d9: call ""void D.Goo(double)""
IL_00de: ldc.r8 1
IL_00e7: call ""void D.Goo(double)""
IL_00ec: ldc.r8 1
IL_00f5: call ""void D.Goo(double)""
IL_00fa: ldc.r8 1
IL_0103: call ""void D.Goo(double)""
IL_0108: ldc.r8 1
IL_0111: call ""void D.Goo(double)""
IL_0116: ldc.r8 1
IL_011f: call ""void D.Goo(double)""
IL_0124: ldc.r8 1
IL_012d: call ""void D.Goo(double)""
IL_0132: ldstr ""hi""
IL_0137: call ""void System.Console.Write(string)""
IL_013c: ret
}
");
}
[Fact]
public void InductiveShortBranches()
{
string source = @"
public class D
{
public static int x;
public static void Goo(double x)
{
}
public static void Main()
{
//some branches will be short
//some branches will be short only after nested branches become short
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
if (x == 0)
{
Goo(1.0);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
System.Console.Write(""hi"");
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"hi");
compilation.VerifyIL("D.Main",
@"{
// Code size 164 (0xa4)
.maxstack 1
IL_0000: ldsfld ""int D.x""
IL_0005: brtrue IL_0099
IL_000a: ldsfld ""int D.x""
IL_000f: brtrue IL_0099
IL_0014: ldsfld ""int D.x""
IL_0019: brtrue.s IL_0099
IL_001b: ldsfld ""int D.x""
IL_0020: brtrue.s IL_0099
IL_0022: ldsfld ""int D.x""
IL_0027: brtrue.s IL_0099
IL_0029: ldsfld ""int D.x""
IL_002e: brtrue.s IL_0099
IL_0030: ldsfld ""int D.x""
IL_0035: brtrue.s IL_0099
IL_0037: ldsfld ""int D.x""
IL_003c: brtrue.s IL_0099
IL_003e: ldsfld ""int D.x""
IL_0043: brtrue.s IL_0099
IL_0045: ldsfld ""int D.x""
IL_004a: brtrue.s IL_0099
IL_004c: ldsfld ""int D.x""
IL_0051: brtrue.s IL_0099
IL_0053: ldsfld ""int D.x""
IL_0058: brtrue.s IL_0099
IL_005a: ldsfld ""int D.x""
IL_005f: brtrue.s IL_0099
IL_0061: ldsfld ""int D.x""
IL_0066: brtrue.s IL_0099
IL_0068: ldsfld ""int D.x""
IL_006d: brtrue.s IL_0099
IL_006f: ldsfld ""int D.x""
IL_0074: brtrue.s IL_0099
IL_0076: ldsfld ""int D.x""
IL_007b: brtrue.s IL_0099
IL_007d: ldsfld ""int D.x""
IL_0082: brtrue.s IL_0099
IL_0084: ldsfld ""int D.x""
IL_0089: brtrue.s IL_0099
IL_008b: ldc.r8 1
IL_0094: call ""void D.Goo(double)""
IL_0099: ldstr ""hi""
IL_009e: call ""void System.Console.Write(string)""
IL_00a3: ret
}
");
}
[WorkItem(9229, "DevDiv_Projects/Roslyn")]
[ConditionalFact(typeof(DesktopOnly))]
public void InitFromBlob()
{
string source = @"
using System.Globalization;
public class D
{
public static void Main()
{
int[] x = new int[] { 1, 2, 3, 4, -5 };
System.Console.WriteLine(x[2]);
System.Console.WriteLine(x[4]);
bool[] b = new bool[] { true, false, true, false, true };
System.Console.WriteLine(b[2]);
System.Console.WriteLine(b[3]);
byte[] by = new byte[] { 0, 127, 223, 128, 220 };
System.Console.WriteLine(by[2]);
System.Console.WriteLine(by[3]);
char[] c = new char[] { 'a', 'b', 'c', 'd', 'e' };
System.Console.WriteLine(c[2]);
System.Console.WriteLine(c[4]);
float[] s = new float[] { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f };
System.Console.WriteLine(s[2].ToString(CultureInfo.InvariantCulture));
System.Console.WriteLine(s[4].ToString(CultureInfo.InvariantCulture));
double[] d = new double[] { 1.1f, 2.2f, -3.3f / 0, 4.4f, -5.5f };
System.Console.WriteLine(d[2].ToString(CultureInfo.InvariantCulture));
System.Console.WriteLine(d[4].ToString(CultureInfo.InvariantCulture));
}
}";
var compilation = CompileAndVerifyWithMscorlib40(source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"), expectedOutput: @"
3
-5
True
False
223
128
c
e
3.3
5.5
-Infinity
-5.5
");
compilation.VerifyIL("D.Main", """
{
// Code size 249 (0xf9)
.maxstack 3
IL_0000: ldc.i4.5
IL_0001: newarr "int"
IL_0006: dup
IL_0007: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=20 <PrivateImplementationDetails>.45ADA43E830E5E3307519346BD95FFFAE55587E4B475BC481E2B70054B75C386"
IL_000c: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_0011: dup
IL_0012: ldc.i4.2
IL_0013: ldelem.i4
IL_0014: call "void System.Console.WriteLine(int)"
IL_0019: ldc.i4.4
IL_001a: ldelem.i4
IL_001b: call "void System.Console.WriteLine(int)"
IL_0020: ldc.i4.5
IL_0021: newarr "bool"
IL_0026: dup
IL_0027: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=5 <PrivateImplementationDetails>.A4E9167DC11A5B8BA7E09C85BAFDEA0B6E0B399CE50086545509017050B33097"
IL_002c: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_0031: dup
IL_0032: ldc.i4.2
IL_0033: ldelem.u1
IL_0034: call "void System.Console.WriteLine(bool)"
IL_0039: ldc.i4.3
IL_003a: ldelem.u1
IL_003b: call "void System.Console.WriteLine(bool)"
IL_0040: ldc.i4.5
IL_0041: newarr "byte"
IL_0046: dup
IL_0047: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=5 <PrivateImplementationDetails>.5BD81897B38CE00BCF990B5AED9316FE43E7A3854DA09401C14DF4AF21B2F90D"
IL_004c: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_0051: dup
IL_0052: ldc.i4.2
IL_0053: ldelem.u1
IL_0054: call "void System.Console.WriteLine(int)"
IL_0059: ldc.i4.3
IL_005a: ldelem.u1
IL_005b: call "void System.Console.WriteLine(int)"
IL_0060: ldc.i4.5
IL_0061: newarr "char"
IL_0066: dup
IL_0067: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=10 <PrivateImplementationDetails>.DC0F42A41F058686A364AF5B6BD49175C5B2CF3C4D5AE95417448BE3517B4008"
IL_006c: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_0071: dup
IL_0072: ldc.i4.2
IL_0073: ldelem.u2
IL_0074: call "void System.Console.WriteLine(char)"
IL_0079: ldc.i4.4
IL_007a: ldelem.u2
IL_007b: call "void System.Console.WriteLine(char)"
IL_0080: ldc.i4.5
IL_0081: newarr "float"
IL_0086: dup
IL_0087: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=20 <PrivateImplementationDetails>.0956A7FE9F6549A51F1EF3A6E0CD03FE7CF1EB2762309FC2A941F85C7E461827"
IL_008c: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_0091: dup
IL_0092: ldc.i4.2
IL_0093: ldelema "float"
IL_0098: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_009d: call "string float.ToString(System.IFormatProvider)"
IL_00a2: call "void System.Console.WriteLine(string)"
IL_00a7: ldc.i4.4
IL_00a8: ldelema "float"
IL_00ad: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_00b2: call "string float.ToString(System.IFormatProvider)"
IL_00b7: call "void System.Console.WriteLine(string)"
IL_00bc: ldc.i4.5
IL_00bd: newarr "double"
IL_00c2: dup
IL_00c3: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=40 <PrivateImplementationDetails>.F9D819AD50107F52959882DF3549DE08003AC644DCC12AFEA2B9BD936EE7D325"
IL_00c8: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_00cd: dup
IL_00ce: ldc.i4.2
IL_00cf: ldelema "double"
IL_00d4: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_00d9: call "string double.ToString(System.IFormatProvider)"
IL_00de: call "void System.Console.WriteLine(string)"
IL_00e3: ldc.i4.4
IL_00e4: ldelema "double"
IL_00e9: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_00ee: call "string double.ToString(System.IFormatProvider)"
IL_00f3: call "void System.Console.WriteLine(string)"
IL_00f8: ret
}
""");
}
[WorkItem(9229, "DevDiv_Projects/Roslyn")]
[Fact]
public void InitFromBlobPartial()
{
string source = @"
public class D
{
public static void Main()
{
int[] x = new int[] {1,2,System.Int32.Parse(""3""),4,5};
System.Console.Write(x[2]);
x = new int[] {1,2,3,4, -x[4]};
System.Console.Write(x[4]);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"), expectedOutput: @"3-5");
//string pid = "<PrivateImplementationDetails>" + compilation.Compilation.SourceModule.Pers
compilation.VerifyIL("D.Main",
@"{
// Code size 73 (0x49)
.maxstack 5
.locals init (int[] V_0) //x
IL_0000: ldc.i4.5
IL_0001: newarr ""int""
IL_0006: dup
IL_0007: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=20 <PrivateImplementationDetails>.BD7819A4179E7ACF9BDBEBF011C106FA85D32545EEE26D28FBF9068F4DEB6658""
IL_000c: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0011: dup
IL_0012: ldc.i4.2
IL_0013: ldstr ""3""
IL_0018: call ""int int.Parse(string)""
IL_001d: stelem.i4
IL_001e: stloc.0
IL_001f: ldloc.0
IL_0020: ldc.i4.2
IL_0021: ldelem.i4
IL_0022: call ""void System.Console.Write(int)""
IL_0027: ldc.i4.5
IL_0028: newarr ""int""
IL_002d: dup
IL_002e: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=20 <PrivateImplementationDetails>.2C749102AF8952FBBED5FE95192883A4153E80448EB125C01A8B2961C0B266E9""
IL_0033: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0038: dup
IL_0039: ldc.i4.4
IL_003a: ldloc.0
IL_003b: ldc.i4.4
IL_003c: ldelem.i4
IL_003d: neg
IL_003e: stelem.i4
IL_003f: stloc.0
IL_0040: ldloc.0
IL_0041: ldc.i4.4
IL_0042: ldelem.i4
IL_0043: call ""void System.Console.Write(int)""
IL_0048: ret
}
");
}
[Fact]
public void InitFromBlobPartial001()
{
string source = @"
public class D
{
public static void Main()
{
int[] x = new int[] {0,0,System.Int32.Parse(""3""),System.Int32.Parse(""4""),5, 0,0,0,0,0};
System.Console.Write(x[2]);
x = new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,2,-x[4], 3, 4};
System.Console.Write(x[4]);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"), expectedOutput: @"30");
//string pid = "<PrivateImplementationDetails>" + compilation.Compilation.SourceModule.Pers
compilation.VerifyIL("D.Main",
@"{
// Code size 82 (0x52)
.maxstack 5
.locals init (int[] V_0) //x
IL_0000: ldc.i4.s 10
IL_0002: newarr ""int""
IL_0007: dup
IL_0008: ldc.i4.2
IL_0009: ldstr ""3""
IL_000e: call ""int int.Parse(string)""
IL_0013: stelem.i4
IL_0014: dup
IL_0015: ldc.i4.3
IL_0016: ldstr ""4""
IL_001b: call ""int int.Parse(string)""
IL_0020: stelem.i4
IL_0021: dup
IL_0022: ldc.i4.4
IL_0023: ldc.i4.5
IL_0024: stelem.i4
IL_0025: stloc.0
IL_0026: ldloc.0
IL_0027: ldc.i4.2
IL_0028: ldelem.i4
IL_0029: call ""void System.Console.Write(int)""
IL_002e: ldc.i4.s 15
IL_0030: newarr ""int""
IL_0035: dup
IL_0036: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=60 <PrivateImplementationDetails>.D6D2D407F387FBD5A6686795005577AE90492DFD316E28ECA98CA47FAF9C99C0""
IL_003b: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0040: dup
IL_0041: ldc.i4.s 12
IL_0043: ldloc.0
IL_0044: ldc.i4.4
IL_0045: ldelem.i4
IL_0046: neg
IL_0047: stelem.i4
IL_0048: stloc.0
IL_0049: ldloc.0
IL_004a: ldc.i4.4
IL_004b: ldelem.i4
IL_004c: call ""void System.Console.Write(int)""
IL_0051: ret
}
");
}
[Fact]
public void ArrayInitFromBlobEnum()
{
string source = @"
public class D
{
public static void Main()
{
System.TypeCode[] x = new System.TypeCode[] {
System.TypeCode.Boolean,
System.TypeCode.Byte,
System.TypeCode.Char,
System.TypeCode.DateTime,
System.TypeCode.DBNull
};
System.Console.WriteLine(x[1]);
System.Console.WriteLine(x[2]);
System.Console.WriteLine(x[4]);
}
}
";
var compilation = CompileAndVerifyWithMscorlib40(source, expectedOutput: @"
Byte
Char
DBNull
");
//NOTE:
// the emit is specific to the target CLR version
// on > 4.0 this is optimizable.
compilation.VerifyIL("D.Main",
@"{
// Code size 66 (0x42)
.maxstack 4
IL_0000: ldc.i4.5
IL_0001: newarr ""System.TypeCode""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.3
IL_0009: stelem.i4
IL_000a: dup
IL_000b: ldc.i4.1
IL_000c: ldc.i4.6
IL_000d: stelem.i4
IL_000e: dup
IL_000f: ldc.i4.2
IL_0010: ldc.i4.4
IL_0011: stelem.i4
IL_0012: dup
IL_0013: ldc.i4.3
IL_0014: ldc.i4.s 16
IL_0016: stelem.i4
IL_0017: dup
IL_0018: ldc.i4.4
IL_0019: ldc.i4.2
IL_001a: stelem.i4
IL_001b: dup
IL_001c: ldc.i4.1
IL_001d: ldelem.i4
IL_001e: box ""System.TypeCode""
IL_0023: call ""void System.Console.WriteLine(object)""
IL_0028: dup
IL_0029: ldc.i4.2
IL_002a: ldelem.i4
IL_002b: box ""System.TypeCode""
IL_0030: call ""void System.Console.WriteLine(object)""
IL_0035: ldc.i4.4
IL_0036: ldelem.i4
IL_0037: box ""System.TypeCode""
IL_003c: call ""void System.Console.WriteLine(object)""
IL_0041: ret
}
");
}
[Fact]
public void ArrayInitFromBlobEnumNetFx45()
{
var source = @"
public class D
{
public static void Main()
{
System.TypeCode[] x = new System.TypeCode[] {
System.TypeCode.Boolean,
System.TypeCode.Byte,
System.TypeCode.Char,
System.TypeCode.DateTime,
System.TypeCode.DBNull
};
System.Console.WriteLine(x[1]);
System.Console.WriteLine(x[2]);
System.Console.WriteLine(x[4]);
}
}
";
var expectedOutput = @"
Byte
Char
DBNull
";
var compilation = CreateCompilationWithMscorlib461(source: source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"));
var verifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
//NOTE:
// the emit is specific to the target CLR version
verifier.VerifyIL("D.Main",
@"{
// Code size 56 (0x38)
.maxstack 3
IL_0000: ldc.i4.5
IL_0001: newarr ""System.TypeCode""
IL_0006: dup
IL_0007: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=20 <PrivateImplementationDetails>.095C4722BB84316FEEE41ADFDAFED13FECA8836A520BDE3AB77C52F5C9F6B620""
IL_000c: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0011: dup
IL_0012: ldc.i4.1
IL_0013: ldelem.i4
IL_0014: box ""System.TypeCode""
IL_0019: call ""void System.Console.WriteLine(object)""
IL_001e: dup
IL_001f: ldc.i4.2
IL_0020: ldelem.i4
IL_0021: box ""System.TypeCode""
IL_0026: call ""void System.Console.WriteLine(object)""
IL_002b: ldc.i4.4
IL_002c: ldelem.i4
IL_002d: box ""System.TypeCode""
IL_0032: call ""void System.Console.WriteLine(object)""
IL_0037: ret
}
");
}
[WorkItem(538105, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538105")]
[Fact]
public void Temporaries()
{
string source = @"
using System;
class Program
{
static void Main()
{
bool x = true;
int y = (x != true).GetType().GetHashCode() - x.GetType().GetHashCode(); // Temps involved
Console.Write((y + y).ToString()); // Temp involved
}
public void test()
{
this.bar(1).ToString(); // Temp involved
}
public int bar(int x)
{
return 0;
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"0");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 54 (0x36)
.maxstack 2
.locals init (bool V_0, //x
int V_1)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: ceq
IL_0006: box ""bool""
IL_000b: call ""System.Type object.GetType()""
IL_0010: callvirt ""int object.GetHashCode()""
IL_0015: ldloc.0
IL_0016: box ""bool""
IL_001b: call ""System.Type object.GetType()""
IL_0020: callvirt ""int object.GetHashCode()""
IL_0025: sub
IL_0026: dup
IL_0027: add
IL_0028: stloc.1
IL_0029: ldloca.s V_1
IL_002b: call ""string int.ToString()""
IL_0030: call ""void System.Console.Write(string)""
IL_0035: ret
}
");
}
[Fact]
public void TemporariesA()
{
string source = @"
using System;
class Program
{
static void Main()
{
bool x = true;
int y = (x != true).GetType().GetHashCode() - x.GetType().GetHashCode(); // Temps involved
Console.Write((y + y).ToString()); // Temp involved
}
public void test()
{
this.bar(1).ToString(); // Temp involved
}
public int bar(int x)
{
return 0;
}
}";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseDebugExe, expectedOutput: @"0");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 56 (0x38)
.maxstack 2
.locals init (bool V_0, //x
int V_1, //y
int V_2)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: ceq
IL_0006: box ""bool""
IL_000b: call ""System.Type object.GetType()""
IL_0010: callvirt ""int object.GetHashCode()""
IL_0015: ldloc.0
IL_0016: box ""bool""
IL_001b: call ""System.Type object.GetType()""
IL_0020: callvirt ""int object.GetHashCode()""
IL_0025: sub
IL_0026: stloc.1
IL_0027: ldloc.1
IL_0028: ldloc.1
IL_0029: add
IL_002a: stloc.2
IL_002b: ldloca.s V_2
IL_002d: call ""string int.ToString()""
IL_0032: call ""void System.Console.Write(string)""
IL_0037: ret
}
");
}
[Fact]
public void EmitObjectToStringOnSimpleType()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
int x = 123;
Console.WriteLine(x.ToString());
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"123");
compilation.VerifyIL("Program.Main",
@"{
// Code size 16 (0x10)
.maxstack 1
.locals init (int V_0) //x
IL_0000: ldc.i4.s 123
IL_0002: stloc.0
IL_0003: ldloca.s V_0
IL_0005: call ""string int.ToString()""
IL_000a: call ""void System.Console.WriteLine(string)""
IL_000f: ret
}
");
}
[WorkItem(543325, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543325")]
[Fact()]
public void EmitCastingMethodGroupToDelegate()
{
string source = @"
using System;
class Base
{
public virtual void F()
{
}
}
class Derived : Base
{
public override void F()
{
Action a = this.F;
a();
}
}";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("Derived.F",
@"{
// Code size 19 (0x13)
.maxstack 2
IL_0000: ldarg.0
IL_0001: dup
IL_0002: ldvirtftn ""void Base.F()""
IL_0008: newobj ""System.Action..ctor(object, System.IntPtr)""
IL_000d: callvirt ""void System.Action.Invoke()""
IL_0012: ret
}
");
}
[WorkItem(543325, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543325")]
[Fact()]
public void EmitCastingMethodGroupToDelegate_2()
{
string source = @"
using System;
class Base
{
public virtual void F()
{
}
}
class Derived : Base
{
public override void F()
{
Action a = new Action(this.F);
a();
}
}";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("Derived.F",
@"{
// Code size 19 (0x13)
.maxstack 2
IL_0000: ldarg.0
IL_0001: dup
IL_0002: ldvirtftn ""void Base.F()""
IL_0008: newobj ""System.Action..ctor(object, System.IntPtr)""
IL_000d: callvirt ""void System.Action.Invoke()""
IL_0012: ret
}
");
}
[WorkItem(543325, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543325")]
[Fact()]
public void EmitCastingMethodGroupToDelegate_3()
{
string source = @"
using System;
class Base
{
public virtual void F<T>()
{
}
}
class Derived : Base
{
public override void F<T>()
{
Action a = this.F<T>;
a();
a = new Action(this.F<T>);
a();
}
}";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("Derived.F<T>",
@"{
// Code size 37 (0x25)
.maxstack 2
IL_0000: ldarg.0
IL_0001: dup
IL_0002: ldvirtftn ""void Base.F<T>()""
IL_0008: newobj ""System.Action..ctor(object, System.IntPtr)""
IL_000d: callvirt ""void System.Action.Invoke()""
IL_0012: ldarg.0
IL_0013: dup
IL_0014: ldvirtftn ""void Base.F<T>()""
IL_001a: newobj ""System.Action..ctor(object, System.IntPtr)""
IL_001f: callvirt ""void System.Action.Invoke()""
IL_0024: ret
}
");
}
[Fact]
public void EmitObjectMethodOnSpecialByRefType()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
}
static void M(System.TypedReference r)
{
bool b = r.Equals(1);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"");
compilation.VerifyIL("Program.M",
@"{
// Code size 15 (0xf)
.maxstack 2
IL_0000: ldarga.s V_0
IL_0002: ldc.i4.1
IL_0003: box ""int""
IL_0008: call ""bool System.TypedReference.Equals(object)""
IL_000d: pop
IL_000e: ret
}
");
}
[Fact]
public void EmitCallToOverriddenToStringOnStruct()
{
string source = @"
using System;
class Program
{
public struct S1
{
public override string ToString()
{
return ""123"";
}
}
static void Main()
{
S1 s1 = new S1();
Console.Write(s1.ToString());
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"123");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 27 (0x1b)
.maxstack 1
.locals init (Program.S1 V_0) //s1
IL_0000: ldloca.s V_0
IL_0002: initobj ""Program.S1""
IL_0008: ldloca.s V_0
IL_000a: constrained. ""Program.S1""
IL_0010: callvirt ""string object.ToString()""
IL_0015: call ""void System.Console.Write(string)""
IL_001a: ret
}
");
}
[Fact]
public void EmitNonVirtualInstanceEnumMethodCallOnEnum()
{
string source = @"
using System;
class Program
{
enum Shade
{
White, Gray, Black
}
static void Main()
{
Shade v = Shade.Gray;
Console.WriteLine(v.GetType());
Console.WriteLine(v.HasFlag(Shade.Black));
Console.WriteLine(v.ToString(""G""));
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"Program+Shade
False
Gray");
compilation.VerifyIL("Program.Main",
@"{
// Code size 62 (0x3e)
.maxstack 2
.locals init (Program.Shade V_0) //v
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: box ""Program.Shade""
IL_0008: call ""System.Type object.GetType()""
IL_000d: call ""void System.Console.WriteLine(object)""
IL_0012: ldloc.0
IL_0013: box ""Program.Shade""
IL_0018: ldc.i4.2
IL_0019: box ""Program.Shade""
IL_001e: call ""bool System.Enum.HasFlag(System.Enum)""
IL_0023: call ""void System.Console.WriteLine(bool)""
IL_0028: ldloc.0
IL_0029: box ""Program.Shade""
IL_002e: ldstr ""G""
IL_0033: call ""string System.Enum.ToString(string)""
IL_0038: call ""void System.Console.WriteLine(string)""
IL_003d: ret
}
");
}
[Fact]
public void NestedLoopAndJumpStatements01()
{
string source = @"using System;
class Program
{
public class Test
{
public static short x; // = 9; NotImpl
public long Goo(sbyte y)
{
while (y < x*x)
{
do
{
if (x > y - 1)
{
if (x > y + 1)
{
x = (short)(x - 1);
}
x = (short)(x - 1);
continue;
}
else
{
if (x + 1 > y)
{
x = (short)(x - 2);
}
else
{
y = (sbyte)(y - 1);
}
}
} while (x > 3);
if (x < 3)
break;
}
return x;
}
}
static void Main()
{
Test.x = 9;
Console.Write(new Test().Goo(6));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2");
compilation.VerifyIL("Program.Test.Goo",
@"{
// Code size 118 (0x76)
.maxstack 3
IL_0000: br.s IL_0061
IL_0002: ldsfld ""short Program.Test.x""
IL_0007: ldarg.1
IL_0008: ldc.i4.1
IL_0009: sub
IL_000a: ble.s IL_0032
IL_000c: ldsfld ""short Program.Test.x""
IL_0011: ldarg.1
IL_0012: ldc.i4.1
IL_0013: add
IL_0014: ble.s IL_0023
IL_0016: ldsfld ""short Program.Test.x""
IL_001b: ldc.i4.1
IL_001c: sub
IL_001d: conv.i2
IL_001e: stsfld ""short Program.Test.x""
IL_0023: ldsfld ""short Program.Test.x""
IL_0028: ldc.i4.1
IL_0029: sub
IL_002a: conv.i2
IL_002b: stsfld ""short Program.Test.x""
IL_0030: br.s IL_0051
IL_0032: ldsfld ""short Program.Test.x""
IL_0037: ldc.i4.1
IL_0038: add
IL_0039: ldarg.1
IL_003a: ble.s IL_004b
IL_003c: ldsfld ""short Program.Test.x""
IL_0041: ldc.i4.2
IL_0042: sub
IL_0043: conv.i2
IL_0044: stsfld ""short Program.Test.x""
IL_0049: br.s IL_0051
IL_004b: ldarg.1
IL_004c: ldc.i4.1
IL_004d: sub
IL_004e: conv.i1
IL_004f: starg.s V_1
IL_0051: ldsfld ""short Program.Test.x""
IL_0056: ldc.i4.3
IL_0057: bgt.s IL_0002
IL_0059: ldsfld ""short Program.Test.x""
IL_005e: ldc.i4.3
IL_005f: blt.s IL_006f
IL_0061: ldarg.1
IL_0062: ldsfld ""short Program.Test.x""
IL_0067: ldsfld ""short Program.Test.x""
IL_006c: mul
IL_006d: blt.s IL_0002
IL_006f: ldsfld ""short Program.Test.x""
IL_0074: conv.i8
IL_0075: ret
}
");
}
[WorkItem(9229, "DevDiv_Projects/Roslyn")]
[Fact]
public void OverloadsInvoke()
{
string source = @"
using System;
class Program
{
public class C
{
public uint Goo(short p1, ushort p2) { return (ushort) (p1 + p2); }
public uint Goo(short p1, string p2) { return (uint) p1; }
public uint Goo(short p1, params ushort[] p2) { return (byte) (p2[0] + p2[1]); }
public uint Goo(short p1, ref ushort p2) { return p2; }
public uint Goo(out short p1, params ushort[] p2) { p1 = (sbyte)127; return (ushort)p1; }
public uint Goo(short p1, out string p2) { p2 = ""Abc123""; return (ushort) (p1 * 3); }
}
public static uint field1, field2;
internal static ushort field3;
private static string field4;
static void Main()
{
C obj = new C();
field1 = obj.Goo(-99, 100) + obj.Goo(2, ""QC""); // 1 + 2
field2 = obj.Goo(-1, 11, 22); // 33
Console.WriteLine(String.Format(""F1={0}, F2={1}"", field1, field2));
field3 = 444;
Console.WriteLine(obj.Goo(12345, ref field3)); // 444
short out1 = 0;
uint local = obj.Goo(out out1, 1,2,3,4); // 127
Console.WriteLine(local);
local = obj.Goo(2, out field4);
Console.WriteLine(local); // 6
Console.WriteLine(field4);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"), expectedOutput: @"
F1=3, F2=33
444
127
6
Abc123
");
compilation.VerifyIL("Program.Main",
@"{
// Code size 188 (0xbc)
.maxstack 6
.locals init (Program.C V_0, //obj
short V_1) //out1
IL_0000: newobj ""Program.C..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.s -99
IL_0009: ldc.i4.s 100
IL_000b: callvirt ""uint Program.C.Goo(short, ushort)""
IL_0010: ldloc.0
IL_0011: ldc.i4.2
IL_0012: ldstr ""QC""
IL_0017: callvirt ""uint Program.C.Goo(short, string)""
IL_001c: add
IL_001d: stsfld ""uint Program.field1""
IL_0022: ldloc.0
IL_0023: ldc.i4.m1
IL_0024: ldc.i4.2
IL_0025: newarr ""ushort""
IL_002a: dup
IL_002b: ldc.i4.0
IL_002c: ldc.i4.s 11
IL_002e: stelem.i2
IL_002f: dup
IL_0030: ldc.i4.1
IL_0031: ldc.i4.s 22
IL_0033: stelem.i2
IL_0034: callvirt ""uint Program.C.Goo(short, params ushort[])""
IL_0039: stsfld ""uint Program.field2""
IL_003e: ldstr ""F1={0}, F2={1}""
IL_0043: ldsfld ""uint Program.field1""
IL_0048: box ""uint""
IL_004d: ldsfld ""uint Program.field2""
IL_0052: box ""uint""
IL_0057: call ""string string.Format(string, object, object)""
IL_005c: call ""void System.Console.WriteLine(string)""
IL_0061: ldc.i4 0x1bc
IL_0066: stsfld ""ushort Program.field3""
IL_006b: ldloc.0
IL_006c: ldc.i4 0x3039
IL_0071: ldsflda ""ushort Program.field3""
IL_0076: callvirt ""uint Program.C.Goo(short, ref ushort)""
IL_007b: call ""void System.Console.WriteLine(uint)""
IL_0080: ldc.i4.0
IL_0081: stloc.1
IL_0082: ldloc.0
IL_0083: ldloca.s V_1
IL_0085: ldc.i4.4
IL_0086: newarr ""ushort""
IL_008b: dup
IL_008c: ldtoken ""long <PrivateImplementationDetails>.EA99F710D9D0B8BA192295C969A63ED7CE8FC5743DA20D2057FA2B6D2C404BFB""
IL_0091: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0096: callvirt ""uint Program.C.Goo(out short, params ushort[])""
IL_009b: call ""void System.Console.WriteLine(uint)""
IL_00a0: ldloc.0
IL_00a1: ldc.i4.2
IL_00a2: ldsflda ""string Program.field4""
IL_00a7: callvirt ""uint Program.C.Goo(short, out string)""
IL_00ac: call ""void System.Console.WriteLine(uint)""
IL_00b1: ldsfld ""string Program.field4""
IL_00b6: call ""void System.Console.WriteLine(string)""
IL_00bb: ret
}
");
}
[Fact]
public void ArrayLength()
{
string source = @"
class A
{
public static void Main()
{
int[] arr = new int[5];
System.Console.Write(arr.Length > 0);
if (0 < arr.Length)
{
System.Console.Write(arr.Length + 1);
}
if (arr.Length != 0)
{
System.Console.Write(arr.Length == 0);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "True6False");
compilation.VerifyIL("A.Main",
@"
{
// Code size 46 (0x2e)
.maxstack 2
.locals init (int[] V_0) //arr
IL_0000: ldc.i4.5
IL_0001: newarr ""int""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldlen
IL_0009: ldc.i4.0
IL_000a: cgt.un
IL_000c: call ""void System.Console.Write(bool)""
IL_0011: ldloc.0
IL_0012: ldlen
IL_0013: brfalse.s IL_001f
IL_0015: ldloc.0
IL_0016: ldlen
IL_0017: conv.i4
IL_0018: ldc.i4.1
IL_0019: add
IL_001a: call ""void System.Console.Write(int)""
IL_001f: ldloc.0
IL_0020: ldlen
IL_0021: brfalse.s IL_002d
IL_0023: ldloc.0
IL_0024: ldlen
IL_0025: ldc.i4.0
IL_0026: ceq
IL_0028: call ""void System.Console.Write(bool)""
IL_002d: ret
}");
}
[Fact]
public void ArrayLongLength()
{
string source = @"
class A
{
public static void Main()
{
int[] arr = new int[5];
System.Console.Write(arr.LongLength + 1);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "6");
compilation.VerifyIL("A.Main",
@"{
// Code size 17 (0x11)
.maxstack 2
IL_0000: ldc.i4.5
IL_0001: newarr ""int""
IL_0006: ldlen
IL_0007: conv.i8
IL_0008: ldc.i4.1
IL_0009: conv.i8
IL_000a: add
IL_000b: call ""void System.Console.Write(long)""
IL_0010: ret
}
");
}
[Fact]
public void AssignmentWithRef()
{
string source = @"
using System;
class C
{
public struct S
{
string field1;
long field2;
public void Goo(string s, ref long n, params long[] ary)
{
field1 = s; // field = param
Console.WriteLine(field1);
field2 = n; // field = ref param
Console.WriteLine(field2);
n = field2 + n; // ref p = field + ref p;
ulong local = 12345;
local = local + (ulong)Math.Abs(ary[0]); // local = ary element
Console.WriteLine(local);
ary[0] = (long)((long)local + ary[1]); // ary element = local
}
}
long n;
static void Main()
{
C obj = new C();
S valobj = new S();
obj.n = 9;
long[] ary = new long[3];
ary[0] = ary[1] = ary[2] = 123;
valobj.Goo(""Qc"", ref obj.n, ary);
Console.WriteLine(obj.n);
Console.WriteLine(ary[0]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
Qc
9
12468
18
12591
");
compilation.VerifyIL("C.S.Goo",
@"{
// Code size 81 (0x51)
.maxstack 5
.locals init (ulong V_0) //local
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld ""string C.S.field1""
IL_0007: ldarg.0
IL_0008: ldfld ""string C.S.field1""
IL_000d: call ""void System.Console.WriteLine(string)""
IL_0012: ldarg.0
IL_0013: ldarg.2
IL_0014: ldind.i8
IL_0015: stfld ""long C.S.field2""
IL_001a: ldarg.0
IL_001b: ldfld ""long C.S.field2""
IL_0020: call ""void System.Console.WriteLine(long)""
IL_0025: ldarg.2
IL_0026: ldarg.0
IL_0027: ldfld ""long C.S.field2""
IL_002c: ldarg.2
IL_002d: ldind.i8
IL_002e: add
IL_002f: stind.i8
IL_0030: ldc.i4 0x3039
IL_0035: conv.i8
IL_0036: stloc.0
IL_0037: ldloc.0
IL_0038: ldarg.3
IL_0039: ldc.i4.0
IL_003a: ldelem.i8
IL_003b: call ""long System.Math.Abs(long)""
IL_0040: add
IL_0041: stloc.0
IL_0042: ldloc.0
IL_0043: call ""void System.Console.WriteLine(ulong)""
IL_0048: ldarg.3
IL_0049: ldc.i4.0
IL_004a: ldloc.0
IL_004b: ldarg.3
IL_004c: ldc.i4.1
IL_004d: ldelem.i8
IL_004e: add
IL_004f: stelem.i8
IL_0050: ret
}
");
}
[WorkItem(538177, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538177")]
[Fact]
public void Bug3712()
{
string source = @"
class A
{
public static void Main()
{
int[] arr;
arr = new int[5] {1,2,3,4,5};
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.DebugExe.WithModuleName("MODULE"));
compilation.VerifyIL("A.Main",
@"{
// Code size 20 (0x14)
.maxstack 3
.locals init (int[] V_0) //arr
IL_0000: nop
IL_0001: ldc.i4.5
IL_0002: newarr ""int""
IL_0007: dup
IL_0008: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=20 <PrivateImplementationDetails>.4F6ADDC9659D6FB90FE94B6688A79F2A1FA8D36EC43F8F3E1D9B6528C448A384""
IL_000d: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0012: stloc.0
IL_0013: ret
}
");
}
[WorkItem(538052, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538052")]
[WorkItem(538224, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538224")]
[Fact]
public void NamespaceAndTypeAlias()
{
string source = @"
namespace N1
{
using N21;
namespace N21
{
public interface IGoo<T>
{
void M(T t, bool b);
}
public class C
{
}
}
namespace N22
{
public class C
{
public System.String Field = null;
}
public class Goo : IGoo<C>
{
public void M(C p, bool b)
{
System.Console.WriteLine(p.Field);
}
}
}
}
namespace N1.N2.N3.N4.N5.N6.N7.N8.N9.N10
{
}
namespace NS
{
using N1;
using N1.N21;
using C = N1.N22.C;
using Bob = N1.N2.N3.N4.N5.N6.N7.N8.N9.N10;
class Test
{
//hides namespace alias Bob
class Bob { }
static bool global = false;
static int Main()
{
C c = new C();
c.Field = ""Hello"";
global::N1.N21.IGoo<C> goo = new global::N1.N22.Goo();
goo.M(c, global);
return 0;
}
bool M(Bob p, bool b)
{
IGoo<long> goo = null;
if (p != null)
b = true;
return b == (goo == null);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "Hello");
compilation.VerifyIL("NS.Test.Main",
@"{
// Code size 35 (0x23)
.maxstack 3
.locals init (N1.N22.C V_0) //c
IL_0000: newobj ""N1.N22.C..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldstr ""Hello""
IL_000c: stfld ""string N1.N22.C.Field""
IL_0011: newobj ""N1.N22.Goo..ctor()""
IL_0016: ldloc.0
IL_0017: ldsfld ""bool NS.Test.global""
IL_001c: callvirt ""void N1.N21.IGoo<N1.N22.C>.M(N1.N22.C, bool)""
IL_0021: ldc.i4.0
IL_0022: ret
}
");
}
[Fact]
public void VolatileFieldAndNumericTypes()
{
string source = @"using System;
namespace CodeGen
{
public struct MyData
{
private volatile bool vField;
internal static volatile byte vsField;
public static void Main()
{
double cd = 1.234;
float f = (float)cd;
short[] ary = new short[3];
ary[0] = -123;
MyData obj = new MyData();
vsField = 0101;
byte p = MyData.vsField;
obj.vField = true;
uint ret = obj.M(ary, ref p, ref f, ref cd);
Console.Write(ret);
}
public uint M(short[] ary, ref byte p1, ref float p2, ref double p3)
{
if (vField)
{
if (ary[0] <= 0)
return (uint)-ary[0] + p1;
return 12345;
}
return 0;
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"224");
compilation.VerifyIL("CodeGen.MyData.M",
@"{
// Code size 32 (0x20)
.maxstack 2
IL_0000: ldarg.0
IL_0001: volatile.
IL_0003: ldfld ""bool CodeGen.MyData.vField""
IL_0008: brfalse.s IL_001e
IL_000a: ldarg.1
IL_000b: ldc.i4.0
IL_000c: ldelem.i2
IL_000d: ldc.i4.0
IL_000e: bgt.s IL_0018
IL_0010: ldarg.1
IL_0011: ldc.i4.0
IL_0012: ldelem.i2
IL_0013: neg
IL_0014: ldarg.2
IL_0015: ldind.u1
IL_0016: add
IL_0017: ret
IL_0018: ldc.i4 0x3039
IL_001d: ret
IL_001e: ldc.i4.0
IL_001f: ret
}
");
}
[Fact]
public void VolatileFieldAsRefAndEnumTypes()
{
string source = @"using System.Threading;
using System;
public enum E
{
Zero, One, Two
}
class Test
{
// ref type
public static volatile string V_2;
static void Thread2()
{
V_2 = ""One"";
}
volatile E V_3;
void Thread3(object p)
{
((Test)p).V_3 = E.Two;
}
static void Main()
{
var V_1 = new Test();
new Thread(new ThreadStart(Thread2)).Start();
new Thread(V_1.Thread3).Start(V_1);
for (; ;)
{
if (V_2 == ""One"" && V_1.V_3 == E.Two)
{
Console.WriteLine(""result={0},{1}"", V_2, V_1.V_3);
return;
}
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"result=One,Two");
// Why IL show
// ldfld "E Test.V_3"
// Instead of
// ldfld valuetype E modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) Test::V_3
compilation.VerifyIL("Test.Main",
@"{
// Code size 112 (0x70)
.maxstack 3
.locals init (Test V_0) //V_1
IL_0000: newobj ""Test..ctor()""
IL_0005: stloc.0
IL_0006: ldnull
IL_0007: ldftn ""void Test.Thread2()""
IL_000d: newobj ""System.Threading.ThreadStart..ctor(object, System.IntPtr)""
IL_0012: newobj ""System.Threading.Thread..ctor(System.Threading.ThreadStart)""
IL_0017: call ""void System.Threading.Thread.Start()""
IL_001c: ldloc.0
IL_001d: ldftn ""void Test.Thread3(object)""
IL_0023: newobj ""System.Threading.ParameterizedThreadStart..ctor(object, System.IntPtr)""
IL_0028: newobj ""System.Threading.Thread..ctor(System.Threading.ParameterizedThreadStart)""
IL_002d: ldloc.0
IL_002e: call ""void System.Threading.Thread.Start(object)""
IL_0033: volatile.
IL_0035: ldsfld ""string Test.V_2""
IL_003a: ldstr ""One""
IL_003f: call ""bool string.op_Equality(string, string)""
IL_0044: brfalse.s IL_0033
IL_0046: ldloc.0
IL_0047: volatile.
IL_0049: ldfld ""E Test.V_3""
IL_004e: ldc.i4.2
IL_004f: bne.un.s IL_0033
IL_0051: ldstr ""result={0},{1}""
IL_0056: volatile.
IL_0058: ldsfld ""string Test.V_2""
IL_005d: ldloc.0
IL_005e: volatile.
IL_0060: ldfld ""E Test.V_3""
IL_0065: box ""E""
IL_006a: call ""void System.Console.WriteLine(string, object, object)""
IL_006f: ret
}
");
}
[Fact]
public void ArithmeticOperations()
{
string source = @"using System;
namespace CodeGen
{
public class MyClass
{
public static ushort M(uint[] ary)
{
ulong local = 123456789;
while (ary[0] >= 0)
{
ary[0] = (uint)(ary[0] - 1);
ary[1] = (uint) ((int)(+ary[0]) % +999L);
local = (local / 7) % ary[1];
if (local < 9)
break;
}
return (ushort)local;
}
public static void Main()
{
uint[] ary = new uint[2];
ary[0] = ushort.MaxValue;
ary[1] = (uint)(ary[0] / 13L);
Console.Write(MyClass.M(ary));
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"6");
compilation.VerifyIL("CodeGen.MyClass.M",
@"{
// Code size 57 (0x39)
.maxstack 4
.locals init (ulong V_0) //local
IL_0000: ldc.i4 0x75bcd15
IL_0005: conv.i8
IL_0006: stloc.0
IL_0007: br.s IL_0030
IL_0009: ldarg.0
IL_000a: ldc.i4.0
IL_000b: ldarg.0
IL_000c: ldc.i4.0
IL_000d: ldelem.u4
IL_000e: ldc.i4.1
IL_000f: sub
IL_0010: stelem.i4
IL_0011: ldarg.0
IL_0012: ldc.i4.1
IL_0013: ldarg.0
IL_0014: ldc.i4.0
IL_0015: ldelem.u4
IL_0016: conv.i8
IL_0017: ldc.i4 0x3e7
IL_001c: conv.i8
IL_001d: rem
IL_001e: conv.u4
IL_001f: stelem.i4
IL_0020: ldloc.0
IL_0021: ldc.i4.7
IL_0022: conv.i8
IL_0023: div.un
IL_0024: ldarg.0
IL_0025: ldc.i4.1
IL_0026: ldelem.u4
IL_0027: conv.u8
IL_0028: rem.un
IL_0029: stloc.0
IL_002a: ldloc.0
IL_002b: ldc.i4.s 9
IL_002d: conv.i8
IL_002e: blt.un.s IL_0036
IL_0030: ldarg.0
IL_0031: ldc.i4.0
IL_0032: ldelem.u4
IL_0033: ldc.i4.0
IL_0034: bge.un.s IL_0009
IL_0036: ldloc.0
IL_0037: conv.u2
IL_0038: ret
}
");
}
[Fact]
public void Delegates()
{
string source = @"using System;
delegate void MyAction<T>(T x);
public class Program
{
static void F(long l)
{
Console.WriteLine(l);
}
void G(long l)
{
Console.WriteLine(l);
}
internal virtual void H(long l)
{
Console.WriteLine(l);
}
public static void Main(string[] args)
{
Program p = new Program();
MyAction<long> act1 = F;
act1(12);
MyAction<long> act2 = new MyAction<long>(p.G);
act2(13);
MyAction<long> act3 = p.H;
act3(14);
MyAction<long> act4 = new MyAction<long>(act3);
act4(15);
}
}
";
CompileAndVerify(source, expectedOutput: @"
12
13
14
15
");
}
[Fact]
public void DelegateMethodDelegates()
{
string source = @"
using System;
class C
{
Action invoke;
Func<AsyncCallback, object, IAsyncResult> beginInvoke;
Action<IAsyncResult> endInvoke;
Func<object[], object> dynamicInvoke;
Func<object> clone;
Func<object, bool> equals;
void M()
{
var a = new Action(M);
invoke = new Action(a.Invoke);
beginInvoke = new Func<AsyncCallback, object, IAsyncResult>(a.BeginInvoke);
endInvoke = new Action<IAsyncResult>(a.EndInvoke);
dynamicInvoke = new Func<object[], object>(a.DynamicInvoke);
clone = new Func<object>(a.Clone);
equals = new Func<object, bool>(a.Equals);
}
}
";
CompileAndVerify(source).VerifyIL("C.M", @"
{
// Code size 124 (0x7c)
.maxstack 3
.locals init (System.Action V_0) //a
IL_0000: ldarg.0
IL_0001: ldftn ""void C.M()""
IL_0007: newobj ""System.Action..ctor(object, System.IntPtr)""
IL_000c: stloc.0
IL_000d: ldarg.0
IL_000e: ldloc.0
IL_000f: ldftn ""void System.Action.Invoke()""
IL_0015: newobj ""System.Action..ctor(object, System.IntPtr)""
IL_001a: stfld ""System.Action C.invoke""
IL_001f: ldarg.0
IL_0020: ldloc.0
IL_0021: ldftn ""System.IAsyncResult System.Action.BeginInvoke(System.AsyncCallback, object)""
IL_0027: newobj ""System.Func<System.AsyncCallback, object, System.IAsyncResult>..ctor(object, System.IntPtr)""
IL_002c: stfld ""System.Func<System.AsyncCallback, object, System.IAsyncResult> C.beginInvoke""
IL_0031: ldarg.0
IL_0032: ldloc.0
IL_0033: ldftn ""void System.Action.EndInvoke(System.IAsyncResult)""
IL_0039: newobj ""System.Action<System.IAsyncResult>..ctor(object, System.IntPtr)""
IL_003e: stfld ""System.Action<System.IAsyncResult> C.endInvoke""
IL_0043: ldarg.0
IL_0044: ldloc.0
IL_0045: ldftn ""object System.Delegate.DynamicInvoke(params object[])""
IL_004b: newobj ""System.Func<object[], object>..ctor(object, System.IntPtr)""
IL_0050: stfld ""System.Func<object[], object> C.dynamicInvoke""
IL_0055: ldarg.0
IL_0056: ldloc.0
IL_0057: dup
IL_0058: ldvirtftn ""object System.Delegate.Clone()""
IL_005e: newobj ""System.Func<object>..ctor(object, System.IntPtr)""
IL_0063: stfld ""System.Func<object> C.clone""
IL_0068: ldarg.0
IL_0069: ldloc.0
IL_006a: dup
IL_006b: ldvirtftn ""bool object.Equals(object)""
IL_0071: newobj ""System.Func<object, bool>..ctor(object, System.IntPtr)""
IL_0076: stfld ""System.Func<object, bool> C.equals""
IL_007b: ret
}");
}
[Fact]
public void ConstantLiteralToDecimal()
{
string source = @"
using System;
using System.Globalization;
public class Program
{
public static void Main()
{
Print(0); // ldc.i4.0 - decimal..ctor(int32)
Print(1); // ldc.i4.1 - decimal..ctor(int32)
Print(8); // ldc.i4.8 - decimal..ctor(int32)
Print(-1); // ldc.i4.m1 - decimal..ctor(int32)
Print(-128);// ldc.i4.s - decimal..ctor(int32)
Print(2147483647); // ldc.i4 - decimal..ctor(int32)
Print(-2147483648); // ldc.i4 - decimal..ctor(int32)
Print(4294967295); // ldc.i4.m1 - decimal..ctor(uint32) [Note: Dev11 uses decimal..ctor(int64)]
Print(9223372036854775807); // ldc.i8 - decimal..ctor(int64)
Print(-9223372036854775808); // ldc.i8 - decimal..ctor(int64)
Print(18446744073709551615); // decimal..ctor(uint64) [Note: Dev11 uses decimal..ctor(int32, int32, int32, bool, byte)]
Print(-79228162514264337593543950335m); // decimal..ctor(int32, int32, int32, bool, byte)
Print((decimal)12345.679f); // ? ldc.r4 - decimal..ctor(Single)
}
public static void Print(decimal val)
{
Console.WriteLine(val.ToString(CultureInfo.InvariantCulture));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
0
1
8
-1
-128
2147483647
-2147483648
4294967295
9223372036854775807
-9223372036854775808
18446744073709551615
-79228162514264337593543950335
12345.68
");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 179 (0xb3)
.maxstack 5
IL_0000: ldsfld ""decimal decimal.Zero""
IL_0005: call ""void Program.Print(decimal)""
IL_000a: ldsfld ""decimal decimal.One""
IL_000f: call ""void Program.Print(decimal)""
IL_0014: ldc.i4.8
IL_0015: newobj ""decimal..ctor(int)""
IL_001a: call ""void Program.Print(decimal)""
IL_001f: ldsfld ""decimal decimal.MinusOne""
IL_0024: call ""void Program.Print(decimal)""
IL_0029: ldc.i4.s -128
IL_002b: newobj ""decimal..ctor(int)""
IL_0030: call ""void Program.Print(decimal)""
IL_0035: ldc.i4 0x7fffffff
IL_003a: newobj ""decimal..ctor(int)""
IL_003f: call ""void Program.Print(decimal)""
IL_0044: ldc.i4 0x80000000
IL_0049: newobj ""decimal..ctor(int)""
IL_004e: call ""void Program.Print(decimal)""
IL_0053: ldc.i4.m1
IL_0054: newobj ""decimal..ctor(uint)""
IL_0059: call ""void Program.Print(decimal)""
IL_005e: ldc.i8 0x7fffffffffffffff
IL_0067: newobj ""decimal..ctor(long)""
IL_006c: call ""void Program.Print(decimal)""
IL_0071: ldc.i8 0x8000000000000000
IL_007a: newobj ""decimal..ctor(long)""
IL_007f: call ""void Program.Print(decimal)""
IL_0084: ldc.i4.m1
IL_0085: conv.i8
IL_0086: newobj ""decimal..ctor(ulong)""
IL_008b: call ""void Program.Print(decimal)""
IL_0090: ldc.i4.m1
IL_0091: ldc.i4.m1
IL_0092: ldc.i4.m1
IL_0093: ldc.i4.1
IL_0094: ldc.i4.0
IL_0095: newobj ""decimal..ctor(int, int, int, bool, byte)""
IL_009a: call ""void Program.Print(decimal)""
IL_009f: ldc.i4 0x12d688
IL_00a4: ldc.i4.0
IL_00a5: ldc.i4.0
IL_00a6: ldc.i4.0
IL_00a7: ldc.i4.2
IL_00a8: newobj ""decimal..ctor(int, int, int, bool, byte)""
IL_00ad: call ""void Program.Print(decimal)""
IL_00b2: ret
}
");
}
[WorkItem(542417, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542417")]
[Fact]
public void OptionalForConstructor()
{
string source = @"using System;
class NamedExample
{
public NamedExample(int optional = 10)
{ }
static void Main(string[] args)
{
var temp = new NamedExample();
}
}
";
CompileAndVerify(source);
}
[Fact]
public void BranchReuse001()
{
string source = @"
using System;
class A
{
public static void Main()
{
int x = int.Parse(""42"");
if (x > 0)
{
string s = ""first"";
Console.WriteLine(s);
}
else
{
string s = ""second"";
Console.WriteLine(s);
}
Console.WriteLine(x);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"first
42");
compilation.VerifyIL("A.Main",
@"{
// Code size 42 (0x2a)
.maxstack 3
IL_0000: ldstr ""42""
IL_0005: call ""int int.Parse(string)""
IL_000a: dup
IL_000b: ldc.i4.0
IL_000c: ble.s IL_001a
IL_000e: ldstr ""first""
IL_0013: call ""void System.Console.WriteLine(string)""
IL_0018: br.s IL_0024
IL_001a: ldstr ""second""
IL_001f: call ""void System.Console.WriteLine(string)""
IL_0024: call ""void System.Console.WriteLine(int)""
IL_0029: ret
}
");
}
[Fact]
public void IncrementUsed()
{
string source = @"
using System;
class A
{
public static void Main()
{
int[] x = new int[3];
x[0] = 1;
x[1] = 2;
x[2] = 3;
int y = x[0]++;
Console.WriteLine(y);
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"1
2
2
3");
compilation.VerifyIL("A.Main",
@"{
// Code size 62 (0x3e)
.maxstack 4
.locals init (int V_0)
IL_0000: ldc.i4.3
IL_0001: newarr ""int""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.1
IL_0009: stelem.i4
IL_000a: dup
IL_000b: ldc.i4.1
IL_000c: ldc.i4.2
IL_000d: stelem.i4
IL_000e: dup
IL_000f: ldc.i4.2
IL_0010: ldc.i4.3
IL_0011: stelem.i4
IL_0012: dup
IL_0013: ldc.i4.0
IL_0014: ldelema ""int""
IL_0019: dup
IL_001a: ldind.i4
IL_001b: stloc.0
IL_001c: ldloc.0
IL_001d: ldc.i4.1
IL_001e: add
IL_001f: stind.i4
IL_0020: ldloc.0
IL_0021: call ""void System.Console.WriteLine(int)""
IL_0026: dup
IL_0027: ldc.i4.0
IL_0028: ldelem.i4
IL_0029: call ""void System.Console.WriteLine(int)""
IL_002e: dup
IL_002f: ldc.i4.1
IL_0030: ldelem.i4
IL_0031: call ""void System.Console.WriteLine(int)""
IL_0036: ldc.i4.2
IL_0037: ldelem.i4
IL_0038: call ""void System.Console.WriteLine(int)""
IL_003d: ret
}
");
}
[Fact]
public void IncrementUnused()
{
string source = @"
using System;
class A
{
public static void Main()
{
int[] x = new int[3];
x[0] = 1;
x[1] = 2;
x[2] = 3;
x[0]++;
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2
2
3");
compilation.VerifyIL("A.Main",
@"
{
// Code size 54 (0x36)
.maxstack 4
IL_0000: ldc.i4.3
IL_0001: newarr ""int""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.1
IL_0009: stelem.i4
IL_000a: dup
IL_000b: ldc.i4.1
IL_000c: ldc.i4.2
IL_000d: stelem.i4
IL_000e: dup
IL_000f: ldc.i4.2
IL_0010: ldc.i4.3
IL_0011: stelem.i4
IL_0012: dup
IL_0013: ldc.i4.0
IL_0014: ldelema ""int""
IL_0019: dup
IL_001a: ldind.i4
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stind.i4
IL_001e: dup
IL_001f: ldc.i4.0
IL_0020: ldelem.i4
IL_0021: call ""void System.Console.WriteLine(int)""
IL_0026: dup
IL_0027: ldc.i4.1
IL_0028: ldelem.i4
IL_0029: call ""void System.Console.WriteLine(int)""
IL_002e: ldc.i4.2
IL_002f: ldelem.i4
IL_0030: call ""void System.Console.WriteLine(int)""
IL_0035: ret
}
");
}
[Fact]
public void IncrementUnused1()
{
string source = @"
using System;
class A
{
private static int[] x = new int[3] {1, 2, 3};
public static void Main()
{
Increment();
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
private static void Increment()
{
x[0]++;
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2
2
3");
compilation.VerifyIL("A.Increment",
@"
{
// Code size 17 (0x11)
.maxstack 3
IL_0000: ldsfld ""int[] A.x""
IL_0005: ldc.i4.0
IL_0006: ldelema ""int""
IL_000b: dup
IL_000c: ldind.i4
IL_000d: ldc.i4.1
IL_000e: add
IL_000f: stind.i4
IL_0010: ret
}
");
}
[Fact]
public void IncrementUnused2()
{
string source = @"
using System;
class A
{
private static int[] x = new int[3] {1, 2, 3};
public static void Main()
{
Increment();
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
private static void Increment()
{
++x[0];
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2
2
3");
compilation.VerifyIL("A.Increment",
@"
{
// Code size 17 (0x11)
.maxstack 3
IL_0000: ldsfld ""int[] A.x""
IL_0005: ldc.i4.0
IL_0006: ldelema ""int""
IL_000b: dup
IL_000c: ldind.i4
IL_000d: ldc.i4.1
IL_000e: add
IL_000f: stind.i4
IL_0010: ret
}
");
}
[Fact]
public void IncrementNested()
{
string source = @"
using System;
class A
{
static int[] x = new int[] {1,2,3};
public static void Main()
{
x[x[x[0]++]++]++;
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2
3
4");
compilation.VerifyIL("A.Main",
@"
{
// Code size 89 (0x59)
.maxstack 5
.locals init (int V_0,
int V_1)
IL_0000: ldsfld ""int[] A.x""
IL_0005: ldsfld ""int[] A.x""
IL_000a: ldsfld ""int[] A.x""
IL_000f: ldc.i4.0
IL_0010: ldelema ""int""
IL_0015: dup
IL_0016: ldind.i4
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: ldc.i4.1
IL_001a: add
IL_001b: stind.i4
IL_001c: ldloc.1
IL_001d: ldelema ""int""
IL_0022: dup
IL_0023: ldind.i4
IL_0024: stloc.0
IL_0025: ldloc.0
IL_0026: ldc.i4.1
IL_0027: add
IL_0028: stind.i4
IL_0029: ldloc.0
IL_002a: ldelema ""int""
IL_002f: dup
IL_0030: ldind.i4
IL_0031: ldc.i4.1
IL_0032: add
IL_0033: stind.i4
IL_0034: ldsfld ""int[] A.x""
IL_0039: ldc.i4.0
IL_003a: ldelem.i4
IL_003b: call ""void System.Console.WriteLine(int)""
IL_0040: ldsfld ""int[] A.x""
IL_0045: ldc.i4.1
IL_0046: ldelem.i4
IL_0047: call ""void System.Console.WriteLine(int)""
IL_004c: ldsfld ""int[] A.x""
IL_0051: ldc.i4.2
IL_0052: ldelem.i4
IL_0053: call ""void System.Console.WriteLine(int)""
IL_0058: ret
}
");
}
[Fact]
public void PreIncrementUsed()
{
string source = @"
using System;
class A
{
public static void Main()
{
int[] x = new int[3];
x[0] = 1;
x[1] = 2;
x[2] = 3;
int y = ++x[0];
Console.WriteLine(y);
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2
2
2
3");
compilation.VerifyIL("A.Main",
@"{
// Code size 62 (0x3e)
.maxstack 4
.locals init (int V_0)
IL_0000: ldc.i4.3
IL_0001: newarr ""int""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.1
IL_0009: stelem.i4
IL_000a: dup
IL_000b: ldc.i4.1
IL_000c: ldc.i4.2
IL_000d: stelem.i4
IL_000e: dup
IL_000f: ldc.i4.2
IL_0010: ldc.i4.3
IL_0011: stelem.i4
IL_0012: dup
IL_0013: ldc.i4.0
IL_0014: ldelema ""int""
IL_0019: dup
IL_001a: ldind.i4
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stloc.0
IL_001e: ldloc.0
IL_001f: stind.i4
IL_0020: ldloc.0
IL_0021: call ""void System.Console.WriteLine(int)""
IL_0026: dup
IL_0027: ldc.i4.0
IL_0028: ldelem.i4
IL_0029: call ""void System.Console.WriteLine(int)""
IL_002e: dup
IL_002f: ldc.i4.1
IL_0030: ldelem.i4
IL_0031: call ""void System.Console.WriteLine(int)""
IL_0036: ldc.i4.2
IL_0037: ldelem.i4
IL_0038: call ""void System.Console.WriteLine(int)""
IL_003d: ret
}
");
}
[Fact]
public void PreIncrementUnused()
{
string source = @"
using System;
class A
{
public static void Main()
{
int[] x = new int[3];
x[0] = 1;
x[1] = 2;
x[2] = 3;
++x[0];
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"2
2
3");
compilation.VerifyIL("A.Main",
@"
{
// Code size 54 (0x36)
.maxstack 4
IL_0000: ldc.i4.3
IL_0001: newarr ""int""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.1
IL_0009: stelem.i4
IL_000a: dup
IL_000b: ldc.i4.1
IL_000c: ldc.i4.2
IL_000d: stelem.i4
IL_000e: dup
IL_000f: ldc.i4.2
IL_0010: ldc.i4.3
IL_0011: stelem.i4
IL_0012: dup
IL_0013: ldc.i4.0
IL_0014: ldelema ""int""
IL_0019: dup
IL_001a: ldind.i4
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stind.i4
IL_001e: dup
IL_001f: ldc.i4.0
IL_0020: ldelem.i4
IL_0021: call ""void System.Console.WriteLine(int)""
IL_0026: dup
IL_0027: ldc.i4.1
IL_0028: ldelem.i4
IL_0029: call ""void System.Console.WriteLine(int)""
IL_002e: ldc.i4.2
IL_002f: ldelem.i4
IL_0030: call ""void System.Console.WriteLine(int)""
IL_0035: ret
}
");
}
[Fact]
public void PreIncrementUnusedA()
{
string source = @"
using System;
class A
{
public static void Main()
{
int[] x = new int[3];
x[0] = 1;
x[1] = 2;
x[2] = 3;
++x[0];
Console.WriteLine(x[0]);
Console.WriteLine(x[1]);
Console.WriteLine(x[2]);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseDebugExe, expectedOutput: @"2
2
3");
compilation.VerifyIL("A.Main",
@"
{
// Code size 56 (0x38)
.maxstack 3
.locals init (int[] V_0) //x
IL_0000: ldc.i4.3
IL_0001: newarr ""int""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.0
IL_0009: ldc.i4.1
IL_000a: stelem.i4
IL_000b: ldloc.0
IL_000c: ldc.i4.1
IL_000d: ldc.i4.2
IL_000e: stelem.i4
IL_000f: ldloc.0
IL_0010: ldc.i4.2
IL_0011: ldc.i4.3
IL_0012: stelem.i4
IL_0013: ldloc.0
IL_0014: ldc.i4.0
IL_0015: ldelema ""int""
IL_001a: dup
IL_001b: ldind.i4
IL_001c: ldc.i4.1
IL_001d: add
IL_001e: stind.i4
IL_001f: ldloc.0
IL_0020: ldc.i4.0
IL_0021: ldelem.i4
IL_0022: call ""void System.Console.WriteLine(int)""
IL_0027: ldloc.0
IL_0028: ldc.i4.1
IL_0029: ldelem.i4
IL_002a: call ""void System.Console.WriteLine(int)""
IL_002f: ldloc.0
IL_0030: ldc.i4.2
IL_0031: ldelem.i4
IL_0032: call ""void System.Console.WriteLine(int)""
IL_0037: ret
}
");
}
[Fact]
public void PostIncrementUnusedStruct()
{
string source = @"
using System;
class A
{
static S1 x = new S1();
public static void Main()
{
x.y++;
Console.WriteLine(x.y);
}
}
struct S1
{
public int y;
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"1");
compilation.VerifyIL("A.Main",
@"
{
// Code size 31 (0x1f)
.maxstack 3
IL_0000: ldsflda ""S1 A.x""
IL_0005: ldflda ""int S1.y""
IL_000a: dup
IL_000b: ldind.i4
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: stind.i4
IL_000f: ldsflda ""S1 A.x""
IL_0014: ldfld ""int S1.y""
IL_0019: call ""void System.Console.WriteLine(int)""
IL_001e: ret
}
");
}
[Fact]
public void PostIncrementUnusedStruct1()
{
string source = @"
using System;
class A
{
public S1 x = new S1();
public static void Main()
{
var v = new A();
v.x.y+=42;
Console.WriteLine(v.x.y);
}
}
struct S1
{
public int y;
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42");
compilation.VerifyIL("A.Main",
@"
{
// Code size 38 (0x26)
.maxstack 4
IL_0000: newobj ""A..ctor()""
IL_0005: dup
IL_0006: ldflda ""S1 A.x""
IL_000b: ldflda ""int S1.y""
IL_0010: dup
IL_0011: ldind.i4
IL_0012: ldc.i4.s 42
IL_0014: add
IL_0015: stind.i4
IL_0016: ldflda ""S1 A.x""
IL_001b: ldfld ""int S1.y""
IL_0020: call ""void System.Console.WriteLine(int)""
IL_0025: ret
}
");
}
[Fact]
public void PostIncrementUnusedStruct1a()
{
string source = @"
using System;
class A
{
public S1 x = new S1();
public static void Main()
{
var v = new A();
v.x.y+=42;
Console.WriteLine(v.x.y);
}
}
struct S1
{
public int y;
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42", options: TestOptions.ReleaseDebugExe);
compilation.VerifyIL("A.Main",
@"
{
// Code size 40 (0x28)
.maxstack 3
.locals init (A V_0) //v
IL_0000: newobj ""A..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldflda ""S1 A.x""
IL_000c: ldflda ""int S1.y""
IL_0011: dup
IL_0012: ldind.i4
IL_0013: ldc.i4.s 42
IL_0015: add
IL_0016: stind.i4
IL_0017: ldloc.0
IL_0018: ldflda ""S1 A.x""
IL_001d: ldfld ""int S1.y""
IL_0022: call ""void System.Console.WriteLine(int)""
IL_0027: ret
}
");
}
[Fact]
public void PostIncrementUnusedStruct2()
{
string source = @"
using System;
class A
{
public static S1 sv = default(S1);
public static void Main()
{
var v = sv;
v.y += 42;
Console.WriteLine(v.y);
}
}
struct S1
{
public int y;
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42");
compilation.VerifyIL("A.Main",
@"
{
// Code size 31 (0x1f)
.maxstack 3
.locals init (S1 V_0) //v
IL_0000: ldsfld ""S1 A.sv""
IL_0005: stloc.0
IL_0006: ldloca.s V_0
IL_0008: ldflda ""int S1.y""
IL_000d: dup
IL_000e: ldind.i4
IL_000f: ldc.i4.s 42
IL_0011: add
IL_0012: stind.i4
IL_0013: ldloc.0
IL_0014: ldfld ""int S1.y""
IL_0019: call ""void System.Console.WriteLine(int)""
IL_001e: ret
}
");
}
[Fact, WorkItem(543618, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543618")]
public void ImplicitConversionCharToDecimal()
{
var source = @"
public class Test
{
static void Main()
{
char source = '\x1';
decimal dest = source;
}
}";
CompileAndVerify(source).
VerifyIL("Test.Main", @"
{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: call ""decimal decimal.op_Implicit(char)""
IL_0006: pop
IL_0007: ret
}");
}
[Fact, WorkItem(543618, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543618")]
public void ConversionDecimalToChar()
{
var source = @"
public class Test
{
static void Main()
{
decimal source = 1M;
char dest = (char)source;
}
}";
CompileAndVerify(source).
VerifyIL("Test.Main", @"
{
// Code size 12 (0xc)
.maxstack 1
IL_0000: ldsfld ""decimal decimal.One""
IL_0005: call ""char decimal.op_Explicit(decimal)""
IL_000a: pop
IL_000b: ret
}");
}
[WorkItem(543621, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543621")]
[Fact]
public void PartialMethodInvocationInIfStatement()
{
var source = @"
public static partial class Contract
{
public static void Assert(bool condition)
{
if (true)
ReportFailure();
}
static partial void ReportFailure();
}";
CompileAndVerify(source);
}
[Fact, WorkItem(529173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529173")]
public void CallWithStruct()
{
var source = @"
using System;
class Program
{
static void Main(string[] args)
{
M1(new S1());
M1(new S1(42));
var x = new S1(42);
M1(x);
var y = new S1(42);
M1(y);
y.Bar();
}
static void M1(S1 arg)
{
}
}
struct S1
{
public S1(int x)
{
this.x = x;
}
public int x;
public void Bar(){}
}
";
CompileAndVerify(source, expectedOutput: "").
VerifyIL("Program.Main", @"
{
// Code size 61 (0x3d)
.maxstack 2
.locals init (S1 V_0, //y
S1 V_1)
IL_0000: ldloca.s V_1
IL_0002: initobj ""S1""
IL_0008: ldloc.1
IL_0009: call ""void Program.M1(S1)""
IL_000e: ldc.i4.s 42
IL_0010: newobj ""S1..ctor(int)""
IL_0015: call ""void Program.M1(S1)""
IL_001a: ldc.i4.s 42
IL_001c: newobj ""S1..ctor(int)""
IL_0021: call ""void Program.M1(S1)""
IL_0026: ldloca.s V_0
IL_0028: ldc.i4.s 42
IL_002a: call ""S1..ctor(int)""
IL_002f: ldloc.0
IL_0030: call ""void Program.M1(S1)""
IL_0035: ldloca.s V_0
IL_0037: call ""void S1.Bar()""
IL_003c: ret
}");
}
[Fact, WorkItem(543611, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543611")]
public void CallOnConst()
{
var source = @"
using System;
class Test
{
static void Main()
{
Console.Write(decimal.One.CompareTo(decimal.Zero));
}
}
";
CompileAndVerify(source, expectedOutput: "1").
VerifyIL("Test.Main", @"
{
// Code size 24 (0x18)
.maxstack 2
.locals init (decimal V_0)
IL_0000: ldsfld ""decimal decimal.One""
IL_0005: stloc.0
IL_0006: ldloca.s V_0
IL_0008: ldsfld ""decimal decimal.Zero""
IL_000d: call ""int decimal.CompareTo(decimal)""
IL_0012: call ""void System.Console.Write(int)""
IL_0017: ret
}");
}
[Fact, WorkItem(543611, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543611")]
public void CallOnReadonlyValField()
{
var source = @"
using System;
class Test
{
struct C1
{
public decimal x;
}
static C1 Goo()
{
return new C1();
}
static void Main()
{
Console.Write(Goo().x.CompareTo(decimal.One));
}
}
";
CompileAndVerify(source, expectedOutput: "-1").
VerifyIL("Test.Main", @"
{
// Code size 29 (0x1d)
.maxstack 2
.locals init (Test.C1 V_0)
IL_0000: call ""Test.C1 Test.Goo()""
IL_0005: stloc.0
IL_0006: ldloca.s V_0
IL_0008: ldflda ""decimal Test.C1.x""
IL_000d: ldsfld ""decimal decimal.One""
IL_0012: call ""int decimal.CompareTo(decimal)""
IL_0017: call ""void System.Console.Write(int)""
IL_001c: ret
}");
}
[Fact(), WorkItem(543691, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543691")]
public void NullableAsArgsForTypeParameter()
{
CreateCompilationWithMscorlib40AndSystemCore(@"
using System;
class C
{
public delegate R RefFunc<A, R>(ref A a);
public static void Main()
{
int failcount = 0;
failcount += Equal(M((char?)null, (ref int x) => ""hi""), typeof(int), typeof(string)); //nullable lifted
}
public static Type[] M<T, U>(T? t, RefFunc<T, U> f) where T : struct
{
return new Type[] { typeof(T), typeof(U) };
}
public static int Equal(Type[] actual, params Type[] expected)
{
return 1;
}
}
").VerifyDiagnostics();
}
[Fact(), WorkItem(543693, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543693")]
public void Anonymous()
{
var source = @"
using System;
using System.Collections.Generic;
delegate T Func<A0, T>(A0 a0);
class Y<U>
{
public U u;
public Y(U u)
{
this.u = u;
}
public Y<T> Select<T>(Func<U, T> selector)
{
return new Y<T>(selector(u));
}
}
class P
{
static void Main()
{
var src = new Y<int>(2);
var q = from x in src
let y = x + 3
select new { X = x, Y = y };
if ((q.u.X != 2 || q.u.Y != 5))
{
}
}
}
";
CompileAndVerify(source);
}
#region Regression
[WorkItem(538224, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538224")]
[Fact]
public void CallMethodFromInterface01()
{
string source = @"
namespace NS
{
public interface IGoo
{
void M();
}
public struct Goo : IGoo
{
public void M()
{
System.Console.Write(""M() Called!"");
}
}
class Test
{
static void Main()
{
Goo goo = new Goo();
goo.M();
IGoo igoo = goo;
igoo.M();
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"M() Called!M() Called!");
compilation.VerifyIL("NS.Test.Main",
@"
{
// Code size 27 (0x1b)
.maxstack 1
.locals init (NS.Goo V_0) //goo
IL_0000: ldloca.s V_0
IL_0002: initobj ""NS.Goo""
IL_0008: ldloca.s V_0
IL_000a: call ""void NS.Goo.M()""
IL_000f: ldloc.0
IL_0010: box ""NS.Goo""
IL_0015: callvirt ""void NS.IGoo.M()""
IL_001a: ret
}");
}
[WorkItem(538224, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538224")]
[Fact]
public void CallMethodFromGenInterface01()
{
string source = @"
namespace NS
{
public interface IGoo<T>
{
void M(T t);
}
public class Goo : IGoo<int>
{
public void M(int n)
{
System.Console.WriteLine(n);
}
}
class Test
{
static void Main()
{
IGoo<int> goo = new Goo();
goo.M(123);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"123");
compilation.VerifyIL("NS.Test.Main",
@"{
// Code size 13 (0xd)
.maxstack 2
IL_0000: newobj ""NS.Goo..ctor()""
IL_0005: ldc.i4.s 123
IL_0007: callvirt ""void NS.IGoo<int>.M(int)""
IL_000c: ret
}
");
}
[WorkItem(538226, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538226")]
[Fact]
public void JumpWithFloatOperand()
{
string source = @"using System;
namespace CodeGen
{
public class MyData
{
public static void Main()
{
bool[] a1 = new bool[2];
a1[0] = false;
a1[1] = true;
byte[] a2 = new byte[3];
a2[0] = a2[1] = a2[2] = 11;
float[] a3 = new float[1];
a3[0] = 0.1249f;
double[] a4 = new double[2];
a4[0] = a4[1] = a3[0];
MyData obj = new MyData();
ulong ret = obj.M(a1, a2, a3, a4);
Console.Write(ret);
}
public ulong M(bool[] a1, byte[] a2, float[] a3, double[] a4)
{
if (a1[0])
{
if (99 <= a2[0])
{
a2[1] = (byte)((a2[0] + (a2[1] + a2[2])) % byte.MaxValue);
return (ulong) (a2[1] + a2[2]);
}
}
else if (a1[1])
{
if (a3[0] >= 0)
{
a3[0] = a3[0] * 100;
return (ulong) a3[0];
}
}
else
{
if (a4[0] <= 1)
{
a4[1] = a4[0] + +100;
return 123ul;
}
}
return 0UL;
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"12");
compilation.VerifyIL("CodeGen.MyData.M",
@"
{
// Code size 114 (0x72)
.maxstack 6
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: ldelem.u1
IL_0003: brfalse.s IL_002a
IL_0005: ldc.i4.s 99
IL_0007: ldarg.2
IL_0008: ldc.i4.0
IL_0009: ldelem.u1
IL_000a: bgt.s IL_006f
IL_000c: ldarg.2
IL_000d: ldc.i4.1
IL_000e: ldarg.2
IL_000f: ldc.i4.0
IL_0010: ldelem.u1
IL_0011: ldarg.2
IL_0012: ldc.i4.1
IL_0013: ldelem.u1
IL_0014: ldarg.2
IL_0015: ldc.i4.2
IL_0016: ldelem.u1
IL_0017: add
IL_0018: add
IL_0019: ldc.i4 0xff
IL_001e: rem
IL_001f: conv.u1
IL_0020: stelem.i1
IL_0021: ldarg.2
IL_0022: ldc.i4.1
IL_0023: ldelem.u1
IL_0024: ldarg.2
IL_0025: ldc.i4.2
IL_0026: ldelem.u1
IL_0027: add
IL_0028: conv.i8
IL_0029: ret
IL_002a: ldarg.1
IL_002b: ldc.i4.1
IL_002c: ldelem.u1
IL_002d: brfalse.s IL_004a
IL_002f: ldarg.3
IL_0030: ldc.i4.0
IL_0031: ldelem.r4
IL_0032: ldc.r4 0
IL_0037: blt.un.s IL_006f
IL_0039: ldarg.3
IL_003a: ldc.i4.0
IL_003b: ldarg.3
IL_003c: ldc.i4.0
IL_003d: ldelem.r4
IL_003e: ldc.r4 100
IL_0043: mul
IL_0044: stelem.r4
IL_0045: ldarg.3
IL_0046: ldc.i4.0
IL_0047: ldelem.r4
IL_0048: conv.u8
IL_0049: ret
IL_004a: ldarg.s V_4
IL_004c: ldc.i4.0
IL_004d: ldelem.r8
IL_004e: ldc.r8 1
IL_0057: bgt.un.s IL_006f
IL_0059: ldarg.s V_4
IL_005b: ldc.i4.1
IL_005c: ldarg.s V_4
IL_005e: ldc.i4.0
IL_005f: ldelem.r8
IL_0060: ldc.r8 100
IL_0069: add
IL_006a: stelem.r8
IL_006b: ldc.i4.s 123
IL_006d: conv.i8
IL_006e: ret
IL_006f: ldc.i4.0
IL_0070: conv.i8
IL_0071: ret
}
");
}
[WorkItem(538245, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538245")]
[Fact]
public void CallParamsCtor()
{
string source = @"
class MyClass
{
int intTest;
public MyClass(params int[] values)
{
intTest = values[0] + values[1] + values[2];
}
public static int Main()
{
int intI = 1;
int intJ = 2;
int intK = 3;
MyClass mc = new MyClass(intI, intJ, intK);
System.Console.Write(mc.intTest);
if (mc.intTest == 6)
{
return 0;
}
else
{
return 1;
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"6");
// Dev10
compilation.VerifyIL("MyClass.Main",
@"{
// Code size 52 (0x34)
.maxstack 4
.locals init (int V_0, //intI
int V_1, //intJ
int V_2) //intK
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldc.i4.2
IL_0003: stloc.1
IL_0004: ldc.i4.3
IL_0005: stloc.2
IL_0006: ldc.i4.3
IL_0007: newarr ""int""
IL_000c: dup
IL_000d: ldc.i4.0
IL_000e: ldloc.0
IL_000f: stelem.i4
IL_0010: dup
IL_0011: ldc.i4.1
IL_0012: ldloc.1
IL_0013: stelem.i4
IL_0014: dup
IL_0015: ldc.i4.2
IL_0016: ldloc.2
IL_0017: stelem.i4
IL_0018: newobj ""MyClass..ctor(params int[])""
IL_001d: dup
IL_001e: ldfld ""int MyClass.intTest""
IL_0023: call ""void System.Console.Write(int)""
IL_0028: ldfld ""int MyClass.intTest""
IL_002d: ldc.i4.6
IL_002e: bne.un.s IL_0032
IL_0030: ldc.i4.0
IL_0031: ret
IL_0032: ldc.i4.1
IL_0033: ret
}
");
}
[Fact]
[WorkItem(33564, "https://github.com/dotnet/roslyn/issues/33564")]
[WorkItem(538246, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538246"), WorkItem(543655, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543655")]
public void FloatDoubleInfinity()
{
string source = @"
using System;
public class MyClass
{
public static int Main()
{
double d1 = double.MaxValue;
double d2 = double.PositiveInfinity;
double d3 = double.NegativeInfinity;
int ret = 0;
if ((double)(d1 + (d1 * 1.0e-15f)) != d2)
{
ret = 1;
}
if ((double)(d1 - (-d1 * 1.0e-15f)) != d2)
{
ret = ret + 10;
}
if ((double)(d1 * (1.0f + 1.0e-15f)) != d1) // note (1.0f + 1.0e-15f) == 1.0f
{
ret = ret + 100;
}
if ((double)(d1 / (1.0f - 1.0e-15f)) != d1) // note (1.0f - 1.0e-15f) == 1.0f
{
ret = ret + 1000;
}
if ((double)(-d1 + (-(d1 * 1.0e-15f))) != d3)
{
ret = ret + 10000;
}
if ((double)((-d1 - (d1 * 1.0e-15f))) != d3)
{
ret = ret + 100000;
}
if ((double)(-d1 * (1.0f + 1.0e-15f)) != -d1) // note (1.0f + 1.0e-15f) == 1.0f
{
ret = ret + 1000000;
}
if ((double)(-d1 / (1.0f - 1.0e-15f)) != -d1) // note (1.0f - 1.0e-15f) == 1.0f
{
ret = ret + 10000000;
}
Console.WriteLine(ret);
return ret;
}
}";
var compilation = CompileAndVerify(source, expectedOutput: "0").
VerifyIL("MyClass.Main", @"
{
// Code size 228 (0xe4)
.maxstack 3
.locals init (double V_0, //d1
double V_1, //d2
double V_2, //d3
int V_3) //ret
IL_0000: ldc.r8 1.79769313486232E+308
IL_0009: stloc.0
IL_000a: ldc.r8 Infinity
IL_0013: stloc.1
IL_0014: ldc.r8 -Infinity
IL_001d: stloc.2
IL_001e: ldc.i4.0
IL_001f: stloc.3
IL_0020: ldloc.0
IL_0021: ldloc.0
IL_0022: ldc.r8 1.00000000362749E-15
IL_002b: mul
IL_002c: add
IL_002d: conv.r8
IL_002e: ldloc.1
IL_002f: beq.s IL_0033
IL_0031: ldc.i4.1
IL_0032: stloc.3
IL_0033: ldloc.0
IL_0034: ldloc.0
IL_0035: neg
IL_0036: ldc.r8 1.00000000362749E-15
IL_003f: mul
IL_0040: sub
IL_0041: conv.r8
IL_0042: ldloc.1
IL_0043: beq.s IL_004a
IL_0045: ldloc.3
IL_0046: ldc.i4.s 10
IL_0048: add
IL_0049: stloc.3
IL_004a: ldloc.0
IL_004b: ldc.r8 1
IL_0054: mul
IL_0055: conv.r8
IL_0056: ldloc.0
IL_0057: beq.s IL_005e
IL_0059: ldloc.3
IL_005a: ldc.i4.s 100
IL_005c: add
IL_005d: stloc.3
IL_005e: ldloc.0
IL_005f: ldc.r8 1
IL_0068: div
IL_0069: conv.r8
IL_006a: ldloc.0
IL_006b: beq.s IL_0075
IL_006d: ldloc.3
IL_006e: ldc.i4 0x3e8
IL_0073: add
IL_0074: stloc.3
IL_0075: ldloc.0
IL_0076: neg
IL_0077: ldloc.0
IL_0078: ldc.r8 1.00000000362749E-15
IL_0081: mul
IL_0082: neg
IL_0083: add
IL_0084: conv.r8
IL_0085: ldloc.2
IL_0086: beq.s IL_0090
IL_0088: ldloc.3
IL_0089: ldc.i4 0x2710
IL_008e: add
IL_008f: stloc.3
IL_0090: ldloc.0
IL_0091: neg
IL_0092: ldloc.0
IL_0093: ldc.r8 1.00000000362749E-15
IL_009c: mul
IL_009d: sub
IL_009e: conv.r8
IL_009f: ldloc.2
IL_00a0: beq.s IL_00aa
IL_00a2: ldloc.3
IL_00a3: ldc.i4 0x186a0
IL_00a8: add
IL_00a9: stloc.3
IL_00aa: ldloc.0
IL_00ab: neg
IL_00ac: ldc.r8 1
IL_00b5: mul
IL_00b6: conv.r8
IL_00b7: ldloc.0
IL_00b8: neg
IL_00b9: beq.s IL_00c3
IL_00bb: ldloc.3
IL_00bc: ldc.i4 0xf4240
IL_00c1: add
IL_00c2: stloc.3
IL_00c3: ldloc.0
IL_00c4: neg
IL_00c5: ldc.r8 1
IL_00ce: div
IL_00cf: conv.r8
IL_00d0: ldloc.0
IL_00d1: neg
IL_00d2: beq.s IL_00dc
IL_00d4: ldloc.3
IL_00d5: ldc.i4 0x989680
IL_00da: add
IL_00db: stloc.3
IL_00dc: ldloc.3
IL_00dd: call ""void System.Console.WriteLine(int)""
IL_00e2: ldloc.3
IL_00e3: ret
}");
}
[WorkItem(538839, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538839")]
[Fact]
public void LocalNumericConstInitWithDifferentType()
{
string source = @"
using System;
class Program
{
static void Main()
{
const long const1 = 1;
Console.WriteLine(const1);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"1");
// Dev10
compilation.VerifyIL("Program.Main",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: conv.i8
IL_0002: call ""void System.Console.WriteLine(long)""
IL_0007: ret
}");
}
[WorkItem(539425, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539425")]
[Fact]
public void ConstantLiftedEquality()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
const bool b = 1 == null;
Console.Write(b);
}
}";
//see Binder.TryFoldingNullableEquality for info on how/why this works
var comp = CompileAndVerify(source, expectedOutput: @"False");
comp.VerifyIL("Program.Main",
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldc.i4.0
IL_0001: call ""void System.Console.Write(bool)""
IL_0006: ret
}");
}
[Fact]
public void VariantInterfaceTypeParameters()
{
string source = @"
interface I<in TIn, out TOut> { }
class A { }
class B : A { }
class Program
{
static void Main(string[] args)
{
I<A, A> aa1 = null;
I<A, B> ab1 = null;
I<B, A> ba1 = null;
I<B, B> bb1 = null;
I<A, A> aa2 = null;
I<A, B> ab2 = null;
I<B, A> ba2 = null;
I<B, B> bb2 = null;
aa1 = aa2;
aa1 = ab2;
// aa1 = ba2; //invalid
// aa1 = bb2; //invalid
// ab1 = aa2; //invalid
ab1 = ab2;
// ab1 = ba2; //invalid
// ab1 = bb2; //invalid
ba1 = aa2;
ba1 = ab2;
ba1 = ba2;
ba1 = bb2;
// bb1 = aa2; //invalid
bb1 = ab2;
// bb1 = ba2; //invalid
bb1 = bb2;
}
}";
CompileAndVerify(source, expectedOutput: string.Empty);
}
[Fact]
public void VariantDelegateTypeParameters()
{
string source = @"
delegate TOut D<in TIn, out TOut>(TIn p);
class A { }
class B : A { }
class Program
{
static void Main(string[] args)
{
D<A, A> aa1 = null;
D<A, B> ab1 = null;
D<B, A> ba1 = null;
D<B, B> bb1 = null;
D<A, A> aa2 = null;
D<A, B> ab2 = null;
D<B, A> ba2 = null;
D<B, B> bb2 = null;
aa1 = aa2;
aa1 = ab2;
// aa1 = ba2; //invalid
// aa1 = bb2; //invalid
// ab1 = aa2; //invalid
ab1 = ab2;
// ab1 = ba2; //invalid
// ab1 = bb2; //invalid
ba1 = aa2;
ba1 = ab2;
ba1 = ba2;
ba1 = bb2;
// bb1 = aa2; //invalid
bb1 = ab2;
// bb1 = ba2; //invalid
bb1 = bb2;
}
}";
CompileAndVerify(source, expectedOutput: string.Empty);
}
[WorkItem(540093, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540093")]
[Fact]
public void UsingReferenceTypeConstField()
{
string source = @"
using System;
class MyClass { }
class MyMainClass
{
public const MyClass mc = null;
public static int Main()
{
int retval = 1;
if (null == mc)
retval = 0;
Console.WriteLine(retval);
return retval;
}
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(528060, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528060")]
[WorkItem(1043494, "DevDiv")]
[Fact]
public void DoubleDivByNegativeZero()
{
string source = @"
class MyClass
{
public static int Main()
{
int ret = 0;
double d1 = 2.0;
double d2 = -0.0;
double d3 = d1 / d2;
if (d3 == double.NegativeInfinity)
{
}
else
{
ret = ret + 1;
}
d1 = -2.0;
d3 = d1 / d2;
if (d3 != double.PositiveInfinity)
{
ret = ret + 1;
}
d1 = double.PositiveInfinity;
d3 = d1 / d2;
if (d3 != double.NegativeInfinity)
{
ret = ret + 1;
}
d1 = double.NegativeInfinity;
d3 = d1 / d2;
if (d3 != double.PositiveInfinity)
{
ret = ret + 1;
}
System.Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(540096, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540096")]
[WorkItem(540878, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540878")]
[Fact]
public void MissingOutFlagForParameter()
{
string source = @"
using System;
using System.Threading;
delegate T GenDelegate<T>(T p1, out T p2);
interface IGoo { U Function<U>(U i, out U j); }
class Goo : IGoo { public U Function<U>(U i, out U j) { j = i; return i; }}
class Test {
public static int Main()
{
int i, j;
IGoo inst = new Goo();
GenDelegate<int> MyDelegate = new GenDelegate<int>(inst.Function<int>);
i = MyDelegate(10, out j);
if ((i != 10) || (j != 10))
{
Console.WriteLine(1);
return 1;
}
Console.WriteLine(0);
return 0;
}
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(540097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540097")]
[Fact]
public void CallBaseMethodExplicitlyWithCall()
{
string source = @"
using System;
namespace Microsoft.Conformance.Expressions
{
public class BaseClass
{
public virtual int intI() { return 1; }
}
public class base007 : BaseClass
{
override public int intI() { return 2; }
public int TestInt()
{
return base.intI();
}
public static int Main()
{
base007 TC = new base007();
if (TC.TestInt() == 1)
{
Console.WriteLine(0);
return 0;
}
else
{
Console.WriteLine(1);
return 1;
}
}
}
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(540149, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540149")]
[Fact]
public void LHSParenthesizedProperty()
{
string source = @"
using System;
namespace Microsoft.Conformance.ParenthesizedExpression
{
class A
{
public int p;
public int P { set { p = value; } }
static int Main(string[] args)
{
A a = new A();
B b = new B();
(a.P) = 0; //devdiv bug 168519.
(b.a.P) = 0; //devdiv bug 168519.
int ret = (a.p + b.a.p);
Console.WriteLine(ret);
return (ret);
}
}
class B { public A a = new A(); }
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(540158, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540158")]
[Fact]
public void LoadMaxConstantForToString()
{
string source = @"
using System;
public class MyClass
{
public static int Main()
{
int RetVal = 0;
int i = int.MaxValue;
string s = i.ToString();
if (!s.Equals(Int32.MaxValue.ToString()))
{
RetVal = 1;
}
Console.WriteLine(RetVal);
return RetVal;
}
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(540252, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540252")]
[Fact]
public void OverloadResolutionWithConsoleWriteLineMethodGroup()
{
var source =
@"
using System;
class Program
{
static void Main()
{
Goo(Console.WriteLine);
}
static void Goo(Action<string> a) { a(""Hello""); }
static void Goo(Action<string, string, string, string, string> a) { }
}
";
CompileAndVerify(source, expectedOutput: "Hello");
}
[WorkItem(540331, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540331")]
[Fact]
public void StringComparisonOpEquality()
{
string source = @"using System;
class Test
{
static void Main()
{
string s = ""A"" + ""B"";
if (s == ""AB"")
{
Console.Write(""Pass01|"");
}
else
{
Console.Write(""Fail01|"");
}
s = ""A"";
string s2 = s + ""B"";
if (s2 == ""AB"")
{
Console.Write(""Pass02|"");
}
else
{
Console.Write(""Fail02|"");
}
string s3 = s + ""b"";
if (s3 != ""AB"")
{
Console.Write(""Pass03"");
}
else
{
Console.Write(""Fail03"");
}
}
}
";
string expectedOutput = @"Pass01|Pass02|Pass03";
CompileAndVerify(source, expectedOutput: expectedOutput);
}
[WorkItem(528183, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528183")]
[Fact]
public void TestExternWithoutDLLImport()
{
string source = @"
class Test
{
extern void Goo();
static void Main()
{
(new Test()).Goo();
}
}";
var comp = CreateCompilation(source, options: TestOptions.ReleaseDll);
// Both Dev10 and Roslyn currently generate unverifiable code for this case...
// Dev10 reports warning CS0626: Method, operator, or accessor 'Test.Goo()' is marked external
// and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
comp.VerifyDiagnostics(
// (4,17): warning CS0626: Method, operator, or accessor 'Test.Goo()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "Goo").WithArguments("Test.Goo()"));
// NOTE: the resulting IL is unverifiable, but not an error for compat reasons
CompileAndVerify(comp, verify: Verification.FailsPEVerify).VerifyIL("Test.Main",
@"
{
// Code size 11 (0xb)
.maxstack 1
IL_0000: newobj ""Test..ctor()""
IL_0005: call ""void Test.Goo()""
IL_000a: ret
}
");
}
[WorkItem(541790, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541790")]
[Fact]
public void TestLINQQueryableAnyExtensionMethod()
{
var source = @"
using System;
using System.Linq;
public class Test
{
public static void Main(string[] args)
{
var collection = new int[] { 1, 2, 3 };
var queryable = collection.AsQueryable();
if (collection.AsQueryable().Any((a) => a != 0))
{
Console.WriteLine(""Success"");
}
}
}";
CompileAndVerifyWithMscorlib40(
source,
references: new[] { SystemCoreRef },
expectedOutput: @"Success");
}
[WorkItem(528651, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528651")]
[Fact]
public void UserDefinedObject()
{
string source = @"
namespace System
{
public class Object
{
}
public class Void
{
}
}
class Test
{
static void Main()
{
}
}
";
CreateEmptyCompilation(source, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute()).VerifyEmitDiagnostics(
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion));
}
[WorkItem(542631, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542631")]
[Fact]
public void Queryable()
{
var source =
@"using System.Linq;
class C
{
static void Main(string[] args)
{
IQueryable<int> q1 = null;
var q = q1.Select(x => x);
}
}
";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics();
}
[WorkItem(542267, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542267")]
[Fact]
public void PartialMethod()
{
var source =
@"partial class C
{
partial void M1();
partial void M1() { }
partial void M2();
}";
CompileAndVerify(source);
}
[WorkItem(542275, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542275")]
[Fact]
public void CallUnimplementedPartialMethod()
{
var source =
@"partial class C
{
partial void M1();
partial void M1() { }
partial void M2();
void M()
{
M1();
M2();
}
}";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M",
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""void C.M1()""
IL_0006: ret
}");
}
[WorkItem(542297, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542297")]
[Fact]
public void GenericClassNameIdenticalToAliasSimpleName()
{
string source = @"using System;
using basic068Inner = basic068One.basic068Three;
public class Test
{
public static void Main()
{
Console.Write(basic068Inner.basic068ThreeClass.F1);
}
}
public class basic068Inner<A>
{
public class basic068ThreeClass
{
public static int F1 = 1;
}
}
namespace basic068One.basic068Three
{
public class basic068ThreeClass
{
public static int F1 = 0;
}
}
";
CompileAndVerify(source, expectedOutput: "0");
}
[WorkItem(542489, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542489")]
[Fact]
public void PartialMethodOnlyHasDeclareButNotImplement()
{
string source = @"using System;
partial class program
{
static void Main(string[] args)
{
goo(name: string.Empty, age: 1, gender: 1 > 2);
}
}
partial class program
{
static partial void goo(string name, int age, bool gender);
}
";
CompileAndVerify(source);
}
[WorkItem(538544, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538544")]
[Fact]
public void DecimalLiteral01()
{
string source = @"using System;
using System.Globalization;
public class MyClass {
public static void Main()
{
Console.WriteLine((0E-10M).ToString(CultureInfo.InvariantCulture));
Console.WriteLine((1E-30M).ToString(CultureInfo.InvariantCulture));
Console.WriteLine((10E-1M).ToString(CultureInfo.InvariantCulture));
}
}
";
CompileAndVerify(source, expectedOutput: @"
0.0000000000
0.0000000000000000000000000000
1.0
");
}
[WorkItem(543897, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543897")]
[Fact]
public void DecimalLiteral02()
{
string source = @"using System;
using System.Globalization;
using System.Threading;
public class MyClass {
public static void Main()
{
System.Globalization.CultureInfo saveCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
try
{
decimal d = 1.00m;
Console.WriteLine((d).ToString());
}
finally
{
System.Threading.Thread.CurrentThread.CurrentCulture = saveCulture;
}
}
}
";
CompileAndVerify(source, expectedOutput: "1.00");
}
// Breaking change: native compiler considers
// digits < 1e-49 when rounding.
[WorkItem(529827, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529827")]
[WorkItem(568494, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/568494")]
[WorkItem(32576, "https://github.com/dotnet/roslyn/issues/32576")]
[WorkItem(375, "https://github.com/dotnet/roslyn/issues/375")]
[Fact] // https://github.com/dotnet/coreclr/issues/22046
public void DecimalLiteral_BreakingChange()
{
string source =
@"using System;
using System.Globalization;
class C
{
static void Main()
{
WriteLine(3.0500000000000000000001e-27m); // 3.05e-27m + 1e-49m [Dev11/Roslyn rounds]
WriteLine(3.05000000000000000000001e-27m); // 3.05e-27m + 1e-50m [Dev11 rounds, Roslyn does not]
WriteLine();
WriteLine(5.00000000000000000001e-29m); // 5.0e-29m + 1e-49m [Dev11/Roslyn rounds]
WriteLine(5.0000000000000000000000000000001e-29m); // 5.0e-29m + 1e-60m [Dev11 rounds, Roslyn does not]
WriteLine();
WriteLine(-5.00000000000000000001e-29m); // -5.0e-29m + 1e-49m [Dev11/Roslyn rounds]
WriteLine(-5.0000000000000000000000000000001e-29m); // -5.0e-29m + 1e-60m [Dev11 rounds, Roslyn does not]
WriteLine();
// 10 20 30 40 50
WriteLine(.10000000000000000000000000005000000000000000000001m); // [Dev11 chops at 50 digits and rounds, Roslyn does not round]
WriteLine(.100000000000000000000000000050000000000000000000001m); // [Dev11 chops at 50 digits and does not round, Roslyn does not round]
}
static void WriteLine() => Console.WriteLine();
static void WriteLine(decimal d) => Console.WriteLine(d.ToString(CultureInfo.InvariantCulture));
}";
if (ExecutionConditionUtil.IsCoreClr)
{
var compilation = CompileAndVerify(source, expectedOutput:
@"0.0000000000000000000000000031
0.0000000000000000000000000031
0.0000000000000000000000000001
0.0000000000000000000000000001
-0.0000000000000000000000000001
-0.0000000000000000000000000001
0.1000000000000000000000000001
0.1000000000000000000000000001");
}
else if (ExecutionConditionUtil.IsDesktop)
{
var compilation = CompileAndVerify(source, expectedOutput:
@"0.0000000000000000000000000031
0.0000000000000000000000000030
0.0000000000000000000000000001
0.0000000000000000000000000000
-0.0000000000000000000000000001
0.0000000000000000000000000000
0.1000000000000000000000000000
0.1000000000000000000000000000");
}
}
[Fact]
public void DecimalZero()
{
var source = @"
using System;
using System.Linq;
class C
{
static void Main()
{
Dump(0E0M);
Dump(0.0E0M);
Dump(0.00E0M);
Console.WriteLine();
Dump(0E-1M);
Dump(0E-10M);
Dump(-0E-10M);
Dump(0.00E-10M);
Dump(0E-100M); //differs from dev10
Console.WriteLine();
Dump(decimal.Negate(0E0M));
Dump(decimal.Negate(0.0E0M));
Dump(decimal.Negate(0.00E0M));
Console.WriteLine();
Dump(decimal.Negate(0E-1M));
Dump(decimal.Negate(0E-10M));
Dump(decimal.Negate(-0E-10M));
Dump(decimal.Negate(0.00E-10M));
Dump(decimal.Negate(0E-100M)); //differs from dev10
}
static string ToHexString(decimal d)
{
return string.Join("""", decimal.GetBits(d).Select(word => string.Format(""{0:x8}"", word)));
}
static void Dump(decimal d)
{
Console.WriteLine(ToHexString(d));
}
}
";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"
00000000000000000000000000000000
00000000000000000000000000010000
00000000000000000000000000020000
00000000000000000000000000010000
000000000000000000000000000a0000
000000000000000000000000800a0000
000000000000000000000000000c0000
000000000000000000000000001c0000
00000000000000000000000080000000
00000000000000000000000080010000
00000000000000000000000080020000
00000000000000000000000080010000
000000000000000000000000800a0000
000000000000000000000000000a0000
000000000000000000000000800c0000
000000000000000000000000801c0000
");
}
// Breaking change: native compiler allows 0eNm where N > 0.
// (The native compiler ignores sign and scale in 0eNm if N > 0
// and represents such cases as 0e0m.)
[WorkItem(568475, "DevDiv")]
[Fact]
public void DecimalZero_BreakingChange()
{
var source =
@"using System;
class C
{
static void Main()
{
Console.WriteLine(0E1M);
Console.WriteLine(0E10M);
Console.WriteLine(-0E10M);
Console.WriteLine(0.00E10M);
Console.WriteLine(-0.00E10M);
Console.WriteLine(0E100M);
}
}";
decimal d;
if (decimal.TryParse("0E1", System.Globalization.NumberStyles.AllowExponent, null, out d))
{
CreateCompilation(source).VerifyDiagnostics();
}
else
{
CreateCompilation(source).VerifyDiagnostics(
// (6,27): error CS0594: Floating-point constant is outside the range of type 'decimal'
Diagnostic(ErrorCode.ERR_FloatOverflow, "0E1M").WithArguments("decimal").WithLocation(6, 27),
// (7,27): error CS0594: Floating-point constant is outside the range of type 'decimal'
Diagnostic(ErrorCode.ERR_FloatOverflow, "0E10M").WithArguments("decimal").WithLocation(7, 27),
// (8,28): error CS0594: Floating-point constant is outside the range of type 'decimal'
Diagnostic(ErrorCode.ERR_FloatOverflow, "0E10M").WithArguments("decimal").WithLocation(8, 28),
// (9,27): error CS0594: Floating-point constant is outside the range of type 'decimal'
Diagnostic(ErrorCode.ERR_FloatOverflow, "0.00E10M").WithArguments("decimal").WithLocation(9, 27),
// (10,28): error CS0594: Floating-point constant is outside the range of type 'decimal'
Diagnostic(ErrorCode.ERR_FloatOverflow, "0.00E10M").WithArguments("decimal").WithLocation(10, 28),
// (11,27): error CS0594: Floating-point constant is outside the range of type 'decimal'
Diagnostic(ErrorCode.ERR_FloatOverflow, "0E100M").WithArguments("decimal").WithLocation(11, 27));
}
}
[Fact]
public void DecimalPositive()
{
var source = @"
using System;
using System.Linq;
class Goo
{
static void Main()
{
Dump(1E0M);
Dump(1.0E0M);
Dump(1.00E0M);
Console.WriteLine();
Dump(1E1M);
Dump(1E10M);
Dump(1E28M);
Console.WriteLine();
Dump(1E-1M);
Dump(1E-10M);
Dump(1E-28M);
Console.WriteLine();
Dump(decimal.Negate(1E0M));
Dump(decimal.Negate(1.0E0M));
Dump(decimal.Negate(1.00E0M));
Console.WriteLine();
Dump(decimal.Negate(1E1M));
Dump(decimal.Negate(1E10M));
Dump(decimal.Negate(1E28M));
Console.WriteLine();
Dump(decimal.Negate(1E-1M));
Dump(decimal.Negate(1E-10M));
Dump(decimal.Negate(1E-28M));
}
static string ToHexString(decimal d)
{
return string.Join("""", decimal.GetBits(d).Select(word => string.Format(""{0:x8}"", word)));
}
static void Dump(decimal d)
{
Console.WriteLine(ToHexString(d));
}
}
";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"
00000001000000000000000000000000
0000000a000000000000000000010000
00000064000000000000000000020000
0000000a000000000000000000000000
540be400000000020000000000000000
100000003e250261204fce5e00000000
00000001000000000000000000010000
000000010000000000000000000a0000
000000010000000000000000001c0000
00000001000000000000000080000000
0000000a000000000000000080010000
00000064000000000000000080020000
0000000a000000000000000080000000
540be400000000020000000080000000
100000003e250261204fce5e80000000
00000001000000000000000080010000
000000010000000000000000800a0000
000000010000000000000000801c0000
");
}
[Fact]
public void DecimalNegative()
{
var source = @"
using System;
using System.Linq;
class Goo
{
static void Main()
{
Dump(-1E0M);
Dump(-1.0E0M);
Dump(-1.00E0M);
Console.WriteLine();
Dump(-1E1M);
Dump(-1E10M);
Dump(-1E28M);
Console.WriteLine();
Dump(-1E-1M);
Dump(-1E-10M);
Dump(-1E-28M);
Console.WriteLine();
Dump(decimal.Negate(-1E0M));
Dump(decimal.Negate(-1.0E0M));
Dump(decimal.Negate(-1.00E0M));
Console.WriteLine();
Dump(decimal.Negate(-1E1M));
Dump(decimal.Negate(-1E10M));
Dump(decimal.Negate(-1E28M));
Console.WriteLine();
Dump(decimal.Negate(-1E-1M));
Dump(decimal.Negate(-1E-10M));
Dump(decimal.Negate(-1E-28M));
}
static string ToHexString(decimal d)
{
return string.Join("""", decimal.GetBits(d).Select(word => string.Format(""{0:x8}"", word)));
}
static void Dump(decimal d)
{
Console.WriteLine(ToHexString(d));
}
}
";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"
00000001000000000000000080000000
0000000a000000000000000080010000
00000064000000000000000080020000
0000000a000000000000000080000000
540be400000000020000000080000000
100000003e250261204fce5e80000000
00000001000000000000000080010000
000000010000000000000000800a0000
000000010000000000000000801c0000
00000001000000000000000000000000
0000000a000000000000000000010000
00000064000000000000000000020000
0000000a000000000000000000000000
540be400000000020000000000000000
100000003e250261204fce5e00000000
00000001000000000000000000010000
000000010000000000000000000a0000
000000010000000000000000001c0000
");
}
[Fact]
public void DecimalMaxValue()
{
var source = @"
using System;
using System.Linq;
class Goo
{
static void Main()
{
Dump(79228162514264337593543950335E0M);
Dump(7922816251426433759354395033.5E1M);
Dump(792281625142643375935439.50335E5M);
Dump(7.9228162514264337593543950335E28M);
Console.WriteLine();
Dump(79228162514264337593543950335E-0M);
Dump(79228162514264337593543950335E-1M);
Dump(79228162514264337593543950335E-5M);
Dump(79228162514264337593543950335E-28M);
Console.WriteLine();
Dump(decimal.Negate(79228162514264337593543950335E0M));
Dump(decimal.Negate(7922816251426433759354395033.5E1M));
Dump(decimal.Negate(792281625142643375935439.50335E5M));
Dump(decimal.Negate(7.9228162514264337593543950335E28M));
Console.WriteLine();
Dump(decimal.Negate(79228162514264337593543950335E-0M));
Dump(decimal.Negate(79228162514264337593543950335E-1M));
Dump(decimal.Negate(79228162514264337593543950335E-5M));
Dump(decimal.Negate(79228162514264337593543950335E-28M));
}
static string ToHexString(decimal d)
{
return string.Join("""", decimal.GetBits(d).Select(word => string.Format(""{0:x8}"", word)));
}
static void Dump(decimal d)
{
Console.WriteLine(ToHexString(d));
}
}
";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"
ffffffffffffffffffffffff00000000
ffffffffffffffffffffffff00000000
ffffffffffffffffffffffff00000000
ffffffffffffffffffffffff00000000
ffffffffffffffffffffffff00000000
ffffffffffffffffffffffff00010000
ffffffffffffffffffffffff00050000
ffffffffffffffffffffffff001c0000
ffffffffffffffffffffffff80000000
ffffffffffffffffffffffff80000000
ffffffffffffffffffffffff80000000
ffffffffffffffffffffffff80000000
ffffffffffffffffffffffff80000000
ffffffffffffffffffffffff80010000
ffffffffffffffffffffffff80050000
ffffffffffffffffffffffff801c0000
");
}
[Fact]
public void DecimalConversion01()
{
string source = @"
using System;
class C
{
static int Goo()
{
int i = 10;
return (int)(decimal)(int)i;
}
static int Bar()
{
return (int)decimal.One;
}
static void Main(string[] args)
{
int i = Goo();
int j = Bar();
Console.Write(i);
Console.Write(j);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: "101");
compilation.VerifyIL("C.Goo",
@"{
// Code size 13 (0xd)
.maxstack 1
IL_0000: ldc.i4.s 10
IL_0002: call ""decimal decimal.op_Implicit(int)""
IL_0007: call ""int decimal.op_Explicit(decimal)""
IL_000c: ret
}");
compilation.VerifyIL("C.Bar",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: ret
}");
}
[Fact]
public void DecimalConversion02()
{
string source = @"
using System;
using System.Globalization;
class C
{
static void Main(string[] args)
{
decimal myMoney = 99.9m;
double x = (double)myMoney;
myMoney = (decimal)x;
System.Console.Write(myMoney.ToString(CultureInfo.InvariantCulture));
}
}";
var compilation = CompileAndVerify(source, expectedOutput: "99.9");
compilation.VerifyIL("C.Main", """
{
// Code size 47 (0x2f)
.maxstack 6
.locals init (decimal V_0) //myMoney
IL_0000: ldloca.s V_0
IL_0002: ldc.i4 0x3e7
IL_0007: ldc.i4.0
IL_0008: ldc.i4.0
IL_0009: ldc.i4.0
IL_000a: ldc.i4.1
IL_000b: call "decimal..ctor(int, int, int, bool, byte)"
IL_0010: ldloc.0
IL_0011: call "double decimal.op_Explicit(decimal)"
IL_0016: conv.r8
IL_0017: call "decimal decimal.op_Explicit(double)"
IL_001c: stloc.0
IL_001d: ldloca.s V_0
IL_001f: call "System.Globalization.CultureInfo System.Globalization.CultureInfo.InvariantCulture.get"
IL_0024: call "string decimal.ToString(System.IFormatProvider)"
IL_0029: call "void System.Console.Write(string)"
IL_002e: ret
}
""");
}
[Fact]
public void DecimalConversion03()
{
string source = @"
class Program
{
static void Main(string[] args)
{
D = I;
}
public static decimal D { get; set; }
public static int I { get; set; }
}
";
var compilation = CompileAndVerify(source);
}
[Fact]
public void DecimalConversion04()
{
string source = @"
class Program
{
double x = 1.0;
decimal y = decimal.One;
static void Main(string[] args)
{
Program a = new Program();
double x = (double)a.y;
decimal y = (decimal)a.x;
System.Console.Write(x);
System.Console.Write(y);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "11");
}
[WorkItem(543888, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543888")]
[Fact]
public void DecimalConversion05()
{
string source = @"
using System;
enum E
{
One = 1, Two, Three, Four, Five
}
public class C
{
public static void Main()
{
decimal d1 = 1m;
decimal d2 = 3m;
decimal d3 = 5m;
E e = (E)d1;
Console.WriteLine(e);
e = (E)d2;
Console.WriteLine(e);
e = (E)d3;
Console.WriteLine(e);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
One
Three
Five
");
}
[WorkItem(543888, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543888")]
[Fact]
public void DecimalConversion06()
{
string source = @"
using System;
enum E
{
Sat, Sun, Mon, Tue, Wed, Thu, Fri
}
public class C
{
public static void Main()
{
decimal d = (decimal)E.Sun;
Console.WriteLine(d);
d = (decimal)E.Wed;
Console.WriteLine(d);
d = (decimal)E.Fri;
Console.WriteLine(d);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
1
4
6
");
}
[WorkItem(543888, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543888")]
[Fact]
public void DecimalConversion07()
{
string source = @"
using System;
enum E
{
E1, E2
}
public class C
{
public static void Main()
{
decimal d1 = 1.00M;
decimal d2 = (decimal)(E)d1;
Console.WriteLine(d2);
E e = (E)((decimal)(E.E1)+1);
Console.WriteLine(e);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
1
E2
");
}
[WorkItem(539392, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539392")]
[Fact]
public void DecimalBinaryOp_01()
{
string source = @"
class C
{
static void Main(string[] args)
{
var y = decimal.MaxValue + 0;
System.Console.Write(y);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: "79228162514264337593543950335");
compilation.VerifyIL("C.Main",
@"{
// Code size 16 (0x10)
.maxstack 5
IL_0000: ldc.i4.m1
IL_0001: ldc.i4.m1
IL_0002: ldc.i4.m1
IL_0003: ldc.i4.0
IL_0004: ldc.i4.0
IL_0005: newobj ""decimal..ctor(int, int, int, bool, byte)""
IL_000a: call ""void System.Console.Write(decimal)""
IL_000f: ret
}");
}
[WorkItem(543279, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543279")]
[Fact]
public void DecimalBinaryOp_02()
{
string source = @"
class C
{
static void Main(string[] args)
{
System.Console.Write(decimal.MaxValue + decimal.MinusOne);
System.Console.Write(0 + decimal.MinusOne);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: "79228162514264337593543950334-1");
compilation.VerifyIL("C.Main",
@"
{
// Code size 27 (0x1b)
.maxstack 5
IL_0000: ldc.i4.s -2
IL_0002: ldc.i4.m1
IL_0003: ldc.i4.m1
IL_0004: ldc.i4.0
IL_0005: ldc.i4.0
IL_0006: newobj ""decimal..ctor(int, int, int, bool, byte)""
IL_000b: call ""void System.Console.Write(decimal)""
IL_0010: ldsfld ""decimal decimal.MinusOne""
IL_0015: call ""void System.Console.Write(decimal)""
IL_001a: ret
}");
}
[ConditionalFact(typeof(DesktopOnly), Reason = "https://github.com/dotnet/runtime/issues/1611")]
[WorkItem(32576, "https://github.com/dotnet/roslyn/issues/32576")]
[WorkItem(34198, "https://github.com/dotnet/roslyn/issues/34198")]
public void DecimalBinaryOp_03()
{
string source = @"
using System.Globalization;
class C
{
// http://msdn.microsoft.com/en-US/library/system.decimal.remainder(v=vs.110).aspx
static void M(decimal d1, decimal d2)
{
var r1 = d1 + d2;
System.Console.WriteLine(r1.ToString(CultureInfo.InvariantCulture));
var r2 = d1 - d2;
System.Console.WriteLine(r2.ToString(CultureInfo.InvariantCulture));
var r3 = d1 * d2;
System.Console.WriteLine(r3.ToString(CultureInfo.InvariantCulture));
var r4 = d1 / d2;
System.Console.WriteLine(r4.ToString(CultureInfo.InvariantCulture));
var r5 = d1 % d2;
System.Console.WriteLine(r5.ToString(CultureInfo.InvariantCulture));
}
static void Main(string[] args)
{
M(1000M, 7M);
M(-1000M, 7M);
M(new decimal(1230000000, 0, 0, false, 7), 0.0012300M);
M(12345678900000000M, 0.0000000012345678M);
M(123456789.0123456789M, 123456789.1123456789M);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
1007
993
7000
142.85714285714285714285714286
6
-993
-1007
-7000
-142.85714285714285714285714286
-6
123.0012300
122.9987700
0.15129000000000
100000
0.0000000
12345678900000000.000000001235
12345678899999999.999999998765
15241577.6390794200000000
10000000729000059778004901.796
0.000000000983
246913578.1246913578
-0.1000000000
15241578765584515.651425087878
0.9999999991899999933660999449
123456789.0123456789
");
}
[Fact]
public void DecimalBinaryOp_04()
{
string source = @"
class C
{
// http://msdn.microsoft.com/en-us/library/system.decimal.compare(v=vs.110).aspx
static void M(decimal d1, decimal d2)
{
var r1 = d1 == d2;
System.Console.WriteLine(r1);
var r2 = d1 != d2;
System.Console.WriteLine(r2);
var r3 = d1 >= d2;
System.Console.WriteLine(r3);
var r4 = d1 > d2;
System.Console.WriteLine(r4);
var r5 = d1 <= d2;
System.Console.WriteLine(r5);
var r6 = d1 < d2;
System.Console.WriteLine(r6);
System.Console.WriteLine();
}
static void Main(string[] args)
{
M(new decimal(123.456), new decimal(1.2345600E+2));
M(new decimal(123.456), 123.4561M);
M(new decimal(123.456), 123.4559M);
M(new decimal(123.456), 123.456000M);
M(new decimal(123.456), new decimal(123456000, 0, 0, false, 6));
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
True
False
True
False
True
False
False
True
False
False
True
True
False
True
True
True
False
False
True
False
True
False
True
False
True
False
True
False
True
False
");
}
[Fact]
public void DecimalUnaryOp_01()
{
string source = @"
using System.Globalization;
class C
{
static void Main(string[] args)
{
var x1 = +123.456M;
WriteLine(x1);
var x2 = -123.456M;
WriteLine(x2);
var x3 = +x1;
WriteLine(x3);
var x4 = -x1;
WriteLine(x4);
var x5 = ++x1;
WriteLine(x5);
var x6 = x1++;
WriteLine(x6);
var x7 = x1--;
WriteLine(x7);
var x8 = --x1;
WriteLine(x8);
}
static void WriteLine(decimal d) => System.Console.WriteLine(d.ToString(CultureInfo.InvariantCulture));
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
123.456
-123.456
123.456
-123.456
124.456
124.456
125.456
123.456
");
compilation.VerifyIL("C.Main",
"""
{
// Code size 111 (0x6f)
.maxstack 6
.locals init (decimal V_0) //x1
IL_0000: ldloca.s V_0
IL_0002: ldc.i4 0x1e240
IL_0007: ldc.i4.0
IL_0008: ldc.i4.0
IL_0009: ldc.i4.0
IL_000a: ldc.i4.3
IL_000b: call "decimal..ctor(int, int, int, bool, byte)"
IL_0010: ldloc.0
IL_0011: call "void C.WriteLine(decimal)"
IL_0016: ldc.i4 0x1e240
IL_001b: ldc.i4.0
IL_001c: ldc.i4.0
IL_001d: ldc.i4.1
IL_001e: ldc.i4.3
IL_001f: newobj "decimal..ctor(int, int, int, bool, byte)"
IL_0024: call "void C.WriteLine(decimal)"
IL_0029: ldloc.0
IL_002a: call "void C.WriteLine(decimal)"
IL_002f: ldloc.0
IL_0030: call "decimal decimal.op_UnaryNegation(decimal)"
IL_0035: call "void C.WriteLine(decimal)"
IL_003a: ldloc.0
IL_003b: call "decimal decimal.op_Increment(decimal)"
IL_0040: dup
IL_0041: stloc.0
IL_0042: call "void C.WriteLine(decimal)"
IL_0047: ldloc.0
IL_0048: dup
IL_0049: call "decimal decimal.op_Increment(decimal)"
IL_004e: stloc.0
IL_004f: call "void C.WriteLine(decimal)"
IL_0054: ldloc.0
IL_0055: dup
IL_0056: call "decimal decimal.op_Decrement(decimal)"
IL_005b: stloc.0
IL_005c: call "void C.WriteLine(decimal)"
IL_0061: ldloc.0
IL_0062: call "decimal decimal.op_Decrement(decimal)"
IL_0067: dup
IL_0068: stloc.0
IL_0069: call "void C.WriteLine(decimal)"
IL_006e: ret
}
""");
}
[Fact]
public void DecimalUnaryOp_02()
{
string source = @"
using System;
using System.Globalization;
class C
{
// http://msdn.microsoft.com/en-us/library/system.decimal.op_unarynegation(v=vs.110).aspx
public static string GetExceptionType(Exception ex)
{
string exceptionType = ex.GetType().ToString();
return exceptionType.Substring(
exceptionType.LastIndexOf('.') + 1);
}
// Display the argument and the incremented and decremented values.
public static void DecIncrDecrUnary(decimal argument)
{
decimal toBeIncr = argument;
decimal toBeDecr = argument;
// Catch the exception if the increment operator throws one.
try
{
toBeIncr++;
System.Console.WriteLine(toBeIncr.ToString(CultureInfo.InvariantCulture));
}
catch (Exception ex)
{
System.Console.WriteLine(GetExceptionType(ex));
}
// Catch the exception if the decrement operator throws one.
try
{
toBeDecr--;
System.Console.WriteLine(toBeDecr.ToString(CultureInfo.InvariantCulture));
}
catch (Exception ex)
{
System.Console.WriteLine(GetExceptionType(ex));
}
System.Console.WriteLine();
}
static void Main(string[] args)
{
// Create objects to compare with the reference.
DecIncrDecrUnary(0.000000123M);
DecIncrDecrUnary(new decimal(123000000, 0, 0, false, 9));
DecIncrDecrUnary(-new decimal(123000000, 0, 0, false, 9));
DecIncrDecrUnary(+decimal.MaxValue);
DecIncrDecrUnary(-decimal.MaxValue);
DecIncrDecrUnary(+7.5000000000000000000000000001M);
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
1.000000123
-0.999999877
1.123000000
-0.877000000
0.877000000
-1.123000000
OverflowException
79228162514264337593543950334
-79228162514264337593543950334
OverflowException
8.500000000000000000000000000
6.5000000000000000000000000001
");
}
[WorkItem(542568, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542568")]
[Fact]
public void ImplicitConversionForOptional()
{
string source = @"class MyClass
{
void Goo(decimal x = 10) { }
}
";
CompileAndVerify(source);
}
[WorkItem(542742, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542742")]
[Fact]
public void CodeGenEmptyStatement()
{
string source = @"class Test
{
static void Main()
{
;
}
}";
CompileAndVerify(source);
}
[WorkItem(542458, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542458")]
[Fact]
public void DefaultParamValueIsStruct_SameAssembly()
{
string source = @"
public class Test
{
public static void Main()
{
DefaultParameterValues.M(""hello"");
}
}
public class DefaultParameterValues
{
public static void M(
string text,
string path = """",
DefaultParameterValues d = null,
System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
}
";
CompileAndVerify(source).VerifyIL("Test.Main", @"
{
// Code size 26 (0x1a)
.maxstack 4
.locals init (System.Threading.CancellationToken V_0)
IL_0000: ldstr ""hello""
IL_0005: ldstr """"
IL_000a: ldnull
IL_000b: ldloca.s V_0
IL_000d: initobj ""System.Threading.CancellationToken""
IL_0013: ldloc.0
IL_0014: call ""void DefaultParameterValues.M(string, string, DefaultParameterValues, System.Threading.CancellationToken)""
IL_0019: ret
}
");
}
[WorkItem(542458, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542458")]
[Fact]
public void DefaultParamValueIsStruct_DifferentAssembly()
{
var source1 = @"
public class DefaultParameterValues
{
public static void M(
string text,
string path = """",
DefaultParameterValues d = null,
System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
}
";
var compilation1 = CreateCompilation(source1);
var source2 = @"
public class Test
{
public static void Main()
{
DefaultParameterValues.M(""hello"");
}
}
";
CompileAndVerify(source2, new[] { new CSharpCompilationReference(compilation1) }).VerifyIL("Test.Main", @"
{
// Code size 26 (0x1a)
.maxstack 4
.locals init (System.Threading.CancellationToken V_0)
IL_0000: ldstr ""hello""
IL_0005: ldstr """"
IL_000a: ldnull
IL_000b: ldloca.s V_0
IL_000d: initobj ""System.Threading.CancellationToken""
IL_0013: ldloc.0
IL_0014: call ""void DefaultParameterValues.M(string, string, DefaultParameterValues, System.Threading.CancellationToken)""
IL_0019: ret
}
");
}
[WorkItem(542458, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542458")]
[Fact]
public void DefaultParamValueIsStruct_MetadataAssembly()
{
var source = @"
public class Test
{
public static void Main()
{
DefaultParameterValues.M(""hello"");
}
}
";
CompileAndVerify(source, new[] { TestReferences.SymbolsTests.Methods.CSMethods }).VerifyIL("Test.Main", @"
{
// Code size 26 (0x1a)
.maxstack 4
.locals init (System.Threading.CancellationToken V_0)
IL_0000: ldstr ""hello""
IL_0005: ldstr """"
IL_000a: ldnull
IL_000b: ldloca.s V_0
IL_000d: initobj ""System.Threading.CancellationToken""
IL_0013: ldloc.0
IL_0014: call ""void DefaultParameterValues.M(string, string, DefaultParameterValues, System.Threading.CancellationToken)""
IL_0019: ret
}
");
}
[WorkItem(542417, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542417")]
[Fact]
public void DefaultParameterInGenericMethod()
{
var source =
@"using System;
public class Program
{
public static void Goo(string str2, string str = ""test1"")
{
Console.WriteLine(""Goo("" + str2 + "", "" + str + "")"");
}
public static void Goo<T>(T str2, string str = ""test2"")
{
Console.WriteLine(""Goo<"" + typeof(T) + "">("" + str2 + "", "" + str + "")"");
}
public static void Main()
{
Goo<string>(""test3"");
}
}";
CompileAndVerify(source, expectedOutput: "Goo<System.String>(test3, test2)");
}
[WorkItem(542920, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542920")]
[Fact]
public void PassExceptionVarByRef()
{
string source = @"
using System;
class Test
{
static void Goo(out Exception ex)
{
ex = new Exception(""bye"");
}
static void Main()
{
try{
throw new Exception(""hi"");
} catch (Exception ex){
Goo(out ex);
Console.WriteLine(ex.Message);
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"bye");
compilation.VerifyIL("Test.Main",
@"{
// Code size 33 (0x21)
.maxstack 1
.locals init (System.Exception V_0) //ex
.try
{
IL_0000: ldstr ""hi""
IL_0005: newobj ""System.Exception..ctor(string)""
IL_000a: throw
}
catch System.Exception
{
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: call ""void Test.Goo(out System.Exception)""
IL_0013: ldloc.0
IL_0014: callvirt ""string System.Exception.Message.get""
IL_0019: call ""void System.Console.WriteLine(string)""
IL_001e: leave.s IL_0020
}
IL_0020: ret
}
");
}
[WorkItem(10616, "DevDiv_Projects/Roslyn")]
[Fact]
public void EnumAsOptionalParameter()
{
string source = @"
using System;
public enum E
{
e1, e2=3, e3
}
public class Parent
{
public int Goo(E e = E.e2) { return e == E.e2 ? 0 : 1; }
}
public class Test
{
public static int Main()
{
var ret = new Parent().Goo();
Console.WriteLine(ret);
return ret;
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"0");
compilation.VerifyIL("Test.Main",
@"{
// Code size 18 (0x12)
.maxstack 2
IL_0000: newobj ""Parent..ctor()""
IL_0005: ldc.i4.3
IL_0006: call ""int Parent.Goo(E)""
IL_000b: dup
IL_000c: call ""void System.Console.WriteLine(int)""
IL_0011: ret
}");
}
[WorkItem(2272, "https://github.com/dotnet/roslyn/issues/2272")]
[Fact]
public void DefaultParamValueIsEnum()
{
string source = @"
using System;
public class Parent
{
public int Goo(ConsoleKey e = ConsoleKey.A) { return e == ConsoleKey.A ? 0 : 1; }
}
public class Test
{
public static int Main()
{
var ret = new Parent().Goo();
Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"0");
}
[WorkItem(543089, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543089")]
[Fact()]
public void NoOutAttributeOnMethodReturn()
{
string source = @"
using System;
class A : Attribute { }
class C
{
[return: A]
void Goo() { }
static void Main()
{
var obj = new C();
var attrs = ((Action)obj.Goo).Method.ReturnTypeCustomAttributes.GetCustomAttributes(false);
Console.Write(attrs.Length);
for (int i = 0; i < attrs.Length; i++)
Console.WriteLine(attrs[i]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"1A");
}
[WorkItem(543090, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543090")]
[Fact()]
public void EmitAttributeOnPartialMethodReturnType()
{
string source = @"
using System;
class A : Attribute { }
partial class C
{
[return: A]
partial void Bar() { }
}
partial class C
{
partial void Bar();
static void Main()
{
var obj = new C();
var attrs = ((Action)obj.Bar).Method.ReturnTypeCustomAttributes.GetCustomAttributes(false);
Console.Write(attrs.Length);
for (int i = 0; i < attrs.Length; i++)
Console.WriteLine(attrs[i]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"1A");
}
[WorkItem(543530, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543530")]
[Fact()]
public void EmitAttributeWithNullTypeArgument1()
{
string source = @"
using System;
using System.Reflection;
class Base1 : Attribute
{
public Base1(Type opt = null)
{
this.Result = opt == null ? ""null"" : opt.ToString();
}
public string Result;
}
class C1
{
[Base1(null)]
static void A(string[] args)
{
}
[Base1()]
static void B(string name)
{
var m = typeof(C1).GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic);
Console.Write(((Base1)m.GetCustomAttributes(typeof(Base1), false)[0]).Result);
Console.Write("";"");
}
[Base1(typeof(C1))]
static void Main(string[] args)
{
B(""A"");
B(""B"");
B(""Main"");
}
}";
var compilation = CompileAndVerify(source, expectedOutput: "null;null;C1;");
}
[WorkItem(543091, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543091")]
[Fact()]
public void EmitAttributeOnPartialMethodParameter()
{
string source = @"
using System;
class A : Attribute { }
partial class C
{
partial void Gen<T>([A]T t);
}
partial class C
{
partial void Gen<T>(T t) { }
static void Main()
{
var obj = new C();
var goo = ((Action<int>)obj.Gen<int>).Method;
var attrs = goo.GetParameters()[0].GetCustomAttributes(false);
Console.Write(attrs.Length);
for (int i = 0; i < attrs.Length; i++)
Console.WriteLine(attrs[i]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"1A");
}
[WorkItem(543156, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543156")]
[Fact()]
public void OverloadResolutionWithParams()
{
string source = @"
using System;
public class C
{
public int Goo(object i = null, object j = null) { return 0; }
public int Goo(int i = 0, params object[] arr) { return 1; }
public int Bar(object o = null, int i = 1, params object[] arr) { return 1; }
public int Bar(string s = ""PickMe"", int i = 1, object o = null) { return 0; }
}
class Test
{
public static void Main()
{
var obj = new C();
Console.Write(obj.Goo());
Console.Write(obj.Bar(i: 3));
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"00");
}
[WorkItem(543157, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543157")]
[Fact()]
public void MultipleUseOfObjectInstance()
{
string source = @"
using System;
class Program
{
public static void Main()
{
Console.WriteLine(Test());
}
public static int Test()
{
var obj = new C();
if (obj.M1() != 10)
return 1;
if (obj.M2() != 20)
return 1;
return 0;
}
class C
{
public int M1() { return 10; }
public int M2() { return 20; }
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"0");
}
[WorkItem(543566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543566")]
[Fact()]
public void OptionalTypeParameterWithDefaultT()
{
string source = @"
using System;
using System.Collections.Generic;
public class Parent<T>
{
public int Goo(T t = default(T))
{
if (t == null) return 0;
return 1;
}
}
class Test
{
public static void Main()
{
var p = new Parent<String>();
Console.Write(p.Goo());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"0");
}
[Fact(), WorkItem(543667, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543667")]
public void BaseCallInAnonymousMethodInGenericMethodWithHoistedLocal()
{
string source = @"
using System;
class A<T>
{
public virtual V PrintField<V, W>(V v, W w)
{
return default(V);
}
}
class B<T> : A<T>
{
public override V PrintField<V, W>(V v, W w)
{
int i = 10;
Func<V, W, V> f = delegate(V dv, W dw)
{
var x = i;
return base.PrintField(dv, dw);
};
return default(V);
}
}";
CompileAndVerify(source);
}
#endregion
[Fact]
[CompilerTrait(CompilerFeature.PEVerifyCompat)]
public void MutateReadonlyNested()
{
string source = @"
using System;
class Program
{
public static void Main()
{
var c = new cls1();
c.y.mutate(123);
c.y.n.n.mutate(456);
Console.WriteLine(c.y.n.n.num);
}
}
class cls1
{
public readonly MyManagedStruct y = new MyManagedStruct(42);
}
struct MyManagedStruct
{
public struct Nested
{
public Nested1 n;
public struct Nested1
{
public int num;
public void mutate(int x)
{
num = x;
}
}
}
public Nested n;
public void mutate(int x)
{
n.n.num = x;
}
public MyManagedStruct(int x)
{
n.n.num = x;
}
}";
// PEVerify: Cannot change initonly field outside its .ctor.
var comp = CompileAndVerify(source, expectedOutput: @"42", parseOptions: TestOptions.Regular7_2, verify: Verification.FailsPEVerify);
comp.VerifyIL("Program.Main",
@"
{
// Code size 76 (0x4c)
.maxstack 3
.locals init (MyManagedStruct V_0,
MyManagedStruct.Nested.Nested1 V_1)
IL_0000: newobj ""cls1..ctor()""
IL_0005: dup
IL_0006: ldfld ""MyManagedStruct cls1.y""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.s 123
IL_0010: call ""void MyManagedStruct.mutate(int)""
IL_0015: dup
IL_0016: ldflda ""MyManagedStruct cls1.y""
IL_001b: ldflda ""MyManagedStruct.Nested MyManagedStruct.n""
IL_0020: ldfld ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0025: stloc.1
IL_0026: ldloca.s V_1
IL_0028: ldc.i4 0x1c8
IL_002d: call ""void MyManagedStruct.Nested.Nested1.mutate(int)""
IL_0032: ldflda ""MyManagedStruct cls1.y""
IL_0037: ldflda ""MyManagedStruct.Nested MyManagedStruct.n""
IL_003c: ldflda ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0041: ldfld ""int MyManagedStruct.Nested.Nested1.num""
IL_0046: call ""void System.Console.WriteLine(int)""
IL_004b: ret
}
");
comp = CompileAndVerify(source, expectedOutput: @"42", verify: Verification.Passes, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
comp.VerifyIL("Program.Main",
@"
{
// Code size 76 (0x4c)
.maxstack 3
.locals init (MyManagedStruct V_0)
IL_0000: newobj ""cls1..ctor()""
IL_0005: dup
IL_0006: ldfld ""MyManagedStruct cls1.y""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.s 123
IL_0010: call ""void MyManagedStruct.mutate(int)""
IL_0015: dup
IL_0016: ldfld ""MyManagedStruct cls1.y""
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldflda ""MyManagedStruct.Nested MyManagedStruct.n""
IL_0023: ldflda ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0028: ldc.i4 0x1c8
IL_002d: call ""void MyManagedStruct.Nested.Nested1.mutate(int)""
IL_0032: ldfld ""MyManagedStruct cls1.y""
IL_0037: ldfld ""MyManagedStruct.Nested MyManagedStruct.n""
IL_003c: ldfld ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0041: ldfld ""int MyManagedStruct.Nested.Nested1.num""
IL_0046: call ""void System.Console.WriteLine(int)""
IL_004b: ret
}
");
comp = CompileAndVerify(source, expectedOutput: @"42", verify: Verification.Passes, parseOptions: TestOptions.Regular7_1);
comp.VerifyIL("Program.Main",
@"
{
// Code size 76 (0x4c)
.maxstack 3
.locals init (MyManagedStruct V_0)
IL_0000: newobj ""cls1..ctor()""
IL_0005: dup
IL_0006: ldfld ""MyManagedStruct cls1.y""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.s 123
IL_0010: call ""void MyManagedStruct.mutate(int)""
IL_0015: dup
IL_0016: ldfld ""MyManagedStruct cls1.y""
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldflda ""MyManagedStruct.Nested MyManagedStruct.n""
IL_0023: ldflda ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0028: ldc.i4 0x1c8
IL_002d: call ""void MyManagedStruct.Nested.Nested1.mutate(int)""
IL_0032: ldfld ""MyManagedStruct cls1.y""
IL_0037: ldfld ""MyManagedStruct.Nested MyManagedStruct.n""
IL_003c: ldfld ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n""
IL_0041: ldfld ""int MyManagedStruct.Nested.Nested1.num""
IL_0046: call ""void System.Console.WriteLine(int)""
IL_004b: ret
}
");
}
[Fact]
[CompilerTrait(CompilerFeature.PEVerifyCompat)]
public void MutateReadonlyNested1()
{
string source = @"
class Program
{
static void Main(string[] args)
{
GetRoRef().ro.ro.ro.ro.ToString();
System.Console.Write(GetRoRef().ro.ro.ro.ro.x);
}
private static ref readonly Largest GetRoRef()
{
return ref (new Largest[1])[0];
}
}
struct Largest
{
public int x;
public readonly Large ro;
}
struct Large
{
public int x;
public Medium ro;
}
struct Medium
{
public int x;
public Small ro;
}
struct Small
{
public int x;
public Smallest ro;
}
struct Smallest
{
public int x;
public override string ToString()
{
x = -1;
System.Console.Write(x);
return null;
}
}";
// PEVerify: Cannot change initonly field outside its .ctor.
var comp = CompileAndVerify(source, expectedOutput: @"-10", verify: Verification.FailsPEVerify);
comp.VerifyIL("Program.Main",
@"
{
// Code size 76 (0x4c)
.maxstack 1
.locals init (Smallest V_0)
IL_0000: call ""ref readonly Largest Program.GetRoRef()""
IL_0005: ldflda ""Large Largest.ro""
IL_000a: ldflda ""Medium Large.ro""
IL_000f: ldflda ""Small Medium.ro""
IL_0014: ldfld ""Smallest Small.ro""
IL_0019: stloc.0
IL_001a: ldloca.s V_0
IL_001c: constrained. ""Smallest""
IL_0022: callvirt ""string object.ToString()""
IL_0027: pop
IL_0028: call ""ref readonly Largest Program.GetRoRef()""
IL_002d: ldflda ""Large Largest.ro""
IL_0032: ldflda ""Medium Large.ro""
IL_0037: ldflda ""Small Medium.ro""
IL_003c: ldflda ""Smallest Small.ro""
IL_0041: ldfld ""int Smallest.x""
IL_0046: call ""void System.Console.Write(int)""
IL_004b: ret
}
");
comp = CompileAndVerify(source, expectedOutput: @"-10", verify: Verification.Passes, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
comp.VerifyIL("Program.Main",
@"
{
// Code size 76 (0x4c)
.maxstack 1
.locals init (Large V_0)
IL_0000: call ""ref readonly Largest Program.GetRoRef()""
IL_0005: ldfld ""Large Largest.ro""
IL_000a: stloc.0
IL_000b: ldloca.s V_0
IL_000d: ldflda ""Medium Large.ro""
IL_0012: ldflda ""Small Medium.ro""
IL_0017: ldflda ""Smallest Small.ro""
IL_001c: constrained. ""Smallest""
IL_0022: callvirt ""string object.ToString()""
IL_0027: pop
IL_0028: call ""ref readonly Largest Program.GetRoRef()""
IL_002d: ldfld ""Large Largest.ro""
IL_0032: ldfld ""Medium Large.ro""
IL_0037: ldfld ""Small Medium.ro""
IL_003c: ldfld ""Smallest Small.ro""
IL_0041: ldfld ""int Smallest.x""
IL_0046: call ""void System.Console.Write(int)""
IL_004b: ret
}
");
}
[Fact]
public void LocalNumericConstToString()
{
string source = @"
using System;
class Program
{
static void Main()
{
const SByte SB = 123;
Console.Write(SB.ToString());
}
}";
var compilation = CompileAndVerify(source, expectedOutput: @"123");
// Dev10
compilation.VerifyIL("Program.Main",
@"{
// Code size 16 (0x10)
.maxstack 1
.locals init (sbyte V_0)
IL_0000: ldc.i4.s 123
IL_0002: stloc.0
IL_0003: ldloca.s V_0
IL_0005: call ""string sbyte.ToString()""
IL_000a: call ""void System.Console.Write(string)""
IL_000f: ret
}");
}
[Fact]
public void PassTypeParamFieldByRef()
{
string source = @"
using System;
static class Test
{
class A
{
public object F;
}
class B<T>
{
public T F;
}
// Pass field on type T by ref.
static void M1<T>(T o) where T : A
{
M(ref o.F);
}
// Pass field of type T by ref.
static void M2<T>(B<T> o)
{
M(ref o.F);
}
static void M<T>(ref T arg)
{
}
static void Main()
{
M1(new A());
M2(new B<int>());
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"");
// Dev10
compilation.VerifyIL("Test.M1<T>(T)",
@"{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldarg.0
IL_0001: box ""T""
IL_0006: ldflda ""object Test.A.F""
IL_000b: call ""void Test.M<object>(ref object)""
IL_0010: ret
}");
}
[Fact]
public void NotEqualIntegralAndFloat()
{
string source = @"
class Class1
{
static void Main()
{
int i = -1;
bool result = i != 0;
if (result)
{
System.Console.WriteLine(""notequal1"");
}
result = i == 0;
if (result)
{
System.Console.WriteLine(""equal1"");
}
double d = -1;
result = d != 0;
if (result)
{
System.Console.WriteLine(""notequal2"");
}
result = d == 0;
if (result)
{
System.Console.WriteLine(""equal2"");
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"notequal1
notequal2");
// Dev10
compilation.VerifyIL("Class1.Main",
@"
{
// Code size 92 (0x5c)
.maxstack 3
IL_0000: ldc.i4.m1
IL_0001: dup
IL_0002: ldc.i4.0
IL_0003: cgt.un
IL_0005: brfalse.s IL_0011
IL_0007: ldstr ""notequal1""
IL_000c: call ""void System.Console.WriteLine(string)""
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: brfalse.s IL_0020
IL_0016: ldstr ""equal1""
IL_001b: call ""void System.Console.WriteLine(string)""
IL_0020: ldc.r8 -1
IL_0029: dup
IL_002a: ldc.r8 0
IL_0033: ceq
IL_0035: ldc.i4.0
IL_0036: ceq
IL_0038: brfalse.s IL_0044
IL_003a: ldstr ""notequal2""
IL_003f: call ""void System.Console.WriteLine(string)""
IL_0044: ldc.r8 0
IL_004d: ceq
IL_004f: brfalse.s IL_005b
IL_0051: ldstr ""equal2""
IL_0056: call ""void System.Console.WriteLine(string)""
IL_005b: ret
}
");
}
[WorkItem(529267, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529267")]
[Fact]
public void ModifyRangeVariable()
{
string source = @"
using System.Linq;
class C
{
static void Main()
{
foreach (var e in from x in new int[2] select Goo(ref x))
{
System.Console.Write(e);
}
}
static int Goo(ref int x)
{
return ++x;
}
}
";
// NOTE: this is a breaking change - dev10 builds and prints 11.
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (8,63): error CS1939: Cannot pass the range variable 'x' as an out or ref parameter
// foreach (var e in from x in new int[2] select Goo(ref x))
Diagnostic(ErrorCode.ERR_QueryOutRefRangeVariable, "x").WithArguments("x"));
}
[Fact, WorkItem(529430, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529430")]
public void DelegateEqualityComparison()
{
string source = @"
using System;
public class SinkHelper
{
public Action action;
public void OnEvent()
{
if (action == null)
return;
if (action != null)
action();
}
}
";
CompileAndVerify(source).VerifyIL("SinkHelper.OnEvent", @"
{
// Code size 29 (0x1d)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ldfld ""System.Action SinkHelper.action""
IL_0006: brtrue.s IL_0009
IL_0008: ret
IL_0009: ldarg.0
IL_000a: ldfld ""System.Action SinkHelper.action""
IL_000f: brfalse.s IL_001c
IL_0011: ldarg.0
IL_0012: ldfld ""System.Action SinkHelper.action""
IL_0017: callvirt ""void System.Action.Invoke()""
IL_001c: ret
}");
}
[Fact]
public void UnorthodoxBool()
{
var source = @"
using System;
class Class1
{
static void Main()
{
byte[] x = { 0xFF };
bool[] y = { true };
Buffer.BlockCopy(x, 0, y, 0, 1);
Console.WriteLine(y[0]);
Console.Write(y[0] == true);
Console.Write(y[0] == false);
Console.Write(y[0] != false);
Console.Write(y[0] != true);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"True
TrueFalseTrueFalse");
compilation.VerifyIL("Class1.Main",
@"
{
// Code size 83 (0x53)
.maxstack 5
.locals init (byte[] V_0, //x
bool[] V_1) //y
IL_0000: ldc.i4.1
IL_0001: newarr ""byte""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4 0xff
IL_000d: stelem.i1
IL_000e: stloc.0
IL_000f: ldc.i4.1
IL_0010: newarr ""bool""
IL_0015: dup
IL_0016: ldc.i4.0
IL_0017: ldc.i4.1
IL_0018: stelem.i1
IL_0019: stloc.1
IL_001a: ldloc.0
IL_001b: ldc.i4.0
IL_001c: ldloc.1
IL_001d: ldc.i4.0
IL_001e: ldc.i4.1
IL_001f: call ""void System.Buffer.BlockCopy(System.Array, int, System.Array, int, int)""
IL_0024: ldloc.1
IL_0025: ldc.i4.0
IL_0026: ldelem.u1
IL_0027: call ""void System.Console.WriteLine(bool)""
IL_002c: ldloc.1
IL_002d: ldc.i4.0
IL_002e: ldelem.u1
IL_002f: call ""void System.Console.Write(bool)""
IL_0034: ldloc.1
IL_0035: ldc.i4.0
IL_0036: ldelem.u1
IL_0037: ldc.i4.0
IL_0038: ceq
IL_003a: call ""void System.Console.Write(bool)""
IL_003f: ldloc.1
IL_0040: ldc.i4.0
IL_0041: ldelem.u1
IL_0042: call ""void System.Console.Write(bool)""
IL_0047: ldloc.1
IL_0048: ldc.i4.0
IL_0049: ldelem.u1
IL_004a: ldc.i4.0
IL_004b: ceq
IL_004d: call ""void System.Console.Write(bool)""
IL_0052: ret
}
");
}
[WorkItem(529593, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529593")]
[Fact]
public void FloatToDecimal01()
{
var source = @"
using System;
using System.Globalization;
public class C
{
static void Main()
{
decimal d1 = 1.712m;
decimal d2 = (decimal)1.712f;
decimal d3 = (decimal)1.712;
decimal d4 = (decimal)(double)1.712f;
Console.WriteLine(d1.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(d2.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(d3.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(d4.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(d1 == d2);
Console.WriteLine(d2 == d3);
Console.WriteLine(d3 == d4);
}
}
";
CompileAndVerify(source, expectedOutput:
@"1.712
1.712
1.712
1.71200001239777
True
True
False");
}
[WorkItem(529593, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529593")]
[Fact]
public void FloatToDecimal02()
{
var source =
@"using System;
using System.Globalization;
class C
{
static void Main()
{
WriteLine((decimal)2147483648f);
WriteLine((decimal)2147483648d);
WriteLine((decimal)9.22337203685478e18f);
WriteLine((decimal)9.22337203685478e18d);
WriteLine((decimal)3.96140812571322e28f);
WriteLine((decimal)3.96140812571322e28d);
WriteLine((decimal)3.96140812663555e28f);
WriteLine((decimal)3.96140812663555e28d);
WriteLine((decimal)0.2147483648f);
WriteLine((decimal)0.2147483648d);
WriteLine((decimal)-0.0922337203685478f);
WriteLine((decimal)-0.0922337203685478d);
WriteLine((decimal)-3.96140812571322f);
WriteLine((decimal)-3.96140812571322d);
}
static void WriteLine(decimal d) => Console.WriteLine(d.ToString(CultureInfo.InvariantCulture));
}";
CompileAndVerify(source, expectedOutput:
@"2147484000
2147483648
9223372000000000000
9223372036854780000
39614080000000000000000000000
39614081257132200000000000000
39614080000000000000000000000
39614081266355500000000000000
0.2147484
0.2147483648
-0.09223372
-0.0922337203685478
-3.961408
-3.96140812571322");
}
/// <summary>
/// Dev11 reports CS0030 "Cannot convert type '...' to 'decimal' for
/// float/double constants out of range, even in unchecked code.
/// Roslyn reports CS0221 "Constant value '...' cannot be converted to a
/// 'decimal' ..." in checked code only, and no error in unchecked code.
/// </summary>
[Fact]
public void FloatToDecimal03()
{
var source =
@"using System;
class C
{
static void Main()
{
Console.WriteLine((decimal)-1e30d); // Dev11: CS0030
Console.WriteLine((decimal)1e-30d);
Console.WriteLine((decimal)-2e30f); // Dev11: CS0030
Console.WriteLine((decimal)2e-30f);
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (6,27): error CS0031: Constant value '-1E+30' cannot be converted to a 'decimal'
// Console.WriteLine((decimal)-1e30d); // Dev11: CS0031
Diagnostic(ErrorCode.ERR_ConstOutOfRange, "(decimal)-1e30d").WithArguments("-1E+30", "decimal"),
// (8,27): error CS0031: Constant value '-2E+30' cannot be converted to a 'decimal'
// Console.WriteLine((decimal)-2e30f); // Dev11: CS0031
Diagnostic(ErrorCode.ERR_ConstOutOfRange, "(decimal)-2e30f").WithArguments("-2E+30", "decimal"));
source =
@"using System;
class C
{
static void Main()
{
unchecked
{
Console.WriteLine((decimal)-3e30d); // Dev11: CS0030
Console.WriteLine((decimal)3e-30d);
Console.WriteLine((decimal)-4e30f); // Dev11: CS0030
Console.WriteLine((decimal)4e-30f);
}
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (8,31): error CS0031: Constant value '-3E+30' cannot be converted to a 'decimal'
// Console.WriteLine((decimal)-3e30d); // Dev11: CS0030
Diagnostic(ErrorCode.ERR_ConstOutOfRange, "(decimal)-3e30d").WithArguments("-3E+30", "decimal"),
// (10,31): error CS0031: Constant value '-4E+30' cannot be converted to a 'decimal'
// Console.WriteLine((decimal)-4e30f); // Dev11: CS0030
Diagnostic(ErrorCode.ERR_ConstOutOfRange, "(decimal)-4e30f").WithArguments("-4E+30", "decimal"));
}
[Fact]
[WorkItem(33564, "https://github.com/dotnet/roslyn/issues/33564")]
public void Bug14064()
{
string source = @"
using System;
class C
{
static void Main()
{
const int i = int.MaxValue; // 2,147,483,647
const float x = i; // rounded to 2,147,483,648
float y = i; // rounded to 2,147,483,648
double z = i; // 2,147,483,647
Test(x == y); // t
Test(x == z); // f
Test(y == z); // f
}
private static void Test(bool b) { Console.Write(b ? 't' : 'f'); }
}
";
string expectedOutput = "tff";
string expectedIL = @"{
// Code size 57 (0x39)
.maxstack 2
.locals init (float V_0, //y
double V_1) //z
IL_0000: ldc.r4 2.147484E+09
IL_0005: stloc.0
IL_0006: ldc.r8 2147483647
IL_000f: stloc.1
IL_0010: ldc.r4 2.147484E+09
IL_0015: ldloc.0
IL_0016: ceq
IL_0018: call ""void C.Test(bool)""
IL_001d: ldc.r8 2147483648
IL_0026: ldloc.1
IL_0027: ceq
IL_0029: call ""void C.Test(bool)""
IL_002e: ldloc.0
IL_002f: conv.r8
IL_0030: ldloc.1
IL_0031: ceq
IL_0033: call ""void C.Test(bool)""
IL_0038: ret
}";
var compilation = CompileAndVerify(source, expectedOutput: expectedOutput);
compilation.VerifyIL("C.Main", expectedIL);
}
[WorkItem(545862, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545862")]
[Fact]
public void TestPropertyAndTypeWithSameNameInDelegateInstantiation()
{
string source = @"
delegate void A();
class B
{
public void M() { System.Console.WriteLine(123); }
}
class C
{
B B { get { return new B(); } }
A R()
{
return new A(B.M);
}
static void Main()
{
(new C()).R()();
}
}";
string expectedOutput = "123";
string expectedIL = @"{
// Code size 18 (0x12)
.maxstack 2
IL_0000: ldarg.0
IL_0001: call ""B C.B.get""
IL_0006: ldftn ""void B.M()""
IL_000c: newobj ""A..ctor(object, System.IntPtr)""
IL_0011: ret
}";
var compilation = CompileAndVerify(source, expectedOutput: expectedOutput);
compilation.VerifyIL("C.R", expectedIL);
}
[WorkItem(545778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545778")]
[Fact]
public void FormattingCharactersInName1()
{
var source = @"
enum " + "\u0915\u094d\u200d\u0937" + @"
{
A
}
";
System.Action<ModuleSymbol> validator = module =>
{
var type = module.GlobalNamespace.GetMember<NamedTypeSymbol>("\u0915\u094d\u0937"); //formatting char removed
Assert.True(type.CanBeReferencedByName);
};
CompileAndVerify(source, sourceSymbolValidator: validator, symbolValidator: validator);
}
[WorkItem(545778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545778")]
[Fact]
public void FormattingCharactersInName2()
{
var il = @"
.class public auto ansi sealed E
extends [mscorlib]System.Enum
{
.field public specialname rtspecialname int32 value__
.field public static literal valuetype E '" + "\u0915\u094d\u200d\u0937" + @"' = int32(0x00000000)
} // end of class E
";
var comp = CreateCompilationWithILAndMscorlib40("", il);
var @enum = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("E");
var field = @enum.GetMembers().OfType<FieldSymbol>().Single();
Assert.False(field.CanBeReferencedByName);
}
[WorkItem(545716, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545716")]
[Fact]
public void Regress14344()
{
string source = @"
class EdmFunction
{
private static void SetFunctionAttribute(ref FunctionAttributes field, FunctionAttributes attribute)
{
field ^= field & attribute;
}
}
enum FunctionAttributes : byte
{
None = 0,
Aggregate = 1,
}
";
CompileAndVerify(source).VerifyIL("EdmFunction.SetFunctionAttribute", @"
{
// Code size 10 (0xa)
.maxstack 4
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldind.u1
IL_0003: ldarg.0
IL_0004: ldind.u1
IL_0005: ldarg.1
IL_0006: and
IL_0007: xor
IL_0008: stind.i1
IL_0009: ret
}
");
}
[Fact]
public void SacrificialReadElement()
{
string source = @"
using System;
class Program
{
static void Main()
{
var x = new Guid[10];
if (x[1] is Guid)
{
Console.WriteLine(""hello"");
}
Test<Guid>(5);
}
private static void Test<T>(int i) where T:struct
{
T[] x = new T[10];
if (x[i] is T)
{
Console.WriteLine(""hello"");
}
}
}
";
CompileAndVerify(source, expectedOutput: @"hello
hello").VerifyIL("Program.Main", @"
{
// Code size 31 (0x1f)
.maxstack 2
IL_0000: ldc.i4.s 10
IL_0002: newarr ""System.Guid""
IL_0007: ldc.i4.1
IL_0008: ldelema ""System.Guid""
IL_000d: pop
IL_000e: ldstr ""hello""
IL_0013: call ""void System.Console.WriteLine(string)""
IL_0018: ldc.i4.5
IL_0019: call ""void Program.Test<System.Guid>(int)""
IL_001e: ret
}
").VerifyIL("Program.Test<T>", @"
{
// Code size 27 (0x1b)
.maxstack 2
IL_0000: ldc.i4.s 10
IL_0002: newarr ""T""
IL_0007: ldarg.0
IL_0008: readonly.
IL_000a: ldelema ""T""
IL_000f: pop
IL_0010: ldstr ""hello""
IL_0015: call ""void System.Console.WriteLine(string)""
IL_001a: ret
}
");
}
[Fact]
public void Regress15667()
{
string source = @"
class Program
{
static void Main(string[] args)
{
bool b;
int s = (b = false) ? 5 : 100; // Warning
int s1 = (b = false) ? 5 : 100; // Warning
System.Console.WriteLine(s1);
}
}
";
string expectedOutput = "100";
string expectedIL = @"
{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldc.i4.s 100
IL_0002: call ""void System.Console.WriteLine(int)""
IL_0007: ret
}";
var compilation = CompileAndVerify(source, expectedOutput: expectedOutput);
compilation.VerifyIL("Program.Main", expectedIL);
}
[Fact(), WorkItem(546860, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546860")]
public void Bug17007()
{
CompileAndVerify(
@"
class Module1
{
static void Main()
{
System.Console.WriteLine(Test1(100));
}
static int Test1(int x)
{
return Test2(x,checked(-x));
}
static int Test2(int x, int y)
{
return y;
}
}", options: TestOptions.ReleaseExe,
expectedOutput: "-100");
}
/// <summary>
/// Diagnostics from other methods should be ignored
/// when compiling and emitting synthesized methods.
/// </summary>
[WorkItem(546867, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546867")]
[Fact]
public void IgnoreOtherDiagnosticsCompilingSynthesizedMethods()
{
var source =
@"class C
{
static object F = new object(); // generate .cctor
static System.Action M()
{
return () => { }; // generate lambda
}
}";
var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll.WithConcurrentBuild(false));
var options = compilation.Options;
var diagnostics = BindingDiagnosticBag.GetInstance(withDiagnostics: true, withDependencies: false);
var assembly = (SourceAssemblySymbol)compilation.Assembly;
var module = new PEAssemblyBuilder(
assembly,
EmitOptions.Default,
options.OutputKind,
GetDefaultModulePropertiesForSerialization(),
new ResourceDescription[0]);
var methodBodyCompiler = new MethodCompiler(
compilation: compilation,
moduleBeingBuiltOpt: module,
emittingPdb: false,
hasDeclarationErrors: false,
emitMethodBodies: true,
diagnostics: diagnostics,
filterOpt: null,
entryPointOpt: null,
cancellationToken: CancellationToken.None);
// Add diagnostic to MethodBodyCompiler bag, as if
// code gen for an earlier method had generated an error.
diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_IntDivByZero), NoLocation.Singleton));
// Compile all methods for type including synthesized methods.
var type = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
methodBodyCompiler.Visit(type);
Assert.Equal(1, diagnostics.DiagnosticBag.AsEnumerable().Count());
diagnostics.Free();
}
[ConditionalFact(typeof(DesktopOnly))]
[WorkItem(546957, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546957")]
public void Bug17352_VarArgCtor()
{
string source = @"
using System;
class A
{
public static void Main()
{
TestVarArgs instTestVarArgs = new TestVarArgs(__arglist());
TestVarArgs instTestVarArgs1 = new TestVarArgs(__arglist(2, ""blah"", null, 2.2));
}
public class TestVarArgs
{
public TestVarArgs(__arglist)
{
Console.WriteLine(""Inside - TestVarArgs::ctor (__arglist)"");
PrintArgList(new ArgIterator(__arglist));
}
private void PrintArgList(ArgIterator args)
{
int argCount = args.GetRemainingCount();
Object[] objArgs = new Object[argCount];
//Walk all of the args in the variable part of the argument list.
for (int i = 1; args.GetRemainingCount() > 0 && i < argCount; i++)
{
TypedReference tr = args.GetNextArg();
objArgs[i] = TypedReference.ToObject(tr);
if (objArgs[i] != null)
{
Console.WriteLine(objArgs[i].GetType());
Console.WriteLine(objArgs[i]);
}
}
}
}
}
";
var compilation = CompileAndVerify(
source,
expectedOutput: @"Inside - TestVarArgs::ctor (__arglist)
Inside - TestVarArgs::ctor (__arglist)
System.Int32
2
System.String
blah");
compilation.VerifyIL("A.Main",
@"
{
// Code size 29 (0x1d)
.maxstack 4
IL_0000: newobj ""A.TestVarArgs..ctor(__arglist)""
IL_0005: pop
IL_0006: ldc.i4.2
IL_0007: ldstr ""blah""
IL_000c: ldnull
IL_000d: ldc.r8 2.2
IL_0016: newobj ""A.TestVarArgs..ctor(__arglist) with __arglist( int, string, object, double)""
IL_001b: pop
IL_001c: ret
}
");
}
[WorkItem(24348, "https://github.com/dotnet/roslyn/issues/24348")]
[ConditionalFact(typeof(DesktopOnly))]
public void VarargBridgeSource()
{
var code = @"
public class VarArgs
{
public void Invoke(__arglist)
{
var ai = new System.ArgIterator(__arglist);
System.Console.WriteLine(ai.GetRemainingCount());
}
}
interface IVarArgs
{
void Invoke(__arglist);
}
class MyVarArgs : VarArgs, IVarArgs
{
}
public static class P
{
public static void Main()
{
IVarArgs iv = new MyVarArgs();
iv.Invoke(__arglist(1, 2, 3, 4));
}
}
";
var compilation = CompileAndVerifyWithMscorlib40(code, expectedOutput: "4");
}
[WorkItem(26113, "https://github.com/dotnet/roslyn/issues/26113")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.TestExecutionNeedsWindowsTypes)]
public void VarargByRef()
{
var code = @"
using System;
class A
{
static void Test(__arglist)
{
var args = new ArgIterator(__arglist);
ref int a = ref __refvalue(args.GetNextArg(), int);
a = 5;
}
static void Main()
{
int a = 0;
Test(__arglist(ref a));
Console.WriteLine(a);
}
}
";
var comp = CompileAndVerify(code, expectedOutput: "5", options: TestOptions.DebugExe);
comp.VerifyIL("A.Main",
@"
{
// Code size 19 (0x13)
.maxstack 1
.locals init (int V_0) //a
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldloca.s V_0
IL_0005: call ""void A.Test(__arglist) with __arglist( ref int)""
IL_000a: nop
IL_000b: ldloc.0
IL_000c: call ""void System.Console.WriteLine(int)""
IL_0011: nop
IL_0012: ret
}
");
comp = CompileAndVerify(code, expectedOutput: "5", options: TestOptions.ReleaseExe);
comp.VerifyIL("A.Main",
@"
{
// Code size 16 (0x10)
.maxstack 1
.locals init (int V_0) //a
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: call ""void A.Test(__arglist) with __arglist( ref int)""
IL_0009: ldloc.0
IL_000a: call ""void System.Console.WriteLine(int)""
IL_000f: ret
}
");
}
[WorkItem(24348, "https://github.com/dotnet/roslyn/issues/24348")]
[ConditionalFact(typeof(DesktopOnly))]
public void VarargBridgeMeta()
{
var reference = CreateCompilation(@"
public class VarArgs
{
public void Invoke(__arglist)
{
var ai = new System.ArgIterator(__arglist);
System.Console.WriteLine(ai.GetRemainingCount());
}
}");
var code = @"
interface IVarArgs
{
void Invoke(__arglist);
}
class MyVarArgs : VarArgs, IVarArgs
{
}
public static class P
{
public static void Main()
{
IVarArgs iv = new MyVarArgs();
iv.Invoke(__arglist(1, 2, 3, 4));
}
}
";
var comp = CreateCompilation(code, references: new[] { reference.ToMetadataReference() });
comp.VerifyDiagnostics(
// (7,28): error CS0630: 'VarArgs.Invoke(__arglist)' cannot implement interface member 'IVarArgs.Invoke(__arglist)' in type 'MyVarArgs' because it has an __arglist parameter.
// class MyVarArgs : VarArgs, IVarArgs
Diagnostic(ErrorCode.ERR_InterfaceImplementedImplicitlyByVariadic, "IVarArgs").WithArguments("VarArgs.Invoke(__arglist)", "IVarArgs.Invoke(__arglist)", "MyVarArgs").WithLocation(7, 28)
);
comp = CreateCompilation(code, references: new[] { reference.EmitToImageReference() });
comp.VerifyDiagnostics(
// (7,28): error CS0630: 'VarArgs.Invoke(__arglist)' cannot implement interface member 'IVarArgs.Invoke(__arglist)' in type 'MyVarArgs' because it has an __arglist parameter.
// class MyVarArgs : VarArgs, IVarArgs
Diagnostic(ErrorCode.ERR_InterfaceImplementedImplicitlyByVariadic, "IVarArgs").WithArguments("VarArgs.Invoke(__arglist)", "IVarArgs.Invoke(__arglist)", "MyVarArgs").WithLocation(7, 28)
);
}
[WorkItem(24348, "https://github.com/dotnet/roslyn/issues/24348")]
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void VarargBridgeSourceModopt()
{
var il = @"
.class interface public auto ansi abstract IVarArgs
{
// Methods
.method public hidebysig newslot abstract virtual
instance vararg int32 modopt(int64) Invoke () cil managed
{
} // end of method IVarArgs::Invoke
} // end of class IVarArgs
";
var reference = CompileIL(il);
var code = @"
public class VarArgs
{
public int Invoke(__arglist) => throw null;
}
class MyVarArgs : VarArgs, IVarArgs
{
}
class MyVarArgs2 : IVarArgs
{
public int Invoke(__arglist) => throw null;
}
class MyVarArgs3 : IVarArgs
{
// this is ok, modifiers are copied
int IVarArgs.Invoke(__arglist) => throw null;
}
public static class P
{
public static void Main()
{
IVarArgs iv = new MyVarArgs3();
iv.Invoke(__arglist(1, 2, 3, 4));
}
}
";
var comp = CreateCompilation(code, references: new[] { reference });
comp.VerifyDiagnostics(
// (15,16): error CS0630: 'MyVarArgs2.Invoke(__arglist)' cannot implement interface member 'IVarArgs.Invoke(__arglist)' in type 'MyVarArgs2' because it has an __arglist parameter
// public int Invoke(__arglist) => throw null;
Diagnostic(ErrorCode.ERR_InterfaceImplementedImplicitlyByVariadic, "Invoke").WithArguments("MyVarArgs2.Invoke(__arglist)", "IVarArgs.Invoke(__arglist)", "MyVarArgs2").WithLocation(15, 16),
// (8,28): error CS0630: 'VarArgs.Invoke(__arglist)' cannot implement interface member 'IVarArgs.Invoke(__arglist)' in type 'MyVarArgs' because it has an __arglist parameter
// class MyVarArgs : VarArgs, IVarArgs
Diagnostic(ErrorCode.ERR_InterfaceImplementedImplicitlyByVariadic, "IVarArgs").WithArguments("VarArgs.Invoke(__arglist)", "IVarArgs.Invoke(__arglist)", "MyVarArgs").WithLocation(8, 28)
);
}
[WorkItem(530067, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530067")]
[Fact]
public void NopAfterCall()
{
// For a nop to be inserted after a call, three conditions must be met:
// 1) void return
// 2) debug build
var source = @"
class C
{
static void Main()
{
Void();
NonVoid();
}
static void Void() { }
static int NonVoid() { return 1; }
}
";
var compRelease = CreateCompilation(source, options: TestOptions.ReleaseExe);
var compDebug = CreateCompilation(source, options: TestOptions.DebugExe);
// (2) is not met.
CompileAndVerify(compRelease).VerifyIL("C.Main", @"
{
// Code size 12 (0xc)
.maxstack 1
IL_0000: call ""void C.Void()""
IL_0005: call ""int C.NonVoid()""
IL_000a: pop
IL_000b: ret
}");
// Void meets (1), but NonVoid does not (it doesn't need a nop since it has a pop).
CompileAndVerify(compDebug).VerifyIL("C.Main", @"
{
// Code size 14 (0xe)
.maxstack 1
IL_0000: nop
IL_0001: call ""void C.Void()""
IL_0006: nop
IL_0007: call ""int C.NonVoid()""
IL_000c: pop
IL_000d: ret
}");
}
[WorkItem(530067, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530067")]
[Fact]
public void NopAfterCall_ForLoop()
{
var source = @"
class C
{
static void Main()
{
for (int i = 0; i < 10; System.Diagnostics.Debugger.Break())
{
}
}
}
";
// Nop after Debugger.Break(), even though it isn't at the end of a statement.
var comp = CreateCompilation(source, options: TestOptions.DebugExe);
var v = CompileAndVerify(comp);
v.VerifyIL("C.Main", @"
{
// Code size 23 (0x17)
.maxstack 2
.locals init (int V_0, //i
bool V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_000d
IL_0005: nop
IL_0006: nop
IL_0007: call ""void System.Diagnostics.Debugger.Break()""
IL_000c: nop
IL_000d: ldloc.0
IL_000e: ldc.i4.s 10
IL_0010: clt
IL_0012: stloc.1
IL_0013: ldloc.1
IL_0014: brtrue.s IL_0005
IL_0016: ret
}");
}
[Fact]
public void CallOnFildInStruct()
{
var source = @"
using System;
class Program
{
static void Main(string[] args)
{
S1 s = new S1(new C1());
Console.Write(s.Prop1);
}
}
struct S1
{
public readonly C1 c;
public S1(C1 c)
{
this.c = c;
}
public int Prop1
{
get
{
return c.s.Length;
}
}
}
public class C1
{
public string s = ""hi"";
}
";
CompileAndVerify(source, expectedOutput: "2").VerifyIL("S1.Prop1.get", @"
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ldfld ""C1 S1.c""
IL_0006: ldfld ""string C1.s""
IL_000b: callvirt ""int string.Length.get""
IL_0010: ret
}
");
}
[Fact]
public void ReferenceEqualsIntrinsic()
{
var source = @"
using System;
public class Program
{
static void Main()
{
object a = ""hi"";
Exception b = null;
// brtrue/brinst equivalence
// if (a)
if (!ReferenceEquals(a, null))
{
Console.Write('1');
}
// trivial Eq
// unconditional
if (ReferenceEquals(null, null))
{
Console.Write('2');
}
// demorgan's
// if (a || b)
if (!(ReferenceEquals(a, null) && ReferenceEquals(b, null)))
{
Console.Write('3');
}
// conversions
if (!(ReferenceEquals(1, (int?)null)))
{
Console.Write('4');
}
}
}
";
CompileAndVerify(source, expectedOutput: "1234").VerifyIL("Program.Main", @"
{
// Code size 52 (0x34)
.maxstack 2
.locals init (System.Exception V_0) //b
IL_0000: ldstr ""hi""
IL_0005: ldnull
IL_0006: stloc.0
IL_0007: dup
IL_0008: brfalse.s IL_0011
IL_000a: ldc.i4.s 49
IL_000c: call ""void System.Console.Write(char)""
IL_0011: ldc.i4.s 50
IL_0013: call ""void System.Console.Write(char)""
IL_0018: brtrue.s IL_001d
IL_001a: ldloc.0
IL_001b: brfalse.s IL_0024
IL_001d: ldc.i4.s 51
IL_001f: call ""void System.Console.Write(char)""
IL_0024: ldc.i4.1
IL_0025: box ""int""
IL_002a: brfalse.s IL_0033
IL_002c: ldc.i4.s 52
IL_002e: call ""void System.Console.Write(char)""
IL_0033: ret
}");
}
[WorkItem(598029, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/598029")]
[Fact]
public void TypeParameterInterfaceVersusNonInterface1()
{
var source = @"
using System;
class Program
{
static void Main()
{
Test(new D());
}
static void Test<U>(U u) where U : C, IGoo
{
Console.WriteLine(u.ToString());
}
}
interface IGoo
{
string ToString();
}
class C
{
public override string ToString()
{
return ""C"";
}
}
class D : C, IGoo
{
public override string ToString()
{
return ""D"";
}
string IGoo.ToString()
{
return ""IGoo"";
}
}
";
// We will have IGoo.ToString and C.ToString (which is an override of object.ToString)
// in the candidate set. Does the rule apply to eliminate all interface methods? NO. The
// rule only applies if the candidate set contains a method which originally came from a
// class type other than object. The method C.ToString is the "slot" for
// object.ToString, so this counts as coming from object. M should call the explicit
// interface implementation.
CompileAndVerify(source, expectedOutput: "IGoo");
}
// Same as above, but C.ToString is "new virtual", rather than "override".
[WorkItem(598029, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/598029")]
[Fact]
public void TypeParameterInterfaceVersusNonInterface2()
{
var source = @"
using System;
class Program
{
static void Main()
{
Test(new D());
}
static void Test<U>(U u) where U : C, IGoo
{
Console.WriteLine(u.ToString());
}
}
interface IGoo
{
string ToString();
}
class C
{
public new virtual string ToString()
{
return ""C"";
}
}
class D : C, IGoo
{
public override string ToString()
{
return ""D"";
}
string IGoo.ToString()
{
return ""IGoo"";
}
}
";
// The candidate set contains a method ToString which comes from a class type other
// than object. The interface method should be eliminated and M should call virtual
// method C.ToString().
CompileAndVerify(source, expectedOutput: "D");
}
[WorkItem(638119, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/638119")]
[Fact]
public void ArrayInitZero()
{
string source = @"
using System;
class Test
{
static void Main()
{
System.Globalization.CultureInfo saveUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
try
{
Run();
}
finally
{
System.Threading.Thread.CurrentThread.CurrentUICulture = saveUICulture;
}
}
static void Run()
{
// no element inits
bool[] arrB1 = new bool[] {false, false, false};
System.Console.WriteLine(arrB1[0]);
// no element inits
Exception[] arrE1 = new Exception[] {null, null, null};
System.Console.WriteLine(arrE1[0]);
// 1 element init
bool[] arrB2 = new bool[] {false, true, false};
System.Console.WriteLine(arrB2[1]);
// 1 element init
Exception[] arrE2 = new Exception[] {null, new Exception(), null};
System.Console.WriteLine(arrE2[1]);
// blob init
bool[] arrB3 = new bool[] {true, false, true, true};
System.Console.WriteLine(arrB3[2]);
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseExe.WithModuleName("MODULE"), expectedOutput: @"False
True
System.Exception: Exception of type 'System.Exception' was thrown.
True");
compilation.VerifyIL("Test.Run",
@"{
// Code size 89 (0x59)
.maxstack 4
IL_0000: ldc.i4.3
IL_0001: newarr ""bool""
IL_0006: ldc.i4.0
IL_0007: ldelem.u1
IL_0008: call ""void System.Console.WriteLine(bool)""
IL_000d: ldc.i4.3
IL_000e: newarr ""System.Exception""
IL_0013: ldc.i4.0
IL_0014: ldelem.ref
IL_0015: call ""void System.Console.WriteLine(object)""
IL_001a: ldc.i4.3
IL_001b: newarr ""bool""
IL_0020: dup
IL_0021: ldc.i4.1
IL_0022: ldc.i4.1
IL_0023: stelem.i1
IL_0024: ldc.i4.1
IL_0025: ldelem.u1
IL_0026: call ""void System.Console.WriteLine(bool)""
IL_002b: ldc.i4.3
IL_002c: newarr ""System.Exception""
IL_0031: dup
IL_0032: ldc.i4.1
IL_0033: newobj ""System.Exception..ctor()""
IL_0038: stelem.ref
IL_0039: ldc.i4.1
IL_003a: ldelem.ref
IL_003b: call ""void System.Console.WriteLine(object)""
IL_0040: ldc.i4.4
IL_0041: newarr ""bool""
IL_0046: dup
IL_0047: ldtoken ""int <PrivateImplementationDetails>.52A5C4A10657220CAC05C63ADFA923C7771C55D868A58EE360EB3D1511985C3E""
IL_004c: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)""
IL_0051: ldc.i4.2
IL_0052: ldelem.u1
IL_0053: call ""void System.Console.WriteLine(bool)""
IL_0058: ret
}
");
}
[WorkItem(1043494, "DevDiv")]
[Fact]
public void NegativeZeroIsNotAZero()
{
var source = @"
class A
{
static int Main()
{
double[] dArr = { -0.0 };
double d = -0.0;
// Invariant: x / -0 => -infinity
if (System.Double.IsNegativeInfinity(2.0 / dArr[0]) != System.Double.IsNegativeInfinity(2.0 / d))
{
System.Console.WriteLine(""Failed test at test 1"");
return 1;
}
if (System.Double.IsNegativeInfinity(2.0 / new double[] { -0.0 }[0]) != System.Double.IsNegativeInfinity(2.0 / d))
{
System.Console.WriteLine(""Failed test at test 2"");
return 1;
}
// all tests pass
return 0;
}
}
";
CompileAndVerify(source, expectedOutput: @"").VerifyIL("A.Main",
@"
{
// Code size 144 (0x90)
.maxstack 5
.locals init (double[] V_0, //dArr
double V_1) //d
IL_0000: ldc.i4.1
IL_0001: newarr ""double""
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.r8 -0.0
IL_0011: stelem.r8
IL_0012: stloc.0
IL_0013: ldc.r8 -0.0
IL_001c: stloc.1
IL_001d: ldc.r8 2
IL_0026: ldloc.0
IL_0027: ldc.i4.0
IL_0028: ldelem.r8
IL_0029: div
IL_002a: call ""bool double.IsNegativeInfinity(double)""
IL_002f: ldc.r8 2
IL_0038: ldloc.1
IL_0039: div
IL_003a: call ""bool double.IsNegativeInfinity(double)""
IL_003f: beq.s IL_004d
IL_0041: ldstr ""Failed test at test 1""
IL_0046: call ""void System.Console.WriteLine(string)""
IL_004b: ldc.i4.1
IL_004c: ret
IL_004d: ldc.r8 2
IL_0056: ldc.i4.1
IL_0057: newarr ""double""
IL_005c: dup
IL_005d: ldc.i4.0
IL_005e: ldc.r8 -0.0
IL_0067: stelem.r8
IL_0068: ldc.i4.0
IL_0069: ldelem.r8
IL_006a: div
IL_006b: call ""bool double.IsNegativeInfinity(double)""
IL_0070: ldc.r8 2
IL_0079: ldloc.1
IL_007a: div
IL_007b: call ""bool double.IsNegativeInfinity(double)""
IL_0080: beq.s IL_008e
IL_0082: ldstr ""Failed test at test 2""
IL_0087: call ""void System.Console.WriteLine(string)""
IL_008c: ldc.i4.1
IL_008d: ret
IL_008e: ldc.i4.0
IL_008f: ret
}
");
}
[WorkItem(1043494, "DevDiv")]
[Fact]
public void NegativeZeroIsNotAZero1()
{
var source = @"
using System;
class Program
{
static void Main(string[] args)
{
var x = new double[] { -0.0, -0.0, -0.0, -0.0, -0.0, };
var y = new float[] { -0.0f, -0.0f, -0.0f, -0.0f, -0.0f, };
var z = new decimal[] { -(decimal.Zero), -(decimal.Zero), -(decimal.Zero), -(decimal.Zero), -(decimal.Zero), };
// false
Console.WriteLine(IsZero(x[0]));
// false
Console.WriteLine(IsZero(y[0]));
// true (I do not know how to get '-0' constant)
Console.WriteLine(IsZero(z[0]));
x = new double[] { -0.0 };
y = new float[] { -0.0f };
z = new decimal[] { -(decimal.Zero) };
// false
Console.WriteLine(IsZero(x[0]));
// false
Console.WriteLine(IsZero(y[0]));
// true (I do not know how to get '-0' constant)
Console.WriteLine(IsZero(z[0]));
}
private static bool IsZero(double x)
{
return x == 0 && 1 / x > 0;
}
private static bool IsZero(float x)
{
return x == 0 && 1 / x > 0;
}
private static bool IsZero(decimal x)
{
var bits = decimal.GetBits(x);
foreach (int part in bits)
{
if (part != 0)
{
return false;
}
}
return true;
}
}
";
CompileAndVerify(source, expectedOutput: @"False
False
True
False
False
True");
}
[Fact, WorkItem(649805, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/649805")]
public void Repro649805()
{
var source = @"
public class Goo
{
public static void Method(string s)
{
if (s == ""abc"") Test.Result++;
}
public string Prop { get; set; }
}
public class Test
{
public Goo Goo { get; set; }
public static void DoExample(dynamic d)
{
Goo.Method(d.Prop);
}
public static int Result = -1;
static void Main()
{
try
{
DoExample(new Goo() { Prop = ""abc"" });
}
catch (System.Exception)
{
Test.Result--;
}
System.Console.WriteLine(Test.Result);
}
}
";
CompileAndVerifyWithMscorlib40(source, references: new[] { SystemCoreRef, CSharpRef }, expectedOutput: @"0");
}
[WorkItem(653588, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/653588")]
[Fact]
public void SelfAssignStructCallTarget()
{
var source = @"
struct S1
{
public int field;
public S1(int v)
{
this.field = v;
}
public void Goo()
{
System.Console.WriteLine(field.ToString());
}
}
class A
{
static void Main(string[] args)
{
S1 s = new S1();
(s = s).Goo();
S1 s1 = new S1(42);
(s1 = s1).Goo();
}
}
";
CompileAndVerify(source, expectedOutput: @"0
42").VerifyIL("A.Main", @"
{
// Code size 40 (0x28)
.maxstack 2
.locals init (S1 V_0, //s
S1 V_1, //s1
S1 V_2)
IL_0000: ldloca.s V_0
IL_0002: initobj ""S1""
IL_0008: ldloc.0
IL_0009: dup
IL_000a: stloc.0
IL_000b: stloc.2
IL_000c: ldloca.s V_2
IL_000e: call ""void S1.Goo()""
IL_0013: ldloca.s V_1
IL_0015: ldc.i4.s 42
IL_0017: call ""S1..ctor(int)""
IL_001c: ldloc.1
IL_001d: dup
IL_001e: stloc.1
IL_001f: stloc.2
IL_0020: ldloca.s V_2
IL_0022: call ""void S1.Goo()""
IL_0027: ret
}
");
}
[WorkItem(653588, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/653588")]
[Fact]
public void UnusedStructFieldLoad()
{
var source = @"
struct S1
{
public int field;
public S1(int v)
{
this.field = v;
}
public void Goo()
{
System.Console.WriteLine(field.ToString());
}
}
class A
{
static void Main(string[] args)
{
var x = (new S1()).field;
var y = (new S1(42)).field;
}
}
";
CompileAndVerify(source, expectedOutput: @"").VerifyIL("A.Main",
@"
{
// Code size 9 (0x9)
.maxstack 1
IL_0000: ldc.i4.s 42
IL_0002: newobj ""S1..ctor(int)""
IL_0007: pop
IL_0008: ret
}
");
}
[WorkItem(665317, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/665317")]
[Fact]
public void InitGenericElement()
{
var source = @"
using System;
class A { }
class B : A { }
class Program
{
static void Goo<T>(T[] array) where T : class
{
array[0] = null;
}
static void Goo1<T>(T[] array) where T : struct
{
array[0] = default(T);
}
static void Bar<T>(T[] array)
{
array[0] = default(T);
}
static void Baz<T>(T[][] array)
{
array[0] = default(T[]);
}
static void Main(string[] args)
{
A[] array = new B[5];
Goo<A>(array);
Bar<A>(array);
A[][] array1 = new B[5][];
Baz<A>(array1);
}
}
";
CompileAndVerify(source, expectedOutput: @""
).VerifyIL("Program.Goo<T>(T[])",
@"
{
// Code size 17 (0x11)
.maxstack 3
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldloca.s V_0
IL_0004: initobj ""T""
IL_000a: ldloc.0
IL_000b: stelem ""T""
IL_0010: ret
}
").VerifyIL("Program.Goo1<T>(T[])",
@"
{
// Code size 14 (0xe)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""T""
IL_0007: initobj ""T""
IL_000d: ret
}
").VerifyIL("Program.Bar<T>(T[])",
@"
{
// Code size 17 (0x11)
.maxstack 3
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldloca.s V_0
IL_0004: initobj ""T""
IL_000a: ldloc.0
IL_000b: stelem ""T""
IL_0010: ret
}
").VerifyIL("Program.Baz<T>(T[][])",
@"
{
// Code size 5 (0x5)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldnull
IL_0003: stelem.ref
IL_0004: ret
}
");
}
[Fact]
public void InitGenericVolatileField()
{
var source = @"
using System;
class A<T> where T: class
{
public T field;
public volatile T vField;
}
class Program
{
static void Goo<T>(A<T> v) where T : class
{
v.field = null;
v.field = default(T);
v.vField = null;
v.vField = default(T);
}
static void Main(string[] args)
{
}
}
";
CompileAndVerify(source, expectedOutput: @""
).VerifyIL("Program.Goo<T>(A<T>)",
@"
{
// Code size 59 (0x3b)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldflda ""T A<T>.field""
IL_0006: initobj ""T""
IL_000c: ldarg.0
IL_000d: ldflda ""T A<T>.field""
IL_0012: initobj ""T""
IL_0018: ldarg.0
IL_0019: ldloca.s V_0
IL_001b: initobj ""T""
IL_0021: ldloc.0
IL_0022: volatile.
IL_0024: stfld ""T A<T>.vField""
IL_0029: ldarg.0
IL_002a: ldloca.s V_0
IL_002c: initobj ""T""
IL_0032: ldloc.0
IL_0033: volatile.
IL_0035: stfld ""T A<T>.vField""
IL_003a: ret
}
");
}
[Fact]
public void CallFinalMethodOnTypeParam()
{
var source = @"
using System;
class Program
{
static void Main(string[] args)
{
Test1(new cls1());
Test1(new cls2());
Test2(new cls2());
}
static void Test1<T>(T arg) where T : cls1
{
arg.Goo();
}
static void Test2<T>(T arg) where T : cls2
{
arg.Goo();
}
}
interface i1
{
void Goo();
}
class cls1 : i1
{
public void Goo()
{
System.Console.Write(""Goo"");
}
}
class cls2 : cls1
{
}
";
CompileAndVerify(source, expectedOutput: @"GooGooGoo").
VerifyIL("Program.Test1<T>(T)",
@"
{
// Code size 12 (0xc)
.maxstack 1
IL_0000: ldarg.0
IL_0001: box ""T""
IL_0006: callvirt ""void cls1.Goo()""
IL_000b: ret
}
").
VerifyIL("Program.Test2<T>(T)",
@"
{
// Code size 12 (0xc)
.maxstack 1
IL_0000: ldarg.0
IL_0001: box ""T""
IL_0006: callvirt ""void cls1.Goo()""
IL_000b: ret
}
");
}
[WorkItem(797996, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/797996")]
[Fact]
public void MissingMember_System_String__op_Equality()
{
var text =
@"namespace System
{
public class Object { }
public struct Void { }
public class ValueType { }
public struct Int32 { }
public struct Nullable<T> { }
public class String { }
}
class C
{
static void M(string s)
{
switch (s) { case ""A"": break; case ""B"": break; }
}
}";
var compilation = CreateEmptyCompilation(text, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute());
compilation.VerifyDiagnostics();
using (var stream = new MemoryStream())
{
var result = compilation.Emit(stream);
result.Diagnostics.Verify(
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1),
// (14,27): error CS0656: Missing compiler required member 'System.String.op_Equality'
// switch (s) { case "A": break; case "B": break; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"""A""").WithArguments("System.String", "op_Equality").WithLocation(14, 27)
);
}
}
[WorkItem(797996, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/797996")]
[Fact]
public void MissingMember_System_Type__GetTypeFromHandle()
{
var text =
@"namespace System
{
public class Object { }
public struct Void { }
public class ValueType { }
public struct Int32 { }
public struct Nullable<T> { }
public class Type { }
public class TypedReference { }
}
class C
{
static object F = typeof(C);
}";
var compilation = CreateEmptyCompilation(text, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute());
compilation.VerifyDiagnostics();
using (var stream = new MemoryStream())
{
var result = compilation.Emit(stream);
result.Diagnostics.Verify(
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion),
// (13,23): error CS0656: Missing compiler required member 'System.Type.GetTypeFromHandle'
// static object F = typeof(C);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "typeof(C)").WithArguments("System.Type", "GetTypeFromHandle").WithLocation(13, 23));
}
}
[WorkItem(797996, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/797996")]
[Fact]
public void MissingMember_System_Type__GetTypeFromHandle_2()
{
var text =
@"namespace System
{
public class Object { }
public struct Void { }
public class ValueType { }
public struct Int32 { }
public struct Nullable<T> { }
public class Type { }
public class TypedReference { }
}
class C
{
static object F(object o)
{
return __reftype(__makeref(o));
}
}";
var compilation = CreateEmptyCompilation(text, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute());
compilation.VerifyDiagnostics();
using (var stream = new MemoryStream())
{
var result = compilation.Emit(stream);
result.Diagnostics.Verify(
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion),
// (15,16): error CS0656: Missing compiler required member 'System.Type.GetTypeFromHandle'
// return __reftype(__makeref(o));
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "__reftype(__makeref(o))").WithArguments("System.Type", "GetTypeFromHandle").WithLocation(15, 16));
}
// Similar to above but with mscorlib.
text =
@"class C
{
static object F(object o)
{
return __reftype(__makeref(o));
}
}";
compilation = CreateCompilation(text);
compilation.VerifyDiagnostics();
using (var stream = new MemoryStream())
{
var result = compilation.Emit(stream);
Assert.True(result.Success);
result.Diagnostics.Verify();
}
}
[Fact]
public void Regress530041()
{
var source = @"
using System;
public static class Test
{
public static void Main()
{
if (SomeExpression()) return;
}
private static bool SomeExpression()
{
return true;
}
}
";
CompileAndVerify(source, expectedOutput: @""
).VerifyIL("Test.Main()",
@"
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: call ""bool Test.SomeExpression()""
IL_0005: pop
IL_0006: ret
}
");
}
[Fact]
public void Regress530041_1()
{
var source = @"
using System;
public static class Test
{
public static void Main()
{
if (SomeExpression())
{
System.Console.WriteLine(""hello"");
return;
}
else
{
System.Console.WriteLine(""hello"");
return;
}
}
private static bool SomeExpression()
{
return true;
}
}
";
CompileAndVerify(source, expectedOutput: @"hello"
).VerifyIL("Test.Main()",
@"
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: call ""bool Test.SomeExpression()""
IL_0005: pop
IL_0006: ldstr ""hello""
IL_000b: call ""void System.Console.WriteLine(string)""
IL_0010: ret
}
");
}
[WorkItem(530049, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530049")]
[Fact]
public void Regress530049()
{
var source = @"
enum MyEnum { first, second, last }
struct MyStruct { int intStructMember; }
public unsafe class Test
{
static bool boolMember = false;
static char charMember = '\0';
static sbyte sbyteMember = 0;
static byte byteMember = 0;
static short shortMember = 0;
static ushort ushortMember = 0;
static int intMember = 0;
static uint uintMember = 0;
static long longMember = 0L;
static ulong ulongMember = 0;
static nint nintMember = 0;
static nuint nuintMember = 0;
static decimal decimalMember = 0m;
static string strMember = null;
static object objMember = null;
static float floatMember = 0.0F;
static double doubleMember = 0.0D;
static MyEnum enumMember = MyEnum.first;
static bool boolMember2 = default(bool);
static char charMember2 = default(char);
static sbyte sbyteMember2 = default(sbyte);
static byte byteMember2 = default(byte);
static short shortMember2 = default(short);
static ushort ushortMember2 = default(ushort);
static int intMember2 = default(int);
static uint uintMember2 = default(uint);
static long longMember2 = default(long);
static ulong ulongMember2 = default(ulong);
static nint nintMember2 = default(nint);
static nuint nuintMember2 = default(nuint);
static decimal decimalMember2 = default(decimal);
static string strMember2 = default(string);
static object objMember2 = default(object);
static float floatMember2 = default(float);
static double doubleMember2 = default(double);
static MyEnum enumMember2 = default(MyEnum);
static MyStruct structMember2 = default(MyStruct);
static System.IntPtr intPtrMember2 = default(System.IntPtr);
static System.UIntPtr uintPtrMember2 = default(System.UIntPtr);
static void* voidPtrMember2 = default(void*);
}
class c1
{
public static void Main()
{
}
}
";
CompileAndVerify(
source,
expectedOutput: "",
symbolValidator: validator,
options: TestOptions.UnsafeDebugExe.WithMetadataImportOptions(MetadataImportOptions.All),
parseOptions: TestOptions.Regular9);
void validator(ModuleSymbol module)
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Test");
Assert.Null(type.GetMember(".cctor"));
}
}
[WorkItem(876784, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/876784")]
[Fact]
public void Repro876784()
{
var source = @"
public delegate void D();
public class A
{
static D Test()
{
return M1(() => { }).M2;
}
static A M1(D d) { return null; }
}
public static class AExtensions
{
public static void M2(this A a) { }
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyEmitDiagnostics();
}
[WorkItem(877317, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/877317")]
[Fact]
public void Repro877317()
{
var source = @"
delegate void D1();
delegate D1 D2();
class C
{
private D2 Test()
{
return () => (D1)this.Ext;
}
}
static class CExtensions
{
public static void Ext(this C r) { }
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyEmitDiagnostics();
}
[Fact]
public void Regress924709()
{
var source = @"
using System;
class Program
{
static bool[] bb;
static void Main(string[] args)
{
bb = AllOnesBool();
TestArrElement(bb);
TestRef(ref bb[0]);
}
static void TestArrElement(bool[] bb)
{
if (bb[0] ^ GetArrElement<bool>(bb))
{
System.Console.WriteLine('f');
}
}
static T GetArrElement<T>(T[] bb)
{
return bb[0];
}
static void TestRef(ref bool br)
{
if (br ^ GetRef<bool>(ref br))
{
System.Console.WriteLine('f');
}
}
static T GetRef<T>(ref T br)
{
return br;
}
unsafe static bool[] AllOnesBool()
{
bool[] bb = new bool[1];
fixed(bool* b = bb)
{
*(byte*)b = byte.MaxValue;
}
return bb;
}
}
";
CompileAndVerify(source, options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @""
).VerifyIL("Program.TestArrElement(bool[])",
@"
{
// Code size 20 (0x14)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelem.u1
IL_0003: ldarg.0
IL_0004: call ""bool Program.GetArrElement<bool>(bool[])""
IL_0009: xor
IL_000a: brfalse.s IL_0013
IL_000c: ldc.i4.s 102
IL_000e: call ""void System.Console.WriteLine(char)""
IL_0013: ret
}
").VerifyIL("Program.TestRef(ref bool)",
@"
{
// Code size 19 (0x13)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldind.u1
IL_0002: ldarg.0
IL_0003: call ""bool Program.GetRef<bool>(ref bool)""
IL_0008: xor
IL_0009: brfalse.s IL_0012
IL_000b: ldc.i4.s 102
IL_000d: call ""void System.Console.WriteLine(char)""
IL_0012: ret
}
");
}
[Fact]
public void NamedParamsOptimizationAndParams001()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
Test(a1: 5, a2: 42.ToString());
Test(a2: 42.ToString(), a1: 5);
}
public static void Test(int a1, params object[] a2)
{
System.Console.WriteLine(a2[0]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42
42");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 51 (0x33)
.maxstack 5
.locals init (int V_0)
IL_0000: ldc.i4.5
IL_0001: ldc.i4.1
IL_0002: newarr ""object""
IL_0007: dup
IL_0008: ldc.i4.0
IL_0009: ldc.i4.s 42
IL_000b: stloc.0
IL_000c: ldloca.s V_0
IL_000e: call ""string int.ToString()""
IL_0013: stelem.ref
IL_0014: call ""void Program.Test(int, params object[])""
IL_0019: ldc.i4.5
IL_001a: ldc.i4.1
IL_001b: newarr ""object""
IL_0020: dup
IL_0021: ldc.i4.0
IL_0022: ldc.i4.s 42
IL_0024: stloc.0
IL_0025: ldloca.s V_0
IL_0027: call ""string int.ToString()""
IL_002c: stelem.ref
IL_002d: call ""void Program.Test(int, params object[])""
IL_0032: ret
}
");
}
[Fact]
public void NamedParamsOptimizationAndParams002()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
Test(a2: 42.ToString(), a1: 5.ToString());
}
public static void Test(string a1, params object[] a2)
{
System.Console.WriteLine(a2[0]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 36 (0x24)
.maxstack 5
.locals init (object V_0,
int V_1)
IL_0000: ldc.i4.s 42
IL_0002: stloc.1
IL_0003: ldloca.s V_1
IL_0005: call ""string int.ToString()""
IL_000a: stloc.0
IL_000b: ldc.i4.5
IL_000c: stloc.1
IL_000d: ldloca.s V_1
IL_000f: call ""string int.ToString()""
IL_0014: ldc.i4.1
IL_0015: newarr ""object""
IL_001a: dup
IL_001b: ldc.i4.0
IL_001c: ldloc.0
IL_001d: stelem.ref
IL_001e: call ""void Program.Test(string, params object[])""
IL_0023: ret
}
");
}
[Fact]
public void NamedParamsOptimizationAndParams003()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
Test(a2: 42.ToString(), a1: 5);
}
public static void Test(int a1, int aOpt = 333, params object[] a2)
{
System.Console.WriteLine(a2[0]);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"42");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 31 (0x1f)
.maxstack 6
.locals init (int V_0)
IL_0000: ldc.i4.5
IL_0001: ldc.i4 0x14d
IL_0006: ldc.i4.1
IL_0007: newarr ""object""
IL_000c: dup
IL_000d: ldc.i4.0
IL_000e: ldc.i4.s 42
IL_0010: stloc.0
IL_0011: ldloca.s V_0
IL_0013: call ""string int.ToString()""
IL_0018: stelem.ref
IL_0019: call ""void Program.Test(int, int, params object[])""
IL_001e: ret
}
");
}
[Fact]
[WorkItem(4196, "https://github.com/dotnet/roslyn/issues/4196")]
public void BadDefaultParameterValue()
{
// In this DLL there is an optional parameter which has a corrupted metadata value
// as the default argument. This can happen in legitimate code when run through an
// obfuscator program. For compatibility with the native compiler we need to treat
// the value as default(T)
string source = @"
using System;
using BadDefaultParameterValue;
class Program
{
static void Main()
{
Util.M(""test"");
}
}";
var testReference = AssemblyMetadata.CreateFromImage(TestResources.SymbolsTests.Metadata.BadDefaultParameterValue).GetReference();
var compilation = CompileAndVerify(source, references: new[] { testReference });
compilation.VerifyIL("Program.Main", @"
{
// Code size 12 (0xc)
.maxstack 2
IL_0000: ldstr ""test""
IL_0005: ldnull
IL_0006: call ""void BadDefaultParameterValue.Util.M(string, string)""
IL_000b: ret
}");
}
[WorkItem(5530, "https://github.com/dotnet/roslyn/issues/5530")]
[Fact]
public void InplaceCtorUsesLocal()
{
string source = @"
class Program
{
private static S1[] arr = new S1[1];
struct S1
{
public int a, b;
public S1(int a, int b)
{
this.a = a;
this.b = b;
}
}
static void Main(string[] args)
{
var arg = System.Math.Max(1, 2);
var val = new S1(arg, arg);
arr[0] = val;
System.Console.WriteLine(arr[0].a);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "2");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 51 (0x33)
.maxstack 3
.locals init (int V_0, //arg
Program.S1 V_1) //val
IL_0000: ldc.i4.1
IL_0001: ldc.i4.2
IL_0002: call ""int System.Math.Max(int, int)""
IL_0007: stloc.0
IL_0008: ldloca.s V_1
IL_000a: ldloc.0
IL_000b: ldloc.0
IL_000c: call ""Program.S1..ctor(int, int)""
IL_0011: ldsfld ""Program.S1[] Program.arr""
IL_0016: ldc.i4.0
IL_0017: ldloc.1
IL_0018: stelem ""Program.S1""
IL_001d: ldsfld ""Program.S1[] Program.arr""
IL_0022: ldc.i4.0
IL_0023: ldelema ""Program.S1""
IL_0028: ldfld ""int Program.S1.a""
IL_002d: call ""void System.Console.WriteLine(int)""
IL_0032: ret
}
");
}
[WorkItem(5530, "https://github.com/dotnet/roslyn/issues/5530")]
[Fact]
public void TernaryConsequenceUsesLocal()
{
string source = @"
class Program
{
static bool goo()
{
return true;
}
static void Main(string[] args)
{
bool arg;
var val = (arg = goo())? arg & arg : false;
System.Console.WriteLine(val);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "True");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 21 (0x15)
.maxstack 2
.locals init (bool V_0) //arg
IL_0000: call ""bool Program.goo()""
IL_0005: dup
IL_0006: stloc.0
IL_0007: brtrue.s IL_000c
IL_0009: ldc.i4.0
IL_000a: br.s IL_000f
IL_000c: ldloc.0
IL_000d: ldloc.0
IL_000e: and
IL_000f: call ""void System.Console.WriteLine(bool)""
IL_0014: ret
}
");
}
[WorkItem(5530, "https://github.com/dotnet/roslyn/issues/5530")]
[Fact]
public void CoalesceUsesLocal()
{
string source = @"
class Program
{
static string goo()
{
return ""hi"";
}
static void Main(string[] args)
{
string str;
var val = (str = goo()) ?? str + ""aa"";
System.Console.WriteLine(val);
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "hi");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 28 (0x1c)
.maxstack 2
.locals init (string V_0) //str
IL_0000: call ""string Program.goo()""
IL_0005: dup
IL_0006: stloc.0
IL_0007: dup
IL_0008: brtrue.s IL_0016
IL_000a: pop
IL_000b: ldloc.0
IL_000c: ldstr ""aa""
IL_0011: call ""string string.Concat(string, string)""
IL_0016: call ""void System.Console.WriteLine(string)""
IL_001b: ret
}
");
}
[WorkItem(5530, "https://github.com/dotnet/roslyn/issues/5530")]
[Fact]
public void TernaryUsesLocal()
{
string source = @"
class Program
{
static void Main(string[] args)
{
string sline = GetString();
var lastChar = sline.Length == 0 ? '\0' : sline[sline.Length - 1];
System.Console.WriteLine(lastChar);
}
private static string GetString()
{
return ""hello"";
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "o");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 37 (0x25)
.maxstack 3
.locals init (string V_0) //sline
IL_0000: call ""string Program.GetString()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt ""int string.Length.get""
IL_000c: brfalse.s IL_001e
IL_000e: ldloc.0
IL_000f: ldloc.0
IL_0010: callvirt ""int string.Length.get""
IL_0015: ldc.i4.1
IL_0016: sub
IL_0017: callvirt ""char string.this[int].get""
IL_001c: br.s IL_001f
IL_001e: ldc.i4.0
IL_001f: call ""void System.Console.WriteLine(char)""
IL_0024: ret
}
");
}
[WorkItem(5530, "https://github.com/dotnet/roslyn/issues/5530")]
[Fact]
public void LogicalOpUsesLocal()
{
string source = @"
class Program
{
static void Main(string[] args)
{
string tokenString = GetString();
if (tokenString[tokenString.Length - 1] != 'L' && tokenString[tokenString.Length -1] != 'l')
{
System.Console.WriteLine(""hi"");
}
}
private static string GetString()
{
return ""hello"";
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "hi");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 53 (0x35)
.maxstack 3
.locals init (string V_0) //tokenString
IL_0000: call ""string Program.GetString()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldloc.0
IL_0008: callvirt ""int string.Length.get""
IL_000d: ldc.i4.1
IL_000e: sub
IL_000f: callvirt ""char string.this[int].get""
IL_0014: ldc.i4.s 76
IL_0016: beq.s IL_0034
IL_0018: ldloc.0
IL_0019: ldloc.0
IL_001a: callvirt ""int string.Length.get""
IL_001f: ldc.i4.1
IL_0020: sub
IL_0021: callvirt ""char string.this[int].get""
IL_0026: ldc.i4.s 108
IL_0028: beq.s IL_0034
IL_002a: ldstr ""hi""
IL_002f: call ""void System.Console.WriteLine(string)""
IL_0034: ret
}
");
}
[WorkItem(5880, "https://github.com/dotnet/roslyn/issues/5880")]
[Fact]
public void StructCtorArgTernary()
{
string source = @"
using System.Collections.Generic;
using System;
class Program
{
struct TextSpan
{
private int start;
private int length;
public int Start => start;
public int End => start + length;
public int Length => length;
public TextSpan(int start, int length)
{
this.start = start;
this.length = length;
}
}
static void Main(string[] args)
{
int length = 123;
int start = 5;
var list = new List<TextSpan>(10);
list.Add(new TextSpan(0, 10));
list.Add(new TextSpan(0, 10));
for (int i = 0; i < list.Count; i++)
{
var span = list[i];
if (span.End < start)
{
continue;
}
var newStart = Math.Min(Math.Max(span.Start + 10, 0), length);
var newSpan = new TextSpan(newStart, newStart >= length ? 0 : span.Length);
list[i] = newSpan;
}
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: "");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 135 (0x87)
.maxstack 4
.locals init (int V_0, //length
int V_1, //start
System.Collections.Generic.List<Program.TextSpan> V_2, //list
int V_3, //i
Program.TextSpan V_4, //span
int V_5, //newStart
Program.TextSpan V_6) //newSpan
IL_0000: ldc.i4.s 123
IL_0002: stloc.0
IL_0003: ldc.i4.5
IL_0004: stloc.1
IL_0005: ldc.i4.s 10
IL_0007: newobj ""System.Collections.Generic.List<Program.TextSpan>..ctor(int)""
IL_000c: stloc.2
IL_000d: ldloc.2
IL_000e: ldc.i4.0
IL_000f: ldc.i4.s 10
IL_0011: newobj ""Program.TextSpan..ctor(int, int)""
IL_0016: callvirt ""void System.Collections.Generic.List<Program.TextSpan>.Add(Program.TextSpan)""
IL_001b: ldloc.2
IL_001c: ldc.i4.0
IL_001d: ldc.i4.s 10
IL_001f: newobj ""Program.TextSpan..ctor(int, int)""
IL_0024: callvirt ""void System.Collections.Generic.List<Program.TextSpan>.Add(Program.TextSpan)""
IL_0029: ldc.i4.0
IL_002a: stloc.3
IL_002b: br.s IL_007d
IL_002d: ldloc.2
IL_002e: ldloc.3
IL_002f: callvirt ""Program.TextSpan System.Collections.Generic.List<Program.TextSpan>.this[int].get""
IL_0034: stloc.s V_4
IL_0036: ldloca.s V_4
IL_0038: call ""int Program.TextSpan.End.get""
IL_003d: ldloc.1
IL_003e: blt.s IL_0079
IL_0040: ldloca.s V_4
IL_0042: call ""int Program.TextSpan.Start.get""
IL_0047: ldc.i4.s 10
IL_0049: add
IL_004a: ldc.i4.0
IL_004b: call ""int System.Math.Max(int, int)""
IL_0050: ldloc.0
IL_0051: call ""int System.Math.Min(int, int)""
IL_0056: stloc.s V_5
IL_0058: ldloca.s V_6
IL_005a: ldloc.s V_5
IL_005c: ldloc.s V_5
IL_005e: ldloc.0
IL_005f: bge.s IL_006a
IL_0061: ldloca.s V_4
IL_0063: call ""int Program.TextSpan.Length.get""
IL_0068: br.s IL_006b
IL_006a: ldc.i4.0
IL_006b: call ""Program.TextSpan..ctor(int, int)""
IL_0070: ldloc.2
IL_0071: ldloc.3
IL_0072: ldloc.s V_6
IL_0074: callvirt ""void System.Collections.Generic.List<Program.TextSpan>.this[int].set""
IL_0079: ldloc.3
IL_007a: ldc.i4.1
IL_007b: add
IL_007c: stloc.3
IL_007d: ldloc.3
IL_007e: ldloc.2
IL_007f: callvirt ""int System.Collections.Generic.List<Program.TextSpan>.Count.get""
IL_0084: blt.s IL_002d
IL_0086: ret
}");
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void FieldInitializerDynamic()
{
string source = @"
using System;
class M
{
object a = Test((dynamic)2);
static object Test(object obj) => obj;
static object Test(string obj) => obj;
static void Main()
{
Console.Write(new M().a);
}
}
";
var compilation = CompileAndVerifyWithMscorlib40(source, new[] { SystemCoreRef, CSharpRef }, expectedOutput: "2");
// the main point of this test is to have it PEVerify/run correctly, although checking IL too can't hurt.
compilation.VerifyIL("M..ctor",
@"{
// Code size 115 (0x73)
.maxstack 10
IL_0000: ldarg.0
IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__4.<>p__0""
IL_0006: brtrue.s IL_0043
IL_0008: ldc.i4.0
IL_0009: ldstr ""Test""
IL_000e: ldnull
IL_000f: ldtoken ""M""
IL_0014: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_0019: ldc.i4.2
IL_001a: newarr ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo""
IL_001f: dup
IL_0020: ldc.i4.0
IL_0021: ldc.i4.s 33
IL_0023: ldnull
IL_0024: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)""
IL_0029: stelem.ref
IL_002a: dup
IL_002b: ldc.i4.1
IL_002c: ldc.i4.0
IL_002d: ldnull
IL_002e: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)""
IL_0033: stelem.ref
IL_0034: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, System.Collections.Generic.IEnumerable<System.Type>, System.Type, System.Collections.Generic.IEnumerable<Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)""
IL_0039: call ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>>.Create(System.Runtime.CompilerServices.CallSiteBinder)""
IL_003e: stsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__4.<>p__0""
IL_0043: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__4.<>p__0""
IL_0048: ldfld ""System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic> System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>>.Target""
IL_004d: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__4.<>p__0""
IL_0052: ldtoken ""M""
IL_0057: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_005c: ldc.i4.2
IL_005d: box ""int""
IL_0062: callvirt ""dynamic System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>.Invoke(System.Runtime.CompilerServices.CallSite, System.Type, dynamic)""
IL_0067: stfld ""object M.a""
IL_006c: ldarg.0
IL_006d: call ""object..ctor()""
IL_0072: ret
}");
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void FieldInitializerDynamicParameter()
{
string source = @"
using System;
class M
{
// inner call is dynamic parameter, static argument
// outer call is dynamic parameter, dynamic argument
object a = Test2(Test(2));
static dynamic Test(dynamic obj) => obj;
static dynamic Test2(int obj) => obj;
static dynamic Test2(long obj) => obj;
static void Main()
{
Console.Write(new M().a);
}
}
";
var compilation = CompileAndVerifyWithMscorlib40(source, new[] { SystemCoreRef, CSharpRef }, expectedOutput: "2");
compilation.VerifyIL("M..ctor",
@"{
// Code size 120 (0x78)
.maxstack 10
IL_0000: ldarg.0
IL_0001: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__5.<>p__0""
IL_0006: brtrue.s IL_0043
IL_0008: ldc.i4.0
IL_0009: ldstr ""Test2""
IL_000e: ldnull
IL_000f: ldtoken ""M""
IL_0014: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_0019: ldc.i4.2
IL_001a: newarr ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo""
IL_001f: dup
IL_0020: ldc.i4.0
IL_0021: ldc.i4.s 33
IL_0023: ldnull
IL_0024: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)""
IL_0029: stelem.ref
IL_002a: dup
IL_002b: ldc.i4.1
IL_002c: ldc.i4.0
IL_002d: ldnull
IL_002e: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)""
IL_0033: stelem.ref
IL_0034: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, System.Collections.Generic.IEnumerable<System.Type>, System.Type, System.Collections.Generic.IEnumerable<Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)""
IL_0039: call ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>>.Create(System.Runtime.CompilerServices.CallSiteBinder)""
IL_003e: stsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__5.<>p__0""
IL_0043: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__5.<>p__0""
IL_0048: ldfld ""System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic> System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>>.Target""
IL_004d: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>> M.<>o__5.<>p__0""
IL_0052: ldtoken ""M""
IL_0057: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_005c: ldc.i4.2
IL_005d: box ""int""
IL_0062: call ""dynamic M.Test(dynamic)""
IL_0067: callvirt ""dynamic System.Func<System.Runtime.CompilerServices.CallSite, System.Type, dynamic, dynamic>.Invoke(System.Runtime.CompilerServices.CallSite, System.Type, dynamic)""
IL_006c: stfld ""object M.a""
IL_0071: ldarg.0
IL_0072: call ""object..ctor()""
IL_0077: ret
}");
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void FieldInitializerDynamicInstance()
{
string source = @"
using System;
class M
{
object a = Test((dynamic)2);
object Test(object obj) => obj;
static void Main()
{
Console.Write(new M().a);
}
}
";
// BREAKING CHANGE: The native compiler allowed this (and generated code that will always throw at runtime)
CreateCompilationWithMscorlib461AndCSharp(source).VerifyDiagnostics(
// (6,16): error CS0236: A field initializer cannot reference the non-static field, method, or property 'M.Test(object)'
// object a = Test((dynamic)2);
Diagnostic(ErrorCode.ERR_FieldInitRefNonstatic, "Test").WithArguments("M.Test(object)").WithLocation(6, 16)
);
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void FieldInitializerDynamicBothStaticInstance_01()
{
string source = @"
using System;
class M
{
object a = Test((dynamic)2L);
object b = Test((dynamic)2);
static object Test(long obj)
{
Console.Write(""long."");
return obj;
}
object Test(int obj)
{
Console.Write(""int."");
return obj;
}
static void Main()
{
try
{
Console.Write(new M().a);
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
{
Console.Write(""ex caught"");
}
}
}
";
var compilation = CompileAndVerifyWithMscorlib40(source, new[] { SystemCoreRef, CSharpRef }, expectedOutput: "long.ex caught");
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void FieldInitializerDynamicBothStaticInstance_02()
{
string source = @"
using System;
class M
{
object a = Test((dynamic)2L);
object b = Test((dynamic)2);
static object Test(long obj)
{
Console.Write(""long."");
return obj;
}
object Test(int obj)
{
Console.Write(""int."");
return obj;
}
static object Test(byte obj)
{
return obj;
}
static void Main()
{
try
{
Console.Write(new M().a);
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
{
Console.Write(""ex caught"");
}
}
}
";
var compilation = CompileAndVerifyWithMscorlib40(source, new[] { SystemCoreRef, CSharpRef }, expectedOutput: "long.ex caught");
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void CtorInitializerInstance()
{
string source = @"
using System;
class B
{
public object a;
public B(object obj)
{
this.a = obj;
}
}
class M : B
{
public M() : base((object)Test((dynamic)2))
{
}
object Test(object obj)
{
return obj;
}
static void Main()
{
try
{
Console.Write(new M().a);
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
{
Console.Write(ex.Message);
}
}
}
";
// BREAKING CHANGE: The native compiler allowed this (and generated code that will always throw at runtime)
CreateCompilationWithMscorlib461AndCSharp(source).VerifyDiagnostics(
// (16,31): error CS0120: An object reference is required for the non-static field, method, or property 'M.Test(object)'
// public M() : base((object)Test((dynamic)2))
Diagnostic(ErrorCode.ERR_ObjectRequired, "Test").WithArguments("M.Test(object)").WithLocation(16, 31)
);
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void StaticCtorInstance()
{
string source = @"
using System;
class M
{
static M()
{
Console.Write((object)Test((dynamic)2));
}
object Test(object obj)
{
return obj;
}
static void Main()
{
}
}
";
// BREAKING CHANGE: The native compiler allowed this (and generated code that will always throw at runtime)
CreateCompilationWithMscorlib461AndCSharp(source).VerifyDiagnostics(
// (8,31): error CS0120: An object reference is required for the non-static field, method, or property 'M.Test(object)'
// Console.Write((object)Test((dynamic)2));
Diagnostic(ErrorCode.ERR_ObjectRequired, "Test").WithArguments("M.Test(object)").WithLocation(8, 31)
);
}
[WorkItem(10463, "https://github.com/dotnet/roslyn/issues/10463")]
[Fact]
public void StaticFieldInstance()
{
string source = @"
class M
{
static object o = (object)Test((dynamic)2);
object Test(object obj)
{
return obj;
}
static void Main()
{
}
}
";
// BREAKING CHANGE: The native compiler allowed this (and generated code that will always throw at runtime)
CreateCompilationWithMscorlib461AndCSharp(source).VerifyDiagnostics(
// (4,31): error CS0236: A field initializer cannot reference the non-static field, method, or property 'M.Test(object)'
// static object o = (object)Test((dynamic)2);
Diagnostic(ErrorCode.ERR_FieldInitRefNonstatic, "Test").WithArguments("M.Test(object)").WithLocation(4, 31)
);
}
[Fact]
public void CallingInstanceDynamicallyFromStaticContext()
{
string source = @"
class B
{
public B(int x)
{
}
}
class C : B
{
int InstanceMethod(int x)
{
return x;
}
static int field = (int)InstanceMethod((dynamic)2);
static int Property
{
get
{
return (int)InstanceMethod((dynamic)2);
}
}
static int Method()
{
return (int)InstanceMethod((dynamic)2);
}
// these are all still static contexts, even though they're related to instance things
int instanceField = (int)InstanceMethod((dynamic)2);
public C(int x) : base((int)InstanceMethod((dynamic)x))
{
}
public C() : this((int)InstanceMethod((dynamic)2))
{
}
}
class M
{
static void Main()
{
// attempting to even load C will cause runtime errors in all cases of calling C.InstanceMethod
System.Console.Write(5);
}
}
";
// BREAKING CHANGE: The native compiler allowed this (and generated code that will always throw at runtime)
CreateCompilationWithMscorlib461AndCSharp(source).VerifyDiagnostics(
// (16,29): error CS0236: A field initializer cannot reference the non-static field, method, or property 'C.InstanceMethod(int)'
// static int field = (int)InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_FieldInitRefNonstatic, "InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(16, 29),
// (30,30): error CS0236: A field initializer cannot reference the non-static field, method, or property 'C.InstanceMethod(int)'
// int instanceField = (int)InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_FieldInitRefNonstatic, "InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(30, 30),
// (21,25): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// return (int)InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_ObjectRequired, "InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(21, 25),
// (26,21): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// return (int)InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_ObjectRequired, "InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(26, 21),
// (31,33): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// public C(int x) : base((int)InstanceMethod((dynamic)x))
Diagnostic(ErrorCode.ERR_ObjectRequired, "InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(31, 33),
// (34,28): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// public C() : this((int)InstanceMethod((dynamic)2))
Diagnostic(ErrorCode.ERR_ObjectRequired, "InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(34, 28)
);
}
[Fact]
public void CallingInstanceDynamicallyFromStaticContextWithTypeName()
{
// Very similar to CallingInstanceDynamicallyFromStaticContext, but every call to `InstanceMethod` is now `C.InstanceMethod`
// The native compiler allows both cases, so it's an interesting backcompat case:
// The spec (as of 2016-05-13, it may be changed) explicitly disallows `C.InstanceMethod`,
// but doesn't say for just `InstanceMethod` (in a way that implies it should be allowed).
// Roslyn disallows both cases.
string source = @"
class B
{
public B(int x)
{
}
}
class C : B
{
int InstanceMethod(int x)
{
return x;
}
static int field = (int)C.InstanceMethod((dynamic)2);
static int Property
{
get
{
return (int)C.InstanceMethod((dynamic)2);
}
}
static int Method()
{
return (int)C.InstanceMethod((dynamic)2);
}
// these are all still static contexts, even though they're related to instance things
int instanceField = (int)C.InstanceMethod((dynamic)2);
public C(int x) : base((int)C.InstanceMethod((dynamic)x))
{
}
public C() : this((int)C.InstanceMethod((dynamic)2))
{
}
}
class M
{
static void Main()
{
// attempting to even load C will cause runtime errors in all cases of calling C.InstanceMethod
System.Console.Write(5);
}
}
";
// BREAKING CHANGE: The native compiler allowed this (and generated code that will always throw at runtime)
CreateCompilationWithMscorlib461AndCSharp(source).VerifyDiagnostics(
// (16,29): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// static int field = (int)C.InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(16, 29),
// (30,30): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// int instanceField = (int)C.InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(30, 30),
// (21,25): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// return (int)C.InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(21, 25),
// (26,21): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// return (int)C.InstanceMethod((dynamic)2);
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(26, 21),
// (31,33): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// public C(int x) : base((int)C.InstanceMethod((dynamic)x))
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(31, 33),
// (34,28): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod(int)'
// public C() : this((int)C.InstanceMethod((dynamic)2))
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.InstanceMethod").WithArguments("C.InstanceMethod(int)").WithLocation(34, 28)
);
}
[Fact, WorkItem(13486, "https://github.com/dotnet/roslyn/issues/13486")]
public void BinaryMulOptimizationsAndSideeffects()
{
string source = @"
using System;
class Program
{
static void Main(string[] args)
{
// should not optimize
System.Console.WriteLine(Goo1() * 0);
System.Console.WriteLine(0 * Goo1());
// should optimize
var local = 123;
System.Console.WriteLine(local * 0);
System.Console.WriteLine(0 * default(int?));
System.Console.WriteLine(0 * local);
// should not capture
System.Console.WriteLine(((Func<int>)(()=>local * 0))());
// should not optimize
System.Console.WriteLine(Goo2() & false);
System.Console.WriteLine(false & Goo2());
// should optimize
var local1 = true;
System.Console.WriteLine(local1 & false);
System.Console.WriteLine(false & default(bool?));
System.Console.WriteLine(false & ((bool?)local1).HasValue);
System.Console.WriteLine(false & local1);
// should optimize
System.Console.WriteLine(Goo2() && false);
System.Console.WriteLine(Goo2() && true);
System.Console.WriteLine(false && Goo2());
System.Console.WriteLine(true && Goo2());
System.Console.WriteLine(Goo2() || false);
System.Console.WriteLine(Goo2() || true);
System.Console.WriteLine(false || Goo2());
System.Console.WriteLine(true || Goo2());
}
static int Goo1()
{
System.Console.Write(""Goo1 "");
return 42;
}
static bool Goo2()
{
System.Console.Write(""Goo2 "");
return true;
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
Goo1 0
Goo1 0
0
0
0
Goo2 False
Goo2 False
False
False
False
False
Goo2 False
Goo2 True
False
Goo2 True
Goo2 True
Goo2 True
Goo2 True
True
");
compilation.VerifyIL("Program.Main",
@"
{
// Code size 221 (0xdd)
.maxstack 2
IL_0000: call ""int Program.Goo1()""
IL_0005: pop
IL_0006: ldc.i4.0
IL_0007: call ""void System.Console.WriteLine(int)""
IL_000c: call ""int Program.Goo1()""
IL_0011: pop
IL_0012: ldc.i4.0
IL_0013: call ""void System.Console.WriteLine(int)""
IL_0018: ldc.i4.0
IL_0019: call ""void System.Console.WriteLine(int)""
IL_001e: ldnull
IL_001f: call ""void System.Console.WriteLine(object)""
IL_0024: ldc.i4.0
IL_0025: call ""void System.Console.WriteLine(int)""
IL_002a: ldsfld ""System.Func<int> Program.<>c.<>9__0_0""
IL_002f: dup
IL_0030: brtrue.s IL_0049
IL_0032: pop
IL_0033: ldsfld ""Program.<>c Program.<>c.<>9""
IL_0038: ldftn ""int Program.<>c.<Main>b__0_0()""
IL_003e: newobj ""System.Func<int>..ctor(object, System.IntPtr)""
IL_0043: dup
IL_0044: stsfld ""System.Func<int> Program.<>c.<>9__0_0""
IL_0049: callvirt ""int System.Func<int>.Invoke()""
IL_004e: call ""void System.Console.WriteLine(int)""
IL_0053: call ""bool Program.Goo2()""
IL_0058: pop
IL_0059: ldc.i4.0
IL_005a: call ""void System.Console.WriteLine(bool)""
IL_005f: call ""bool Program.Goo2()""
IL_0064: pop
IL_0065: ldc.i4.0
IL_0066: call ""void System.Console.WriteLine(bool)""
IL_006b: ldc.i4.0
IL_006c: call ""void System.Console.WriteLine(bool)""
IL_0071: ldc.i4.0
IL_0072: box ""bool""
IL_0077: call ""void System.Console.WriteLine(object)""
IL_007c: ldc.i4.0
IL_007d: call ""void System.Console.WriteLine(bool)""
IL_0082: ldc.i4.0
IL_0083: call ""void System.Console.WriteLine(bool)""
IL_0088: call ""bool Program.Goo2()""
IL_008d: brfalse.s IL_0092
IL_008f: ldc.i4.0
IL_0090: br.s IL_0093
IL_0092: ldc.i4.0
IL_0093: call ""void System.Console.WriteLine(bool)""
IL_0098: call ""bool Program.Goo2()""
IL_009d: call ""void System.Console.WriteLine(bool)""
IL_00a2: ldc.i4.0
IL_00a3: call ""void System.Console.WriteLine(bool)""
IL_00a8: call ""bool Program.Goo2()""
IL_00ad: call ""void System.Console.WriteLine(bool)""
IL_00b2: call ""bool Program.Goo2()""
IL_00b7: call ""void System.Console.WriteLine(bool)""
IL_00bc: call ""bool Program.Goo2()""
IL_00c1: brtrue.s IL_00c6
IL_00c3: ldc.i4.1
IL_00c4: br.s IL_00c7
IL_00c6: ldc.i4.1
IL_00c7: call ""void System.Console.WriteLine(bool)""
IL_00cc: call ""bool Program.Goo2()""
IL_00d1: call ""void System.Console.WriteLine(bool)""
IL_00d6: ldc.i4.1
IL_00d7: call ""void System.Console.WriteLine(bool)""
IL_00dc: ret
}
");
}
[Fact, WorkItem(0, "http://stackoverflow.com/questions/39254676/roslyn-compiler-optimizing-away-function-call-multiplication-with-zero?stw=2")]
public void SideEffectOptimizedAway()
{
var source =
@"
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static void Main(string[] args)
{
Stack<long> s = new Stack<long>();
s.Push(1); // stack contains [1]
s.Push(s.Pop() * 0); // stack should contain [0]
Console.WriteLine(string.Join(""|"", s.Reverse()));
}
}
";
CompileAndVerify(source, targetFramework: TargetFramework.NetFramework, expectedOutput: "0");
}
[Fact, WorkItem(9703, "https://github.com/dotnet/roslyn/issues/9703")]
public void IgnoredConversion()
{
string source = @"
using System;
public class Form1 {
public class BadCompiler {
public DateTime? Value {get; set;}
}
private BadCompiler TestObj = new BadCompiler();
public void IPE() {
object o;
o = TestObj.Value;
}
}";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("Form1.IPE", @"
{
// Code size 13 (0xd)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ldfld ""Form1.BadCompiler Form1.TestObj""
IL_0006: callvirt ""System.DateTime? Form1.BadCompiler.Value.get""
IL_000b: pop
IL_000c: ret
}");
}
[Fact]
public void CorrectOverloadOfStackAllocSpanChosen()
{
var source = @"
using System;
class Test
{
unsafe public static void Main()
{
bool condition = false;
var span1 = condition ? stackalloc int[1] : new Span<int>(null, 2);
Console.Write(span1.Length);
var span2 = condition ? new Span<int>(null, 3) : stackalloc int[4];
Console.Write(span2.Length);
}
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.UnsafeReleaseExe);
CompileAndVerify(comp, expectedOutput: "24", verify: Verification.Fails);
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.UnsafeDebugExe);
CompileAndVerify(comp, expectedOutput: "24", verify: Verification.Fails);
}
[Fact, WorkItem(35764, "https://github.com/dotnet/roslyn/issues/35764")]
public void StackAllocExpressionIL()
{
var source = @"
using System;
class Test
{
public static void Main()
{
Span<int> x = stackalloc int[33];
Console.Write(x.Length);
x = stackalloc int[0];
Console.Write(x.Length);
}
}";
var expectedOutput = "330";
CSharpCompilation comp;
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 49 (0x31)
.maxstack 2
.locals init (System.Span<int> V_0) //x
IL_0000: ldc.i4 0x84
IL_0005: conv.u
IL_0006: localloc
IL_0008: ldc.i4.s 33
IL_000a: newobj ""System.Span<int>..ctor(void*, int)""
IL_000f: stloc.0
IL_0010: ldloca.s V_0
IL_0012: call ""int System.Span<int>.Length.get""
IL_0017: call ""void System.Console.Write(int)""
IL_001c: ldloca.s V_0
IL_001e: initobj ""System.Span<int>""
IL_0024: ldloca.s V_0
IL_0026: call ""int System.Span<int>.Length.get""
IL_002b: call ""void System.Console.Write(int)""
IL_0030: ret
}");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 54 (0x36)
.maxstack 2
.locals init (System.Span<int> V_0, //x
System.Span<int> V_1)
IL_0000: nop
IL_0001: ldc.i4 0x84
IL_0006: conv.u
IL_0007: localloc
IL_0009: ldc.i4.s 33
IL_000b: newobj ""System.Span<int>..ctor(void*, int)""
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: stloc.0
IL_0013: ldloca.s V_0
IL_0015: call ""int System.Span<int>.Length.get""
IL_001a: call ""void System.Console.Write(int)""
IL_001f: nop
IL_0020: ldloca.s V_0
IL_0022: initobj ""System.Span<int>""
IL_0028: ldloca.s V_0
IL_002a: call ""int System.Span<int>.Length.get""
IL_002f: call ""void System.Console.Write(int)""
IL_0034: nop
IL_0035: ret
}
");
}
[Fact]
public void StackAllocSpanLengthNotEvaluatedTwice()
{
var source = @"
using System;
class Test
{
private static int length = 0;
private static int GetLength()
{
return ++length;
}
public static void Main()
{
for (int i = 0; i < 5; i++)
{
Span<int> x = stackalloc int[GetLength()];
Console.Write(x.Length);
}
}
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "12345", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 44 (0x2c)
.maxstack 2
.locals init (int V_0, //i
System.Span<int> V_1, //x
int V_2)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0027
IL_0004: call ""int Test.GetLength()""
IL_0009: stloc.2
IL_000a: ldloc.2
IL_000b: conv.u
IL_000c: ldc.i4.4
IL_000d: mul.ovf.un
IL_000e: localloc
IL_0010: ldloc.2
IL_0011: newobj ""System.Span<int>..ctor(void*, int)""
IL_0016: stloc.1
IL_0017: ldloca.s V_1
IL_0019: call ""int System.Span<int>.Length.get""
IL_001e: call ""void System.Console.Write(int)""
IL_0023: ldloc.0
IL_0024: ldc.i4.1
IL_0025: add
IL_0026: stloc.0
IL_0027: ldloc.0
IL_0028: ldc.i4.5
IL_0029: blt.s IL_0004
IL_002b: ret
}");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "12345", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 56 (0x38)
.maxstack 2
.locals init (int V_0, //i
System.Span<int> V_1, //x
int V_2,
System.Span<int> V_3,
bool V_4)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_002d
IL_0005: nop
IL_0006: call ""int Test.GetLength()""
IL_000b: stloc.2
IL_000c: ldloc.2
IL_000d: conv.u
IL_000e: ldc.i4.4
IL_000f: mul.ovf.un
IL_0010: localloc
IL_0012: ldloc.2
IL_0013: newobj ""System.Span<int>..ctor(void*, int)""
IL_0018: stloc.3
IL_0019: ldloc.3
IL_001a: stloc.1
IL_001b: ldloca.s V_1
IL_001d: call ""int System.Span<int>.Length.get""
IL_0022: call ""void System.Console.Write(int)""
IL_0027: nop
IL_0028: nop
IL_0029: ldloc.0
IL_002a: ldc.i4.1
IL_002b: add
IL_002c: stloc.0
IL_002d: ldloc.0
IL_002e: ldc.i4.5
IL_002f: clt
IL_0031: stloc.s V_4
IL_0033: ldloc.s V_4
IL_0035: brtrue.s IL_0005
IL_0037: ret
}
");
}
[Fact]
public void NestedStackAlloc_01()
{
var source = @"
using System;
class Test
{
public static void Main()
{
Console.WriteLine(M(2, stackalloc int[3]));
}
public static int M(int x, Span<int> y) => x * y.Length;
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 25 (0x19)
.maxstack 2
.locals init (System.Span<int> V_0)
IL_0000: ldc.i4.s 12
IL_0002: conv.u
IL_0003: localloc
IL_0005: ldc.i4.3
IL_0006: newobj ""System.Span<int>..ctor(void*, int)""
IL_000b: stloc.0
IL_000c: ldc.i4.2
IL_000d: ldloc.0
IL_000e: call ""int Test.M(int, System.Span<int>)""
IL_0013: call ""void System.Console.WriteLine(int)""
IL_0018: ret
}
");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 27 (0x1b)
.maxstack 2
.locals init (System.Span<int> V_0)
IL_0000: nop
IL_0001: ldc.i4.s 12
IL_0003: conv.u
IL_0004: localloc
IL_0006: ldc.i4.3
IL_0007: newobj ""System.Span<int>..ctor(void*, int)""
IL_000c: stloc.0
IL_000d: ldc.i4.2
IL_000e: ldloc.0
IL_000f: call ""int Test.M(int, System.Span<int>)""
IL_0014: call ""void System.Console.WriteLine(int)""
IL_0019: nop
IL_001a: ret
}
");
}
[Fact]
public void NestedStackAlloc_02()
{
var source = @"
using System;
class Test
{
public static void Main()
{
int z = 2;
Console.WriteLine(M(z, stackalloc int[3]));
}
public static int M(int x, Span<int> y) => x * y.Length;
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 27 (0x1b)
.maxstack 2
.locals init (int V_0,
System.Span<int> V_1)
IL_0000: ldc.i4.2
IL_0001: stloc.0
IL_0002: ldc.i4.s 12
IL_0004: conv.u
IL_0005: localloc
IL_0007: ldc.i4.3
IL_0008: newobj ""System.Span<int>..ctor(void*, int)""
IL_000d: stloc.1
IL_000e: ldloc.0
IL_000f: ldloc.1
IL_0010: call ""int Test.M(int, System.Span<int>)""
IL_0015: call ""void System.Console.WriteLine(int)""
IL_001a: ret
}
");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 31 (0x1f)
.maxstack 2
.locals init (int V_0, //z
int V_1,
System.Span<int> V_2)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: stloc.1
IL_0005: ldc.i4.s 12
IL_0007: conv.u
IL_0008: localloc
IL_000a: ldc.i4.3
IL_000b: newobj ""System.Span<int>..ctor(void*, int)""
IL_0010: stloc.2
IL_0011: ldloc.1
IL_0012: ldloc.2
IL_0013: call ""int Test.M(int, System.Span<int>)""
IL_0018: call ""void System.Console.WriteLine(int)""
IL_001d: nop
IL_001e: ret
}
");
}
[Fact]
public void NestedStackAlloc_03()
{
var source = @"
using System;
class Test
{
public static void Main()
{
int z = 2;
Console.WriteLine(z * stackalloc int[3] { 1, stackalloc int[2] { 4, 5 }.Length, 3 }.Length);
}
public static int M(int x, Span<int> y) => x * y.Length;
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 70 (0x46)
.maxstack 4
.locals init (int V_0,
System.Span<int> V_1,
System.Span<int> V_2)
IL_0000: ldc.i4.2
IL_0001: stloc.0
IL_0002: ldc.i4.8
IL_0003: conv.u
IL_0004: localloc
IL_0006: dup
IL_0007: ldc.i4.4
IL_0008: stind.i4
IL_0009: dup
IL_000a: ldc.i4.4
IL_000b: add
IL_000c: ldc.i4.5
IL_000d: stind.i4
IL_000e: ldc.i4.2
IL_000f: newobj ""System.Span<int>..ctor(void*, int)""
IL_0014: stloc.2
IL_0015: ldc.i4.s 12
IL_0017: conv.u
IL_0018: localloc
IL_001a: dup
IL_001b: ldc.i4.1
IL_001c: stind.i4
IL_001d: dup
IL_001e: ldc.i4.4
IL_001f: add
IL_0020: ldloca.s V_2
IL_0022: call ""int System.Span<int>.Length.get""
IL_0027: stind.i4
IL_0028: dup
IL_0029: ldc.i4.2
IL_002a: conv.i
IL_002b: ldc.i4.4
IL_002c: mul
IL_002d: add
IL_002e: ldc.i4.3
IL_002f: stind.i4
IL_0030: ldc.i4.3
IL_0031: newobj ""System.Span<int>..ctor(void*, int)""
IL_0036: stloc.1
IL_0037: ldloc.0
IL_0038: ldloca.s V_1
IL_003a: call ""int System.Span<int>.Length.get""
IL_003f: mul
IL_0040: call ""void System.Console.WriteLine(int)""
IL_0045: ret
}
");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
// Code size 74 (0x4a)
.maxstack 4
.locals init (int V_0, //z
int V_1,
System.Span<int> V_2,
System.Span<int> V_3)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: stloc.1
IL_0005: ldc.i4.8
IL_0006: conv.u
IL_0007: localloc
IL_0009: dup
IL_000a: ldc.i4.4
IL_000b: stind.i4
IL_000c: dup
IL_000d: ldc.i4.4
IL_000e: add
IL_000f: ldc.i4.5
IL_0010: stind.i4
IL_0011: ldc.i4.2
IL_0012: newobj ""System.Span<int>..ctor(void*, int)""
IL_0017: stloc.3
IL_0018: ldc.i4.s 12
IL_001a: conv.u
IL_001b: localloc
IL_001d: dup
IL_001e: ldc.i4.1
IL_001f: stind.i4
IL_0020: dup
IL_0021: ldc.i4.4
IL_0022: add
IL_0023: ldloca.s V_3
IL_0025: call ""int System.Span<int>.Length.get""
IL_002a: stind.i4
IL_002b: dup
IL_002c: ldc.i4.2
IL_002d: conv.i
IL_002e: ldc.i4.4
IL_002f: mul
IL_0030: add
IL_0031: ldc.i4.3
IL_0032: stind.i4
IL_0033: ldc.i4.3
IL_0034: newobj ""System.Span<int>..ctor(void*, int)""
IL_0039: stloc.2
IL_003a: ldloc.1
IL_003b: ldloca.s V_2
IL_003d: call ""int System.Span<int>.Length.get""
IL_0042: mul
IL_0043: call ""void System.Console.WriteLine(int)""
IL_0048: nop
IL_0049: ret
}
");
}
[Fact]
public void ImplicitCastOperatorOnStackAllocIsLoweredCorrectly()
{
var source = @"
using System;
unsafe class Test
{
public static void Main()
{
Test obj1 = stackalloc int[10];
Console.Write(""|"");
Test obj2 = stackalloc double[10];
}
public static implicit operator Test(Span<int> value)
{
Console.Write(""SpanOpCalled"");
return default(Test);
}
public static implicit operator Test(double* value)
{
Console.Write(""PointerOpCalled"");
return default(Test);
}
}";
var expectedOutput = "SpanOpCalled|PointerOpCalled";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.UnsafeReleaseExe);
CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails);
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.UnsafeDebugExe);
CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails);
}
[Fact]
public void ExplicitCastOperatorOnStackAllocIsLoweredCorrectly()
{
var source = @"
using System;
unsafe class Test
{
public static void Main()
{
Test obj1 = (Test)stackalloc int[10];
}
public static explicit operator Test(Span<int> value)
{
Console.Write(""SpanOpCalled"");
return default(Test);
}
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.UnsafeReleaseExe);
CompileAndVerify(comp, expectedOutput: "SpanOpCalled", verify: Verification.Fails);
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.UnsafeDebugExe);
CompileAndVerify(comp, expectedOutput: "SpanOpCalled", verify: Verification.Fails);
}
[Fact]
public void ArrayElementCompoundAssignment_Invariant()
{
string source =
@"class C
{
static void Main()
{
F(new string[] { """" }, ""B"");
}
static void F(string[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(string[] a, string s)
{
a[0] += s;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "B");
verifier.VerifyIL("C.G",
@"{
// Code size 17 (0x11)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""string""
IL_0007: dup
IL_0008: ldind.ref
IL_0009: ldarg.1
IL_000a: call ""string string.Concat(string, string)""
IL_000f: stind.ref
IL_0010: ret
}");
}
[WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")]
[Fact]
public void ArrayElementCompoundAssignment_Covariant()
{
string source =
@"class C
{
static void Main()
{
F(new object[] { """" }, ""A"");
F(new string[] { """" }, ""B"");
}
static void F(object[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(object[] a, string s)
{
a[0] += s;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "AB");
verifier.VerifyIL("C.G",
@"{
// Code size 27 (0x1b)
.maxstack 4
.locals init (object[] V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: ldelem.ref
IL_0007: dup
IL_0008: brtrue.s IL_000e
IL_000a: pop
IL_000b: ldnull
IL_000c: br.s IL_0013
IL_000e: callvirt ""string object.ToString()""
IL_0013: ldarg.1
IL_0014: call ""string string.Concat(string, string)""
IL_0019: stelem.ref
IL_001a: ret
}");
}
[Fact]
public void ArrayElementCompoundAssignment_ValueType()
{
string source =
@"class C
{
static void Main()
{
F(new int[] { 1 }, 2);
}
static void F(int[] a, int i)
{
G(a, i);
System.Console.Write(a[0]);
}
static void G(int[] a, int i)
{
a[0] += i;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "3");
verifier.VerifyIL("C.G",
@"{
// Code size 13 (0xd)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""int""
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldarg.1
IL_000a: add
IL_000b: stind.i4
IL_000c: ret
}");
}
[WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")]
[Fact]
public void ArrayElementCompoundAssignment_Covariant_NonConstantIndex()
{
string source =
@"class C
{
static void Main()
{
F(new object[] { """" }, ""A"");
F(new string[] { """" }, ""B"");
}
static void F(object[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(object[] a, string s)
{
a[Index(a)] += s;
}
static int Index(object arg)
{
System.Console.Write(arg.GetType().Name);
return 0;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "Object[]AString[]B");
verifier.VerifyIL("C.G",
@"{
// Code size 34 (0x22)
.maxstack 4
.locals init (object[] V_0,
int V_1)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: call ""int C.Index(object)""
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: ldloc.1
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: ldelem.ref
IL_000e: dup
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_001a
IL_0015: callvirt ""string object.ToString()""
IL_001a: ldarg.1
IL_001b: call ""string string.Concat(string, string)""
IL_0020: stelem.ref
IL_0021: ret
}");
}
[Fact]
public void ArrayElementIncrement_ValueType()
{
string source =
@"class C
{
static void Main()
{
F(new int[] { 1 });
}
static void F(int[] a)
{
G(a);
System.Console.Write(a[0]);
}
static void G(int[] a)
{
a[0]++;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "2");
verifier.VerifyIL("C.G",
@"{
// Code size 13 (0xd)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""int""
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stind.i4
IL_000c: ret
}");
}
[Fact]
public void EnumConstraint_NoBoxing()
{
var code = @"
enum E1
{
A = 5
}
class Test1
{
public static void M<T>(T arg) where T : struct, System.Enum
{
}
}
class Test2
{
public void M()
{
Test1.M(E1.A);
}
}";
CompileAndVerify(code).VerifyIL("Test2.M", @"
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldc.i4.5
IL_0001: call ""void Test1.M<E1>(E1)""
IL_0006: ret
}");
}
[Fact]
public void PartialMethodsWithInParameter_WithBody()
{
CompileAndVerify(@"
partial class C
{
public void Call()
{
M(5);
}
partial void M(in int i);
}
partial class C
{
partial void M(in int i)
{
System.Console.WriteLine(i);
}
}
static class Program
{
static void Main()
{
new C().Call();
}
}",
expectedOutput: "5")
.VerifyIL("C.Call", @"
{
// Code size 11 (0xb)
.maxstack 2
.locals init (int V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stloc.0
IL_0003: ldloca.s V_0
IL_0005: call ""void C.M(in int)""
IL_000a: ret
}");
}
[Fact]
public void PartialMethodsWithInParameter_NoBody()
{
CompileAndVerify(@"
partial class C
{
public void Call()
{
M(5);
}
partial void M(in int i);
}
static class Program
{
static void Main()
{
new C().Call();
}
}")
.VerifyIL("C.Call", @"
{
// Code size 1 (0x1)
.maxstack 0
IL_0000: ret
}");
}
[Fact]
public void OverloadingPartialMethods_RefKindInWithNone_ImplementIn()
{
CompileAndVerify(@"
partial class C
{
public void Call()
{
int x = 0;
M(x);
M(in x);
}
partial void M(in int i);
partial void M(int i);
}
partial class C
{
partial void M(in int i)
{
System.Console.WriteLine(""in called"");
}
}
static class Program
{
static void Main()
{
new C().Call();
}
}",
expectedOutput: "in called");
}
[Fact]
public void OverloadingPartialMethods_RefKindInWithNone_ImplementNone()
{
CompileAndVerify(@"
partial class C
{
public void Call()
{
int x = 0;
M(x);
M(in x);
}
partial void M(in int i);
partial void M(int i);
}
partial class C
{
partial void M(int i)
{
System.Console.WriteLine(""none called"");
}
}
static class Program
{
static void Main()
{
new C().Call();
}
}",
expectedOutput: "none called");
}
[Fact]
public void OverloadingPartialMethods_RefKindInWithNone_ImplementBoth()
{
CompileAndVerify(@"
partial class C
{
public void Call()
{
int x = 0;
M(x);
M(in x);
}
partial void M(in int i);
partial void M(int i);
}
partial class C
{
partial void M(int i)
{
System.Console.WriteLine(""none called"");
}
partial void M(in int i)
{
System.Console.WriteLine(""in called"");
}
}
static class Program
{
static void Main()
{
new C().Call();
}
}",
expectedOutput: @"
none called
in called");
}
[Fact]
public void NormalizedNaN()
{
string source =
@"using System;
class Program
{
static void Main()
{
CheckNaN(double.NaN);
CheckNaN(0.0 / 0.0);
CheckNaN(0.0 / -0.0);
const double inf = 1.0 / 0.0;
CheckNaN(inf + double.NaN);
CheckNaN(inf - double.NaN);
CheckNaN(-double.NaN);
CheckNaN(float.NaN);
CheckNaN(0.0f / 0.0f);
CheckNaN(0.0f / -0.0f);
const float finf = 1.0f / 0.0f;
CheckNaN(finf + float.NaN);
CheckNaN(finf - float.NaN);
CheckNaN(-float.NaN);
}
static void CheckNaN(double nan)
{
const long expected = unchecked((long)0xFFF8000000000000UL);
long actual = BitConverter.DoubleToInt64Bits(nan);
if (expected != actual)
throw new Exception($""expected=0X{expected:X} actual=0X{actual:X}"");
}
static unsafe void CheckNaN(float nan)
{
const int expected = unchecked((int)0xFFC00000U);
void* p = &nan;
int* ip = (int*)p;
int actual = *ip;
if (expected != actual)
throw new Exception($""expected=0X{expected:X} actual=0X{actual:X}"");
}
}
";
var compilation = CompileAndVerify(source, options: TestOptions.ReleaseExe.WithAllowUnsafe(true), verify: Verification.Skipped, expectedOutput: @"");
}
[Fact]
[WorkItem(51228, "https://github.com/dotnet/roslyn/issues/51228")]
public void Issue51228()
{
var source = @"
using System;
using System.Threading.Tasks;
class Program
{
static Task<object> t;
static async Task Main(string[] args)
{
Task<object> task = MethodAsync();
GetReference(__makeref(task));
object result = await task;
System.Console.WriteLine(result);
System.Console.WriteLine(task == t);
}
static void GetReference(TypedReference reference)
{
t = __refvalue(reference, Task<object>);
System.Console.WriteLine(__reftype(reference));
}
static async Task<object> MethodAsync()
{
await Task.FromResult(1);
await Task.FromResult(2);
return ""Success"";
}
}
";
CompileAndVerify(source, expectedOutput: @"
System.Threading.Tasks.Task`1[System.Object]
Success
True
", verify: Verification.FailsILVerify with
{
ILVerifyMessage =
"""
[GetReference]: TypedReference not supported in .NET Core
[MoveNext]: TypedReference not supported in .NET Core
"""
}).VerifyDiagnostics();
}
[Fact]
public void BoxingReceiver()
{
string source = @"
class C
{
static void Main()
{
System.Console.Write(Test(new C()).ToString());
}
static System.Type Test(C c) => c.GetInt().GetType();
int GetInt() => 1;
}
";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
var verifier = CompileAndVerify(comp, expectedOutput: "System.Int32").VerifyDiagnostics();
verifier.VerifyIL("C.Test", @"
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldarg.0
IL_0001: callvirt ""int C.GetInt()""
IL_0006: box ""int""
IL_000b: call ""System.Type object.GetType()""
IL_0010: ret
}
");
}
}
}
|