File: CodeGen\CodeGenStructsAndEnum.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit\Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit.UnitTests)
// 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 Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
    public class CodeGenStructsAndEnum : EmitMetadataTestBase
    {
        #region "Struct"
 
        [Fact]
        public void ValInstanceField()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public static Boo Inst;
    }
 
    public static void Main()
    {
        Boo val = Boo.Inst;
 
        int i = val.I1;
        System.Console.Write(i);
        val.I1 = 42;
        System.Console.Write(val.I1);
        val.I1 = 7;
        System.Console.Write(val.I1);
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "0427");
 
            compilation.VerifyIL("D.Main",
@"
{
  // Code size       57 (0x39)
  .maxstack  2
  .locals init (D.Boo V_0) //val
  IL_0000:  ldsfld     ""D.Boo D.Boo.Inst""
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ldfld      ""int D.Boo.I1""
  IL_000c:  call       ""void System.Console.Write(int)""
  IL_0011:  ldloca.s   V_0
  IL_0013:  ldc.i4.s   42
  IL_0015:  stfld      ""int D.Boo.I1""
  IL_001a:  ldloc.0
  IL_001b:  ldfld      ""int D.Boo.I1""
  IL_0020:  call       ""void System.Console.Write(int)""
  IL_0025:  ldloca.s   V_0
  IL_0027:  ldc.i4.7
  IL_0028:  stfld      ""int D.Boo.I1""
  IL_002d:  ldloc.0
  IL_002e:  ldfld      ""int D.Boo.I1""
  IL_0033:  call       ""void System.Console.Write(int)""
  IL_0038:  ret
}
");
        }
 
        [Fact]
        public void ValStaticField()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public static Boo Inst;
    }
 
    public static void Main()
    {
        Boo val = Boo.Inst;
 
        System.Console.Write(Boo.Inst.I1);
 
        val.I1 = 42;
        Boo.Inst = val;
 
        System.Console.Write(Boo.Inst.I1);
    }
}
";
            var compilation = CompileAndVerify(source, expectedOutput: "042");
 
            compilation.VerifyIL("D.Main",
@"{
  // Code size       52 (0x34)
  .maxstack  2
  .locals init (D.Boo V_0) //val
  IL_0000:  ldsfld     ""D.Boo D.Boo.Inst""
  IL_0005:  stloc.0   
  IL_0006:  ldsflda    ""D.Boo D.Boo.Inst""
  IL_000b:  ldfld      ""int D.Boo.I1""
  IL_0010:  call       ""void System.Console.Write(int)""
  IL_0015:  ldloca.s   V_0
  IL_0017:  ldc.i4.s   42
  IL_0019:  stfld      ""int D.Boo.I1""
  IL_001e:  ldloc.0   
  IL_001f:  stsfld     ""D.Boo D.Boo.Inst""
  IL_0024:  ldsflda    ""D.Boo D.Boo.Inst""
  IL_0029:  ldfld      ""int D.Boo.I1""
  IL_002e:  call       ""void System.Console.Write(int)""
  IL_0033:  ret       
}
");
        }
 
        [Fact]
        public void StructCtor()
        {
            string source = @"
public class D
{
    public static void Main()
    {
        System.Decimal val = 0m;
        System.Console.Write(val);
 
        val = new System.Decimal(7);
        System.Console.Write(val);
 
        val = new System.Decimal();
        System.Console.Write(val);
 
        val = ((decimal)int.MaxValue + 1) * 4; // use the ctor that takes a long
        System.Console.Write(val);
 
    }
}
";
            var compilation = CompileAndVerify(source, expectedOutput: "0708589934592");
 
            // expect just two locals (temp is reused)
            compilation.VerifyIL("D.Main",
@"
{
  // Code size       51 (0x33)
  .maxstack  1
  IL_0000:  ldsfld     ""decimal decimal.Zero""
  IL_0005:  call       ""void System.Console.Write(decimal)""
  IL_000a:  ldc.i4.7
  IL_000b:  newobj     ""decimal..ctor(int)""
  IL_0010:  call       ""void System.Console.Write(decimal)""
  IL_0015:  ldsfld     ""decimal decimal.Zero""
  IL_001a:  call       ""void System.Console.Write(decimal)""
  IL_001f:  ldc.i8     0x200000000
  IL_0028:  newobj     ""decimal..ctor(long)""
  IL_002d:  call       ""void System.Console.Write(decimal)""
  IL_0032:  ret
}
");
        }
 
        [Fact]
        public void AddressUnbox()
        {
            string source = @"
using System;
 
class Program
{
    public struct S1
    {
        public int x;
 
        public void Goo()
        {
            x = 123;
        }
    }
 
    public static S1 goo()
    {
        return new S1();
    }
 
    static void Main()
    {
        goo().ToString();
        Console.Write(goo().x);
    }
}";
            var compilation = CompileAndVerify(source, expectedOutput: @"0");
 
            compilation.VerifyIL("Program.Main",
@"{
  // Code size       36 (0x24)
  .maxstack  1
  .locals init (Program.S1 V_0)
  IL_0000:  call       ""Program.S1 Program.goo()""
  IL_0005:  stloc.0
  IL_0006:  ldloca.s   V_0
  IL_0008:  constrained. ""Program.S1""
  IL_000e:  callvirt   ""string object.ToString()""
  IL_0013:  pop
  IL_0014:  call       ""Program.S1 Program.goo()""
  IL_0019:  ldfld      ""int Program.S1.x""
  IL_001e:  call       ""void System.Console.Write(int)""
  IL_0023:  ret
}
");
        }
 
        [Fact]
        public void EqualsHashcode()
        {
            string source = @"
using System;
 
struct S1
{
    public int field;
 
    public override bool Equals(object obj)
    {
        return obj is S1 && field == ((S1)obj).field;
    }
 
    public override int GetHashCode()
    {
        return field;
    }
 
    public static bool operator ==(S1 value1, S1 value2)
    {
        return value1.field == value2.field;
    }
 
    public static bool operator !=(S1 value1, S1 value2)
    {
        return value1.field != value2.field;
    }
}
 
class Program
{
    static void Main(string[] args)
    {
    }
}
";
            var compilation = CompileAndVerify(source, expectedOutput: @"");
 
            compilation.VerifyIL("S1.Equals(object)",
@"
{
  // Code size       30 (0x1e)
  .maxstack  2
  IL_0000:  ldarg.1
  IL_0001:  isinst     ""S1""
  IL_0006:  brfalse.s  IL_001c
  IL_0008:  ldarg.0
  IL_0009:  ldfld      ""int S1.field""
  IL_000e:  ldarg.1
  IL_000f:  unbox      ""S1""
  IL_0014:  ldfld      ""int S1.field""
  IL_0019:  ceq
  IL_001b:  ret
  IL_001c:  ldc.i4.0
  IL_001d:  ret
}
").VerifyIL("S1.GetHashCode()",
@"
{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int S1.field""
  IL_0006:  ret
}
").VerifyIL("bool S1.op_Equality(S1, S1)",
@"
{
  // Code size       15 (0xf)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int S1.field""
  IL_0006:  ldarg.1
  IL_0007:  ldfld      ""int S1.field""
  IL_000c:  ceq
  IL_000e:  ret
}
").VerifyIL("bool S1.op_Inequality(S1, S1)",
@"
{
  // Code size       18 (0x12)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int S1.field""
  IL_0006:  ldarg.1
  IL_0007:  ldfld      ""int S1.field""
  IL_000c:  ceq
  IL_000e:  ldc.i4.0
  IL_000f:  ceq
  IL_0011:  ret
}
");
        }
 
        [Fact]
        public void EmitObjectGetTypeCallOnStruct()
        {
            string source = @"
using System;
 
class Program
{
    public struct S1
    {
    }
 
    static void Main()
    {
        Console.Write((new S1()).GetType());
    }
}";
            var compilation = CompileAndVerify(source, expectedOutput: @"Program+S1");
 
            compilation.VerifyIL("Program.Main",
@"{
  // Code size       25 (0x19)
  .maxstack  1
  .locals init (Program.S1 V_0)
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""Program.S1""
  IL_0008:  ldloc.0
  IL_0009:  box        ""Program.S1""
  IL_000e:  call       ""System.Type object.GetType()""
  IL_0013:  call       ""void System.Console.Write(object)""
  IL_0018:  ret
}
");
        }
 
        [Fact]
        public void EmitInterfaceMethodOnStruct()
        {
            string source = @"
using System;
 
class Program
{
    interface I
    {
        void M();
    }
 
    struct S : I
    {
        public void M()
        {
            Console.WriteLine(""S::M"");
        }
    }
 
    static void Main(string[] args)
    {
        S s = new S();
        s.M();
        ((I)s).M();
    }
}";
            var compilation = CompileAndVerify(source, expectedOutput: @"S::M
S::M");
 
            compilation.VerifyIL("Program.Main",
@"{
  // Code size       27 (0x1b)
  .maxstack  1
  .locals init (Program.S V_0) //s
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""Program.S""
  IL_0008:  ldloca.s   V_0
  IL_000a:  call       ""void Program.S.M()""
  IL_000f:  ldloc.0
  IL_0010:  box        ""Program.S""
  IL_0015:  callvirt   ""void Program.I.M()""
  IL_001a:  ret
}
");
        }
 
        [Fact]
        public void ValueTypeWithGeneric()
        {
            string source = @"
namespace NS
{
    using System;
    using N2;
 
    namespace N2
    {
        public interface IGoo<T>
        {
            void M(T t);
        }
 
        struct S<T, V> : IGoo<T>
        {
            public S(V v)
            {
                field = v;
            }
 
            public V field;
            public void M(T t) {  Console.WriteLine(t); }
        }
    }
 
    public class Test
    {
        static S<N2, char>[] ary;
 
        class N1 { }
        class N2 : N1 { }
        
        static void Main()
        {
            IGoo<string> goo = new S<string, byte>(255);
            goo.M(""Abc"");
            Console.WriteLine(((S<string, byte>)goo).field);
 
            ary = new S<N2, char>[3];
            ary[0] = ary[1] = ary[2] = new S<N2, char>('q');
            Console.WriteLine(ary[1].field);
        }
    }
}
";
            var compilation = CompileAndVerify(source, expectedOutput: @"
Abc
255
q");
 
            compilation.VerifyIL("NS.Test.Main",
@"{
  // Code size      120 (0x78)
  .maxstack  8
  .locals init (NS.N2.S<NS.Test.N2, char> V_0)
  IL_0000:  ldc.i4     0xff
  IL_0005:  newobj     ""NS.N2.S<string, byte>..ctor(byte)""
  IL_000a:  box        ""NS.N2.S<string, byte>""
  IL_000f:  dup
  IL_0010:  ldstr      ""Abc""
  IL_0015:  callvirt   ""void NS.N2.IGoo<string>.M(string)""
  IL_001a:  unbox      ""NS.N2.S<string, byte>""
  IL_001f:  ldfld      ""byte NS.N2.S<string, byte>.field""
  IL_0024:  call       ""void System.Console.WriteLine(int)""
  IL_0029:  ldc.i4.3
  IL_002a:  newarr     ""NS.N2.S<NS.Test.N2, char>""
  IL_002f:  stsfld     ""NS.N2.S<NS.Test.N2, char>[] NS.Test.ary""
  IL_0034:  ldsfld     ""NS.N2.S<NS.Test.N2, char>[] NS.Test.ary""
  IL_0039:  ldc.i4.0
  IL_003a:  ldsfld     ""NS.N2.S<NS.Test.N2, char>[] NS.Test.ary""
  IL_003f:  ldc.i4.1
  IL_0040:  ldsfld     ""NS.N2.S<NS.Test.N2, char>[] NS.Test.ary""
  IL_0045:  ldc.i4.2
  IL_0046:  ldc.i4.s   113
  IL_0048:  newobj     ""NS.N2.S<NS.Test.N2, char>..ctor(char)""
  IL_004d:  dup
  IL_004e:  stloc.0
  IL_004f:  stelem     ""NS.N2.S<NS.Test.N2, char>""
  IL_0054:  ldloc.0
  IL_0055:  dup
  IL_0056:  stloc.0
  IL_0057:  stelem     ""NS.N2.S<NS.Test.N2, char>""
  IL_005c:  ldloc.0
  IL_005d:  stelem     ""NS.N2.S<NS.Test.N2, char>""
  IL_0062:  ldsfld     ""NS.N2.S<NS.Test.N2, char>[] NS.Test.ary""
  IL_0067:  ldc.i4.1
  IL_0068:  ldelema    ""NS.N2.S<NS.Test.N2, char>""
  IL_006d:  ldfld      ""char NS.N2.S<NS.Test.N2, char>.field""
  IL_0072:  call       ""void System.Console.WriteLine(char)""
  IL_0077:  ret
}
");
        }
 
        [WorkItem(540954, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540954")]
        [Fact]
        public void StructInit()
        {
            var text =
@"
struct Struct
{
    public static void Main()
    {
        Struct s = new Struct();
    }
}
";
            string expectedIL = @"
{
  // Code size       10 (0xa)
  .maxstack  1
  .locals init (Struct V_0) //s
  IL_0000:  nop
  IL_0001:  ldloca.s   V_0
  IL_0003:  initobj    ""Struct""
  IL_0009:  ret
}
";
            CompileAndVerify(text, options: TestOptions.DebugExe).VerifyIL("Struct.Main()", expectedIL);
        }
 
        [WorkItem(541845, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541845")]
        [Fact]
        public void ConstructEnum()
        {
            var text =
@"
using System;
 
class A
{
    enum E1
    {
        AA
    }
 
    static void Main()
    {
        var v = new DayOfWeek();
        Console.Write(v.ToString());
        var e = new E1();
        Console.WriteLine(e.ToString());
    }
}
";
            string expectedIL = @"
{
  // Code size       41 (0x29)
  .maxstack  1
  .locals init (System.DayOfWeek V_0, //v
  A.E1 V_1) //e
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldloca.s   V_0
  IL_0004:  constrained. ""System.DayOfWeek""
  IL_000a:  callvirt   ""string object.ToString()""
  IL_000f:  call       ""void System.Console.Write(string)""
  IL_0014:  ldc.i4.0
  IL_0015:  stloc.1
  IL_0016:  ldloca.s   V_1
  IL_0018:  constrained. ""A.E1""
  IL_001e:  callvirt   ""string object.ToString()""
  IL_0023:  call       ""void System.Console.WriteLine(string)""
  IL_0028:  ret
}";
            CompileAndVerify(text, expectedOutput: "SundayAA").VerifyIL("A.Main()", expectedIL);
        }
 
        [WorkItem(541599, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541599")]
        [Fact]
        public void TestStructWithStaticField01()
        {
            var source = @"
using System;
 
public struct S
{
    public static int _verify = 123;
    static void Main()
    {
        Console.Write(_verify);
    }
}
";
            CompileAndVerify(source, expectedOutput: @"123");
        }
 
        [Fact, WorkItem(543088, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543088")]
        public void UseStructLocal()
        {
            var text = @"
using System;
 
struct GetProperty
{
    int i;
    GetProperty(int x)
    {
        i = x;
    }
 
    static void Main()
    {
        GetProperty t = new GetProperty(123);
        Console.Write(t.i);
    }
}
";
 
            CompileAndVerify(text, expectedOutput: "123");
        }
 
        [Fact]
        public void InplaceInit001()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
    }
 
    public static Boo v1;
 
    public static void DummyUse(Boo arg)
    {
    }
 
    public static void Main()
    {
        Boo a1 = default(Boo);
        Boo a2 = default(Boo);
        TestInit(out a1, a2);
    }
 
    private static void TestInit(out Boo rArg, Boo vArg)
    {
        v1 = default(Boo);
        DummyUse(v1);
 
        Boo v2 = default(Boo);
        DummyUse(v2);
 
        rArg = default(Boo);
        DummyUse(rArg);
 
        vArg = default(Boo);
        DummyUse(rArg);
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "");
 
            compilation.VerifyIL("D.TestInit",
@"
{
  // Code size       73 (0x49)
  .maxstack  1
  .locals init (D.Boo V_0)
  IL_0000:  ldsflda    ""D.Boo D.v1""
  IL_0005:  initobj    ""D.Boo""
  IL_000b:  ldsfld     ""D.Boo D.v1""
  IL_0010:  call       ""void D.DummyUse(D.Boo)""
  IL_0015:  ldloca.s   V_0
  IL_0017:  initobj    ""D.Boo""
  IL_001d:  ldloc.0
  IL_001e:  call       ""void D.DummyUse(D.Boo)""
  IL_0023:  ldarg.0
  IL_0024:  initobj    ""D.Boo""
  IL_002a:  ldarg.0
  IL_002b:  ldobj      ""D.Boo""
  IL_0030:  call       ""void D.DummyUse(D.Boo)""
  IL_0035:  ldarga.s   V_1
  IL_0037:  initobj    ""D.Boo""
  IL_003d:  ldarg.0
  IL_003e:  ldobj      ""D.Boo""
  IL_0043:  call       ""void D.DummyUse(D.Boo)""
  IL_0048:  ret
}
");
        }
 
        [Fact]
        public void InplaceInit002()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
    }
 
    public static Boo v1;
 
    public static void DummyUse(Boo arg)
    {
    }
 
    public static void Main()
    {
        Boo a1 = default(Boo);
        Boo a2 = default(Boo);
        TestInit(out a1, a2);
    }
 
    private static void TestInit(out Boo rArg, Boo vArg)
    {
        try
        {
            v1 = default(Boo);
            DummyUse(v1);
 
            Boo v2 = default(Boo);
            DummyUse(v2);
 
            rArg = default(Boo);
            DummyUse(rArg);
 
            vArg = default(Boo);
            DummyUse(rArg);
        }
        catch (System.Exception) 
        {
            rArg = default(Boo);
            DummyUse(rArg);
        }
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "");
 
            compilation.VerifyIL("D.TestInit",
@"
{
  // Code size       96 (0x60)
  .maxstack  1
  .locals init (D.Boo V_0)
  .try
{
  IL_0000:  ldsflda    ""D.Boo D.v1""
  IL_0005:  initobj    ""D.Boo""
  IL_000b:  ldsfld     ""D.Boo D.v1""
  IL_0010:  call       ""void D.DummyUse(D.Boo)""
  IL_0015:  ldloca.s   V_0
  IL_0017:  initobj    ""D.Boo""
  IL_001d:  ldloc.0
  IL_001e:  call       ""void D.DummyUse(D.Boo)""
  IL_0023:  ldarg.0
  IL_0024:  initobj    ""D.Boo""
  IL_002a:  ldarg.0
  IL_002b:  ldobj      ""D.Boo""
  IL_0030:  call       ""void D.DummyUse(D.Boo)""
  IL_0035:  ldarga.s   V_1
  IL_0037:  initobj    ""D.Boo""
  IL_003d:  ldarg.0
  IL_003e:  ldobj      ""D.Boo""
  IL_0043:  call       ""void D.DummyUse(D.Boo)""
  IL_0048:  leave.s    IL_005f
}
  catch System.Exception
{
  IL_004a:  pop
  IL_004b:  ldarg.0
  IL_004c:  initobj    ""D.Boo""
  IL_0052:  ldarg.0
  IL_0053:  ldobj      ""D.Boo""
  IL_0058:  call       ""void D.DummyUse(D.Boo)""
  IL_005d:  leave.s    IL_005f
}
  IL_005f:  ret
}
");
        }
 
        [Fact]
        public void InplaceCtor001()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(int i1)
        {
            this.I1 = i1;
        }
    }
 
    public static Boo v1;
 
    public static void DummyUse(Boo arg)
    {
    }
 
    public static void Main()
    {
        Boo a1 = default(Boo);
        Boo a2 = default(Boo);
        TestInit(out a1, a2);
    }
 
    private static void TestInit(out Boo rArg, Boo vArg)
    {
        //try
        //{
            v1 = new Boo(42);
            DummyUse(v1);
 
            Boo v2 = new Boo(42);
            DummyUse(v2);
 
            rArg = new Boo(42);
            DummyUse(rArg);
 
            vArg = new Boo(42);
            DummyUse(rArg);
        //}
        //catch (System.Exception) 
        //
        //    rArg = new Boo(42);
        //    DummyUse(rArg);
        //}
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "");
 
            compilation.VerifyIL("D.TestInit",
@"
{
  // Code size       79 (0x4f)
  .maxstack  2
  IL_0000:  ldc.i4.s   42
  IL_0002:  newobj     ""D.Boo..ctor(int)""
  IL_0007:  stsfld     ""D.Boo D.v1""
  IL_000c:  ldsfld     ""D.Boo D.v1""
  IL_0011:  call       ""void D.DummyUse(D.Boo)""
  IL_0016:  ldc.i4.s   42
  IL_0018:  newobj     ""D.Boo..ctor(int)""
  IL_001d:  call       ""void D.DummyUse(D.Boo)""
  IL_0022:  ldarg.0
  IL_0023:  ldc.i4.s   42
  IL_0025:  newobj     ""D.Boo..ctor(int)""
  IL_002a:  stobj      ""D.Boo""
  IL_002f:  ldarg.0
  IL_0030:  ldobj      ""D.Boo""
  IL_0035:  call       ""void D.DummyUse(D.Boo)""
  IL_003a:  ldarga.s   V_1
  IL_003c:  ldc.i4.s   42
  IL_003e:  call       ""D.Boo..ctor(int)""
  IL_0043:  ldarg.0
  IL_0044:  ldobj      ""D.Boo""
  IL_0049:  call       ""void D.DummyUse(D.Boo)""
  IL_004e:  ret
}
");
        }
 
        [Fact]
        public void InplaceCtor002()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(int i1)
        {
            this.I1 = i1;
        }
    }
 
    public static Boo v1;
 
    public static void DummyUse(Boo arg)
    {
    }
 
    public static void Main()
    {
        Boo a1 = default(Boo);
        Boo a2 = default(Boo);
        TestInit(out a1, a2);
    }
 
    private static void TestInit(out Boo rArg, Boo vArg)
    {
        Boo v3;
        try{
            Boo v3a;
            try
            {
                v1 = new Boo(42);
                DummyUse(v1);
 
                Boo v2 = new Boo(43);
                DummyUse(v2);
 
                v3 = new Boo(44);
                v3.ToString();
 
                // should be a call, since v4 is defined in the same try scope
                Boo v4 = new Boo(45);
                v4.ToString();
 
                rArg = new Boo(46);
                DummyUse(rArg);
 
                vArg = new Boo(47);
                DummyUse(rArg);
            }
            catch (System.Exception) 
            {
                v3 = new Boo(44);
                v3.ToString();
 
                // should be a call, since v3a is defined in the same try scope
                v3a = new Boo(44);
                v3a.ToString();
 
                // should be a call, since v4 is defined in the same try scope
                Boo v4 = new Boo(45);
                v4.ToString();
 
                rArg = new Boo(48);
                DummyUse(rArg);
            }
        }
        finally
        {
        }
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "");
 
            compilation.VerifyIL("D.TestInit",
@"
{
  // Code size      222 (0xde)
  .maxstack  2
  .locals init (D.Boo V_0, //v3
                D.Boo V_1, //v3a
                D.Boo V_2, //v4
                D.Boo V_3) //v4
  .try
  {
    IL_0000:  ldc.i4.s   42
    IL_0002:  newobj     ""D.Boo..ctor(int)""
    IL_0007:  stsfld     ""D.Boo D.v1""
    IL_000c:  ldsfld     ""D.Boo D.v1""
    IL_0011:  call       ""void D.DummyUse(D.Boo)""
    IL_0016:  ldc.i4.s   43
    IL_0018:  newobj     ""D.Boo..ctor(int)""
    IL_001d:  call       ""void D.DummyUse(D.Boo)""
    IL_0022:  ldc.i4.s   44
    IL_0024:  newobj     ""D.Boo..ctor(int)""
    IL_0029:  stloc.0
    IL_002a:  ldloca.s   V_0
    IL_002c:  constrained. ""D.Boo""
    IL_0032:  callvirt   ""string object.ToString()""
    IL_0037:  pop
    IL_0038:  ldloca.s   V_2
    IL_003a:  ldc.i4.s   45
    IL_003c:  call       ""D.Boo..ctor(int)""
    IL_0041:  ldloca.s   V_2
    IL_0043:  constrained. ""D.Boo""
    IL_0049:  callvirt   ""string object.ToString()""
    IL_004e:  pop
    IL_004f:  ldarg.0
    IL_0050:  ldc.i4.s   46
    IL_0052:  newobj     ""D.Boo..ctor(int)""
    IL_0057:  stobj      ""D.Boo""
    IL_005c:  ldarg.0
    IL_005d:  ldobj      ""D.Boo""
    IL_0062:  call       ""void D.DummyUse(D.Boo)""
    IL_0067:  ldc.i4.s   47
    IL_0069:  newobj     ""D.Boo..ctor(int)""
    IL_006e:  starg.s    V_1
    IL_0070:  ldarg.0
    IL_0071:  ldobj      ""D.Boo""
    IL_0076:  call       ""void D.DummyUse(D.Boo)""
    IL_007b:  leave.s    IL_00dd
  }
  catch System.Exception
  {
    IL_007d:  pop
    IL_007e:  ldloca.s   V_0
    IL_0080:  ldc.i4.s   44
    IL_0082:  call       ""D.Boo..ctor(int)""
    IL_0087:  ldloca.s   V_0
    IL_0089:  constrained. ""D.Boo""
    IL_008f:  callvirt   ""string object.ToString()""
    IL_0094:  pop
    IL_0095:  ldloca.s   V_1
    IL_0097:  ldc.i4.s   44
    IL_0099:  call       ""D.Boo..ctor(int)""
    IL_009e:  ldloca.s   V_1
    IL_00a0:  constrained. ""D.Boo""
    IL_00a6:  callvirt   ""string object.ToString()""
    IL_00ab:  pop
    IL_00ac:  ldloca.s   V_3
    IL_00ae:  ldc.i4.s   45
    IL_00b0:  call       ""D.Boo..ctor(int)""
    IL_00b5:  ldloca.s   V_3
    IL_00b7:  constrained. ""D.Boo""
    IL_00bd:  callvirt   ""string object.ToString()""
    IL_00c2:  pop
    IL_00c3:  ldarg.0
    IL_00c4:  ldc.i4.s   48
    IL_00c6:  newobj     ""D.Boo..ctor(int)""
    IL_00cb:  stobj      ""D.Boo""
    IL_00d0:  ldarg.0
    IL_00d1:  ldobj      ""D.Boo""
    IL_00d6:  call       ""void D.DummyUse(D.Boo)""
    IL_00db:  leave.s    IL_00dd
  }
  IL_00dd:  ret
}
");
        }
 
        [WorkItem(16364, "https://github.com/dotnet/roslyn/issues/16364")]
        [Fact]
        public void InplaceCtor003()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(ref int i1)
        {            
            this.I1 = 1;
            this.I1 += i1;
        }
 
        public Boo(ref Boo b1)
        {            
            this.I1 = 1;
            this.I1 += b1.I1;
        }
    }
 
    public static Boo v1;
 
    public static void Main()
    {
        Boo a1 = default(Boo);
 
        a1 = new Boo(ref a1);
        System.Console.Write(a1.I1);
 
        v1 = new Boo(ref v1);
        System.Console.Write(v1.I1);
 
        a1 = default(Boo);
        v1 = default(Boo);
 
        a1 = new Boo(ref a1.I1);
        System.Console.Write(a1.I1);
 
        v1 = new Boo(ref v1.I1);
        System.Console.Write(v1.I1);
 
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "1111");
 
            compilation.VerifyIL("D.Main",
@"
{
  // Code size      136 (0x88)
  .maxstack  1
  .locals init (D.Boo V_0) //a1
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""D.Boo""
  IL_0008:  ldloca.s   V_0
  IL_000a:  newobj     ""D.Boo..ctor(ref D.Boo)""
  IL_000f:  stloc.0
  IL_0010:  ldloc.0
  IL_0011:  ldfld      ""int D.Boo.I1""
  IL_0016:  call       ""void System.Console.Write(int)""
  IL_001b:  ldsflda    ""D.Boo D.v1""
  IL_0020:  newobj     ""D.Boo..ctor(ref D.Boo)""
  IL_0025:  stsfld     ""D.Boo D.v1""
  IL_002a:  ldsflda    ""D.Boo D.v1""
  IL_002f:  ldfld      ""int D.Boo.I1""
  IL_0034:  call       ""void System.Console.Write(int)""
  IL_0039:  ldloca.s   V_0
  IL_003b:  initobj    ""D.Boo""
  IL_0041:  ldsflda    ""D.Boo D.v1""
  IL_0046:  initobj    ""D.Boo""
  IL_004c:  ldloca.s   V_0
  IL_004e:  ldflda     ""int D.Boo.I1""
  IL_0053:  newobj     ""D.Boo..ctor(ref int)""
  IL_0058:  stloc.0
  IL_0059:  ldloc.0
  IL_005a:  ldfld      ""int D.Boo.I1""
  IL_005f:  call       ""void System.Console.Write(int)""
  IL_0064:  ldsflda    ""D.Boo D.v1""
  IL_0069:  ldflda     ""int D.Boo.I1""
  IL_006e:  newobj     ""D.Boo..ctor(ref int)""
  IL_0073:  stsfld     ""D.Boo D.v1""
  IL_0078:  ldsflda    ""D.Boo D.v1""
  IL_007d:  ldfld      ""int D.Boo.I1""
  IL_0082:  call       ""void System.Console.Write(int)""
  IL_0087:  ret
}
");
        }
 
        [WorkItem(16364, "https://github.com/dotnet/roslyn/issues/16364")]
        [Fact]
        public void InplaceCtor004()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(ref int i1)
        {            
            this.I1 = 1;
            this.I1 += i1;
        }
 
        public Boo(ref Boo b1)
        {            
            this.I1 = 1;
            this.I1 += b1.I1;
        }
    }
 
    public static Boo v1;
 
    public static void Main()
    {
        Boo a1 = default(Boo);
 
        ref var r1 = ref a1;
        a1 = new Boo(ref r1);
        System.Console.Write(a1.I1);
 
        ref var r2 = ref v1;
        v1 = new Boo(ref r2);
        System.Console.Write(v1.I1);
 
        a1 = default(Boo);
        v1 = default(Boo);
 
        ref var r3 = ref a1.I1;
        a1 = new Boo(ref r3);
        System.Console.Write(a1.I1);
 
        ref var r4 = ref v1.I1;
        v1 = new Boo(ref r4);
        System.Console.Write(v1.I1);
 
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "1111");
 
            compilation.VerifyIL("D.Main",
@"
{
  // Code size      146 (0x92)
  .maxstack  1
  .locals init (D.Boo V_0, //a1
                D.Boo& V_1, //r1
                D.Boo& V_2, //r2
                int& V_3, //r3
                int& V_4) //r4
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""D.Boo""
  IL_0008:  ldloca.s   V_0
  IL_000a:  stloc.1
  IL_000b:  ldloc.1
  IL_000c:  newobj     ""D.Boo..ctor(ref D.Boo)""
  IL_0011:  stloc.0
  IL_0012:  ldloc.0
  IL_0013:  ldfld      ""int D.Boo.I1""
  IL_0018:  call       ""void System.Console.Write(int)""
  IL_001d:  ldsflda    ""D.Boo D.v1""
  IL_0022:  stloc.2
  IL_0023:  ldloc.2
  IL_0024:  newobj     ""D.Boo..ctor(ref D.Boo)""
  IL_0029:  stsfld     ""D.Boo D.v1""
  IL_002e:  ldsflda    ""D.Boo D.v1""
  IL_0033:  ldfld      ""int D.Boo.I1""
  IL_0038:  call       ""void System.Console.Write(int)""
  IL_003d:  ldloca.s   V_0
  IL_003f:  initobj    ""D.Boo""
  IL_0045:  ldsflda    ""D.Boo D.v1""
  IL_004a:  initobj    ""D.Boo""
  IL_0050:  ldloca.s   V_0
  IL_0052:  ldflda     ""int D.Boo.I1""
  IL_0057:  stloc.3
  IL_0058:  ldloc.3
  IL_0059:  newobj     ""D.Boo..ctor(ref int)""
  IL_005e:  stloc.0
  IL_005f:  ldloc.0
  IL_0060:  ldfld      ""int D.Boo.I1""
  IL_0065:  call       ""void System.Console.Write(int)""
  IL_006a:  ldsflda    ""D.Boo D.v1""
  IL_006f:  ldflda     ""int D.Boo.I1""
  IL_0074:  stloc.s    V_4
  IL_0076:  ldloc.s    V_4
  IL_0078:  newobj     ""D.Boo..ctor(ref int)""
  IL_007d:  stsfld     ""D.Boo D.v1""
  IL_0082:  ldsflda    ""D.Boo D.v1""
  IL_0087:  ldfld      ""int D.Boo.I1""
  IL_008c:  call       ""void System.Console.Write(int)""
  IL_0091:  ret
}
");
        }
 
        [WorkItem(16364, "https://github.com/dotnet/roslyn/issues/16364")]
        [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)]
        public void InplaceCtor005()
        {
            string source = @"
using System;
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(int x, __arglist)
        {
            this.I1 = 1;
            this.I1 += __refvalue(new ArgIterator(__arglist).GetNextArg(), Boo).I1;
        }
    }
 
    public static Boo v1;
 
    public static void Main()
    {
        Boo a1 = default(Boo);
 
        a1 = new Boo(1, __arglist(ref a1));
        System.Console.Write(a1.I1);
 
        v1 = new Boo(1, __arglist(ref v1));
        System.Console.Write(v1.I1);
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "11");
 
            compilation.VerifyIL("D.Main",
@"
{
  // Code size       60 (0x3c)
  .maxstack  2
  .locals init (D.Boo V_0) //a1
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""D.Boo""
  IL_0008:  ldc.i4.1
  IL_0009:  ldloca.s   V_0
  IL_000b:  newobj     ""D.Boo..ctor(int, __arglist) with __arglist( ref D.Boo)""
  IL_0010:  stloc.0
  IL_0011:  ldloc.0
  IL_0012:  ldfld      ""int D.Boo.I1""
  IL_0017:  call       ""void System.Console.Write(int)""
  IL_001c:  ldc.i4.1
  IL_001d:  ldsflda    ""D.Boo D.v1""
  IL_0022:  newobj     ""D.Boo..ctor(int, __arglist) with __arglist( ref D.Boo)""
  IL_0027:  stsfld     ""D.Boo D.v1""
  IL_002c:  ldsflda    ""D.Boo D.v1""
  IL_0031:  ldfld      ""int D.Boo.I1""
  IL_0036:  call       ""void System.Console.Write(int)""
  IL_003b:  ret
}
");
        }
 
        [Fact]
        public void InitUsed001()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(int i1)
        {
            this.I1 = i1;
        }
    }
 
    public static Boo v1;
 
    public static void DummyUse(Boo arg)
    {
    }
 
    public static void DummyUse1(ref Boo arg)
    {
    }
 
    public static void Main()
    {
        Boo a1 = default(Boo);
        Boo a2 = default(Boo);
        TestInit(out a1, a2);
    }
 
    private static void TestInit(out Boo rArg, Boo vArg)
    {
        DummyUse(v1 = default(Boo));
        DummyUse(v1);
 
        Boo v2;
        DummyUse(v2 = default(Boo));
        DummyUse(v2);
 
        // TODO: no need for a temp
        Boo v2a;
        DummyUse(v2a = default(Boo));
        DummyUse1(ref v2a);
 
        DummyUse(rArg = default(Boo));
        DummyUse(rArg);
 
        // TODO: no need for a temp
        DummyUse(vArg = default(Boo));
        DummyUse(vArg);
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "");
 
            compilation.VerifyIL("D.TestInit",
@"
{
  // Code size      126 (0x7e)
  .maxstack  3
  .locals init (D.Boo V_0, //v2a
  D.Boo V_1)
  IL_0000:  ldloca.s   V_1
  IL_0002:  initobj    ""D.Boo""
  IL_0008:  ldloc.1
  IL_0009:  dup
  IL_000a:  stsfld     ""D.Boo D.v1""
  IL_000f:  call       ""void D.DummyUse(D.Boo)""
  IL_0014:  ldsfld     ""D.Boo D.v1""
  IL_0019:  call       ""void D.DummyUse(D.Boo)""
  IL_001e:  ldloca.s   V_1
  IL_0020:  initobj    ""D.Boo""
  IL_0026:  ldloc.1
  IL_0027:  dup
  IL_0028:  call       ""void D.DummyUse(D.Boo)""
  IL_002d:  call       ""void D.DummyUse(D.Boo)""
  IL_0032:  ldloca.s   V_0
  IL_0034:  initobj    ""D.Boo""
  IL_003a:  ldloc.0
  IL_003b:  call       ""void D.DummyUse(D.Boo)""
  IL_0040:  ldloca.s   V_0
  IL_0042:  call       ""void D.DummyUse1(ref D.Boo)""
  IL_0047:  ldarg.0
  IL_0048:  ldloca.s   V_1
  IL_004a:  initobj    ""D.Boo""
  IL_0050:  ldloc.1
  IL_0051:  dup
  IL_0052:  stloc.1
  IL_0053:  stobj      ""D.Boo""
  IL_0058:  ldloc.1
  IL_0059:  call       ""void D.DummyUse(D.Boo)""
  IL_005e:  ldarg.0
  IL_005f:  ldobj      ""D.Boo""
  IL_0064:  call       ""void D.DummyUse(D.Boo)""
  IL_0069:  ldarga.s   V_1
  IL_006b:  initobj    ""D.Boo""
  IL_0071:  ldarg.1
  IL_0072:  call       ""void D.DummyUse(D.Boo)""
  IL_0077:  ldarg.1
  IL_0078:  call       ""void D.DummyUse(D.Boo)""
  IL_007d:  ret
}
");
        }
 
        [Fact]
        public void CtorUsed001()
        {
            string source = @"
 
public class D
{
    public struct Boo
    {
        public int I1;
 
        public Boo(int i1)
        {
            this.I1 = i1;
        }
    }
 
    public static Boo v1;
 
    public static void DummyUse(Boo arg)
    {
    }
 
    public static void DummyUse1(ref Boo arg)
    {
    }
 
    public static void Main()
    {
        Boo a1 = default(Boo);
        Boo a2 = default(Boo);
        TestInit(out a1, a2);
    }
 
    private static void TestInit(out Boo rArg, Boo vArg)
    {
        DummyUse(v1 = new Boo(42));
        DummyUse(v1);
 
        Boo v2;
        DummyUse(v2 = new Boo(42));
        DummyUse(v2);
 
        Boo v2a;
        DummyUse(v2a = new Boo(42));
        DummyUse1(ref v2a);
 
        DummyUse(rArg = new Boo(42));
        DummyUse(rArg);
 
        DummyUse(vArg = new Boo(42));
        DummyUse(vArg);
    }
}
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "");
 
            compilation.VerifyIL("D.TestInit",
@"
{
  // Code size      122 (0x7a)
  .maxstack  3
  .locals init (D.Boo V_0, //v2a
  D.Boo V_1)
  IL_0000:  ldc.i4.s   42
  IL_0002:  newobj     ""D.Boo..ctor(int)""
  IL_0007:  dup
  IL_0008:  stsfld     ""D.Boo D.v1""
  IL_000d:  call       ""void D.DummyUse(D.Boo)""
  IL_0012:  ldsfld     ""D.Boo D.v1""
  IL_0017:  call       ""void D.DummyUse(D.Boo)""
  IL_001c:  ldc.i4.s   42
  IL_001e:  newobj     ""D.Boo..ctor(int)""
  IL_0023:  dup
  IL_0024:  call       ""void D.DummyUse(D.Boo)""
  IL_0029:  call       ""void D.DummyUse(D.Boo)""
  IL_002e:  ldloca.s   V_0
  IL_0030:  ldc.i4.s   42
  IL_0032:  call       ""D.Boo..ctor(int)""
  IL_0037:  ldloc.0
  IL_0038:  call       ""void D.DummyUse(D.Boo)""
  IL_003d:  ldloca.s   V_0
  IL_003f:  call       ""void D.DummyUse1(ref D.Boo)""
  IL_0044:  ldarg.0
  IL_0045:  ldc.i4.s   42
  IL_0047:  newobj     ""D.Boo..ctor(int)""
  IL_004c:  dup
  IL_004d:  stloc.1
  IL_004e:  stobj      ""D.Boo""
  IL_0053:  ldloc.1
  IL_0054:  call       ""void D.DummyUse(D.Boo)""
  IL_0059:  ldarg.0
  IL_005a:  ldobj      ""D.Boo""
  IL_005f:  call       ""void D.DummyUse(D.Boo)""
  IL_0064:  ldarga.s   V_1
  IL_0066:  ldc.i4.s   42
  IL_0068:  call       ""D.Boo..ctor(int)""
  IL_006d:  ldarg.1
  IL_006e:  call       ""void D.DummyUse(D.Boo)""
  IL_0073:  ldarg.1
  IL_0074:  call       ""void D.DummyUse(D.Boo)""
  IL_0079:  ret
}
");
        }
 
        [Fact]
        public void InheritedCallOnReadOnly()
        {
            string source = @"
    class Program
    {
        static void Main()
        {
            var obj = new C1();
            System.Console.WriteLine(obj.field.ToString());
        }
    }
 
    class C1
    {
        public readonly S1 field;
    }
 
    struct S1
    {
    }
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "S1", verify: Verification.Skipped);
 
            compilation.VerifyIL("Program.Main", @"
{
  // Code size       30 (0x1e)
  .maxstack  1
  .locals init (S1 V_0)
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  ldfld      ""S1 C1.field""
  IL_000a:  stloc.0
  IL_000b:  ldloca.s   V_0
  IL_000d:  constrained. ""S1""
  IL_0013:  callvirt   ""string object.ToString()""
  IL_0018:  call       ""void System.Console.WriteLine(string)""
  IL_001d:  ret
}
");
            compilation = CompileAndVerify(source, expectedOutput: "S1", parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
 
            compilation.VerifyIL("Program.Main",
@"
{
  // Code size       30 (0x1e)
  .maxstack  1
  .locals init (S1 V_0)
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  ldfld      ""S1 C1.field""
  IL_000a:  stloc.0
  IL_000b:  ldloca.s   V_0
  IL_000d:  constrained. ""S1""
  IL_0013:  callvirt   ""string object.ToString()""
  IL_0018:  call       ""void System.Console.WriteLine(string)""
  IL_001d:  ret
}
");
        }
 
        [Fact]
        [WorkItem(27049, "https://github.com/dotnet/roslyn/issues/27049")]
        public void BoxingRefStructForBaseCall()
        {
            CreateCompilation(@"
ref struct S
{
    public override bool Equals(object obj) => base.Equals(obj);
 
    public override int GetHashCode() => base.GetHashCode();
 
    public override string ToString() => base.ToString();
}").VerifyDiagnostics(
                // (4,48): error CS0029: Cannot implicitly convert type 'S' to 'System.ValueType'
                //     public override bool Equals(object obj) => base.Equals(obj);
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "base").WithArguments("S", "System.ValueType").WithLocation(4, 48),
                // (6,42): error CS0029: Cannot implicitly convert type 'S' to 'System.ValueType'
                //     public override int GetHashCode() => base.GetHashCode();
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "base").WithArguments("S", "System.ValueType").WithLocation(6, 42),
                // (8,42): error CS0029: Cannot implicitly convert type 'S' to 'System.ValueType'
                //     public override string ToString() => base.ToString();
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "base").WithArguments("S", "System.ValueType").WithLocation(8, 42));
        }
 
        #endregion
        #region "Enum"
 
        [Fact]
        public void TestEnum()
        {
            string source =
@"enum E { A, B }
class C
{
    static void Main()
    {
        E e = E.A;
        e = e + 1;
    }
}
";
            var compilation = CompileAndVerify(source);
 
            compilation.VerifyIL("C.Main",
@"{
  // Code size        3 (0x3)
  .maxstack  1
  IL_0000:  ldc.i4.0
  IL_0001:  pop
  IL_0002:  ret
}
");
        }
 
        [Fact]
        public void BoxEnum()
        {
            string source =
@"enum E { A, B }
class C
{
    static void Main()
    {
        E e = E.B;
        object o = e;
        e = (E)o;
        System.Console.Write(e);
    }
}
";
            var compilation = CompileAndVerify(source, expectedOutput: "B");
 
            compilation.VerifyIL("C.Main",
@"{
  // Code size       22 (0x16)
  .maxstack  1
  IL_0000:  ldc.i4.1
  IL_0001:  box        ""E""
  IL_0006:  unbox.any  ""E""
  IL_000b:  box        ""E""
  IL_0010:  call       ""void System.Console.Write(object)""
  IL_0015:  ret
}
");
        }
 
        [Fact]
        public void MBRO_StructField()
        {
            string source =
@"
    using System;
 
    class Program
    {
        static void Main(string[] args)
        {
            var v = new cls1();
            v.Test();
        }
    }
 
    struct S1
    {
        public Guid g;
    }
 
    class cls1 : MarshalByRefObject
    {
        public Guid g1;
        public S1 s;
 
        public void Test()
        {
            g1 = new Guid();
            TestRef(ref g1);
            g1 = new Guid(g1.ToString());
            System.Console.WriteLine(g1);
            System.Console.WriteLine(s.g.ToString());
 
            var other = new cls1();
            other.g1 = new Guid();
            System.Console.WriteLine(other.g1);
            TestRef(ref other.g1);
            other.g1 = new Guid(other.g1.ToString());
            System.Console.WriteLine(other.g1);
            System.Console.WriteLine(other.s.g.ToString());
 
            var gg = other.s.g;
            System.Console.WriteLine(gg);
        }
 
        public void TestRef(ref Guid arg)
        {
            arg = new Guid(""ca761232ed4211cebacd00aa0057b223"");
        }
    }
 
";
            var compilation = CompileAndVerify(source, expectedOutput: @"ca761232-ed42-11ce-bacd-00aa0057b223
00000000-0000-0000-0000-000000000000
00000000-0000-0000-0000-000000000000
ca761232-ed42-11ce-bacd-00aa0057b223
00000000-0000-0000-0000-000000000000
00000000-0000-0000-0000-000000000000");
 
            compilation.VerifyIL("cls1.Test",
@"
{
  // Code size      237 (0xed)
  .maxstack  2
  .locals init (cls1 V_0, //other
  System.Guid V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldflda     ""System.Guid cls1.g1""
  IL_0006:  initobj    ""System.Guid""
  IL_000c:  ldarg.0
  IL_000d:  ldarg.0
  IL_000e:  ldflda     ""System.Guid cls1.g1""
  IL_0013:  call       ""void cls1.TestRef(ref System.Guid)""
  IL_0018:  ldarg.0
  IL_0019:  ldarg.0
  IL_001a:  ldflda     ""System.Guid cls1.g1""
  IL_001f:  constrained. ""System.Guid""
  IL_0025:  callvirt   ""string object.ToString()""
  IL_002a:  newobj     ""System.Guid..ctor(string)""
  IL_002f:  stfld      ""System.Guid cls1.g1""
  IL_0034:  ldarg.0
  IL_0035:  ldfld      ""System.Guid cls1.g1""
  IL_003a:  box        ""System.Guid""
  IL_003f:  call       ""void System.Console.WriteLine(object)""
  IL_0044:  ldarg.0
  IL_0045:  ldflda     ""S1 cls1.s""
  IL_004a:  ldflda     ""System.Guid S1.g""
  IL_004f:  constrained. ""System.Guid""
  IL_0055:  callvirt   ""string object.ToString()""
  IL_005a:  call       ""void System.Console.WriteLine(string)""
  IL_005f:  newobj     ""cls1..ctor()""
  IL_0064:  stloc.0
  IL_0065:  ldloc.0
  IL_0066:  ldloca.s   V_1
  IL_0068:  initobj    ""System.Guid""
  IL_006e:  ldloc.1
  IL_006f:  stfld      ""System.Guid cls1.g1""
  IL_0074:  ldloc.0
  IL_0075:  ldfld      ""System.Guid cls1.g1""
  IL_007a:  box        ""System.Guid""
  IL_007f:  call       ""void System.Console.WriteLine(object)""
  IL_0084:  ldarg.0
  IL_0085:  ldloc.0
  IL_0086:  ldflda     ""System.Guid cls1.g1""
  IL_008b:  call       ""void cls1.TestRef(ref System.Guid)""
  IL_0090:  ldloc.0
  IL_0091:  ldloc.0
  IL_0092:  ldflda     ""System.Guid cls1.g1""
  IL_0097:  constrained. ""System.Guid""
  IL_009d:  callvirt   ""string object.ToString()""
  IL_00a2:  newobj     ""System.Guid..ctor(string)""
  IL_00a7:  stfld      ""System.Guid cls1.g1""
  IL_00ac:  ldloc.0
  IL_00ad:  ldfld      ""System.Guid cls1.g1""
  IL_00b2:  box        ""System.Guid""
  IL_00b7:  call       ""void System.Console.WriteLine(object)""
  IL_00bc:  ldloc.0
  IL_00bd:  ldflda     ""S1 cls1.s""
  IL_00c2:  ldflda     ""System.Guid S1.g""
  IL_00c7:  constrained. ""System.Guid""
  IL_00cd:  callvirt   ""string object.ToString()""
  IL_00d2:  call       ""void System.Console.WriteLine(string)""
  IL_00d7:  ldloc.0
  IL_00d8:  ldfld      ""S1 cls1.s""
  IL_00dd:  ldfld      ""System.Guid S1.g""
  IL_00e2:  box        ""System.Guid""
  IL_00e7:  call       ""void System.Console.WriteLine(object)""
  IL_00ec:  ret
}
");
        }
 
        [Fact]
        public void InitTemp001()
        {
            string source = @"
 
using System;
 
struct S
{
    int x;
 
    static void Main()
    {
        Console.WriteLine(new S { x = 0 }.Equals(new S { x = 1 }));
    }
}
 
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "False");
 
            compilation.VerifyIL("S.Main",
@"
{
  // Code size       57 (0x39)
  .maxstack  3
  .locals init (S V_0,
  S V_1)
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""S""
  IL_0008:  ldloca.s   V_0
  IL_000a:  ldc.i4.0
  IL_000b:  stfld      ""int S.x""
  IL_0010:  ldloca.s   V_0
  IL_0012:  ldloca.s   V_1
  IL_0014:  initobj    ""S""
  IL_001a:  ldloca.s   V_1
  IL_001c:  ldc.i4.1
  IL_001d:  stfld      ""int S.x""
  IL_0022:  ldloc.1
  IL_0023:  box        ""S""
  IL_0028:  constrained. ""S""
  IL_002e:  callvirt   ""bool object.Equals(object)""
  IL_0033:  call       ""void System.Console.WriteLine(bool)""
  IL_0038:  ret
}
");
        }
 
        [Fact]
        public void InitTemp001a()
        {
            string source = @"
 
using System;
 
struct S1
{
    public int x;
}
 
struct S
{
    public S1 x;
 
    
 
    static void Main()
    {
        Console.WriteLine(new S { x = new S1{x=0} }.x.Equals(new S { x = new S1{x=1} }));
    }
}
 
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "False");
 
            compilation.VerifyIL("S.Main",
@"
{
  // Code size       94 (0x5e)
  .maxstack  4
  .locals init (S V_0,
                S1 V_1,
                S V_2)
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""S""
  IL_0008:  ldloca.s   V_0
  IL_000a:  ldloca.s   V_1
  IL_000c:  initobj    ""S1""
  IL_0012:  ldloca.s   V_1
  IL_0014:  ldc.i4.0
  IL_0015:  stfld      ""int S1.x""
  IL_001a:  ldloc.1
  IL_001b:  stfld      ""S1 S.x""
  IL_0020:  ldloca.s   V_0
  IL_0022:  ldflda     ""S1 S.x""
  IL_0027:  ldloca.s   V_2
  IL_0029:  initobj    ""S""
  IL_002f:  ldloca.s   V_2
  IL_0031:  ldloca.s   V_1
  IL_0033:  initobj    ""S1""
  IL_0039:  ldloca.s   V_1
  IL_003b:  ldc.i4.1
  IL_003c:  stfld      ""int S1.x""
  IL_0041:  ldloc.1
  IL_0042:  stfld      ""S1 S.x""
  IL_0047:  ldloc.2
  IL_0048:  box        ""S""
  IL_004d:  constrained. ""S1""
  IL_0053:  callvirt   ""bool object.Equals(object)""
  IL_0058:  call       ""void System.Console.WriteLine(bool)""
  IL_005d:  ret
}
");
        }
 
        [Fact]
        public void InitTemp001b()
        {
            string source = @"
 
using System;
 
class S1
{
    public int x;
}
 
struct S
{
    public S1 x;
 
    
 
    static void Main()
    {
        Console.WriteLine(new S { x = new S1{x=0} }.x.Equals(new S { x = new S1{x=1} }));
    }
}
 
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "False");
 
            compilation.VerifyIL("S.Main",
@"
{
  // Code size       77 (0x4d)
  .maxstack  5
  .locals init (S V_0)
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""S""
  IL_0008:  ldloca.s   V_0
  IL_000a:  newobj     ""S1..ctor()""
  IL_000f:  dup
  IL_0010:  ldc.i4.0
  IL_0011:  stfld      ""int S1.x""
  IL_0016:  stfld      ""S1 S.x""
  IL_001b:  ldloc.0
  IL_001c:  ldfld      ""S1 S.x""
  IL_0021:  ldloca.s   V_0
  IL_0023:  initobj    ""S""
  IL_0029:  ldloca.s   V_0
  IL_002b:  newobj     ""S1..ctor()""
  IL_0030:  dup
  IL_0031:  ldc.i4.1
  IL_0032:  stfld      ""int S1.x""
  IL_0037:  stfld      ""S1 S.x""
  IL_003c:  ldloc.0
  IL_003d:  box        ""S""
  IL_0042:  callvirt   ""bool object.Equals(object)""
  IL_0047:  call       ""void System.Console.WriteLine(bool)""
  IL_004c:  ret
}
");
        }
 
        [Fact]
        public void InitTemp002()
        {
            string source = @"
using System;
 
struct S
{
    int x;
 
    static void Main()
    {
        Console.WriteLine(new S { x = 0 }.Equals(new S { x = 1 }).Equals(
                          new S { x = 1 }.Equals(new S { x = 1 })));
    }
}
 
";
 
            var compilation = CompileAndVerify(source, expectedOutput: "False");
 
            compilation.VerifyIL("S.Main",
@"
{
  // Code size      116 (0x74)
  .maxstack  4
  .locals init (S V_0,
                S V_1,
                bool V_2,
                S V_3)
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""S""
  IL_0008:  ldloca.s   V_0
  IL_000a:  ldc.i4.0
  IL_000b:  stfld      ""int S.x""
  IL_0010:  ldloca.s   V_0
  IL_0012:  ldloca.s   V_1
  IL_0014:  initobj    ""S""
  IL_001a:  ldloca.s   V_1
  IL_001c:  ldc.i4.1
  IL_001d:  stfld      ""int S.x""
  IL_0022:  ldloc.1
  IL_0023:  box        ""S""
  IL_0028:  constrained. ""S""
  IL_002e:  callvirt   ""bool object.Equals(object)""
  IL_0033:  stloc.2
  IL_0034:  ldloca.s   V_2
  IL_0036:  ldloca.s   V_1
  IL_0038:  initobj    ""S""
  IL_003e:  ldloca.s   V_1
  IL_0040:  ldc.i4.1
  IL_0041:  stfld      ""int S.x""
  IL_0046:  ldloca.s   V_1
  IL_0048:  ldloca.s   V_3
  IL_004a:  initobj    ""S""
  IL_0050:  ldloca.s   V_3
  IL_0052:  ldc.i4.1
  IL_0053:  stfld      ""int S.x""
  IL_0058:  ldloc.3
  IL_0059:  box        ""S""
  IL_005e:  constrained. ""S""
  IL_0064:  callvirt   ""bool object.Equals(object)""
  IL_0069:  call       ""bool bool.Equals(bool)""
  IL_006e:  call       ""void System.Console.WriteLine(bool)""
  IL_0073:  ret
}
");
        }
 
        [Fact]
        public void InitTemp003()
        {
            string source = @"
using System;
 
readonly struct S
{
    readonly int x;
 
    public S(int x)
    {
        this.x = x;
    }
 
    static void Main()
    {
        // named argument reordering introduces a sequence with temps
        // and we cannot know whether RefMethod returns a ref to a sequence local
        // so we must assume that it can, and therefore must keep all the sequence the locals in use 
        // for the duration of the most-encompassing expression.
        Console.WriteLine(RefMethod(arg2: I(5), arg1: I(3)).GreaterThan(
                          RefMethod(arg2: I(0), arg1: I(0))));
    }
 
    public static ref readonly S RefMethod(in S arg1, in S arg2)
    {
        return ref arg2;
    }
 
    public bool GreaterThan(in S arg)
    {
        return this.x > arg.x;
    }
 
    public static S I(int arg)
    {
        return new S(arg);
    }
}
 
";
 
            var compilation = CompileAndVerify(source, verify: Verification.Fails, expectedOutput: "True");
 
            compilation.VerifyIL("S.Main",
@"
{
  // Code size       57 (0x39)
  .maxstack  3
  .locals init (S V_0,
                S V_1,
                S V_2,
                S V_3)
  IL_0000:  ldc.i4.5
  IL_0001:  call       ""S S.I(int)""
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.3
  IL_0008:  call       ""S S.I(int)""
  IL_000d:  stloc.1
  IL_000e:  ldloca.s   V_1
  IL_0010:  ldloca.s   V_0
  IL_0012:  call       ""ref readonly S S.RefMethod(in S, in S)""
  IL_0017:  ldc.i4.0
  IL_0018:  call       ""S S.I(int)""
  IL_001d:  stloc.2
  IL_001e:  ldc.i4.0
  IL_001f:  call       ""S S.I(int)""
  IL_0024:  stloc.3
  IL_0025:  ldloca.s   V_3
  IL_0027:  ldloca.s   V_2
  IL_0029:  call       ""ref readonly S S.RefMethod(in S, in S)""
  IL_002e:  call       ""bool S.GreaterThan(in S)""
  IL_0033:  call       ""void System.Console.WriteLine(bool)""
  IL_0038:  ret
}
");
        }
 
        [Fact]
        public void InitTemp004()
        {
            string source = @"
using System;
 
readonly struct S
{
    public readonly int x;
 
    public S(int x)
    {
        this.x = x;
    }
 
    static void Main()
    {
        System.Console.Write(TestRO().x);
        System.Console.WriteLine();
        System.Console.Write(Test().x);
    }
 
    static ref readonly S TestRO()
    {
        try
        {
            // both args are refs
            return ref RefMethodRO(arg2: I(5), arg1: I(3));
        }
        finally
        {
            // first arg is a value!!
            RefMethodRO(arg2: I_Val(5), arg1: I(3));
        }
    }
 
    public static ref readonly S RefMethodRO(in S arg1, in S arg2)
    {
        System.Console.Write(arg2.x);
        return ref arg2;
    }
 
    // similar as above, but with regular (not readonly) refs for comparison
    static ref S Test()
    {
        try
        {
            return ref RefMethod(arg2: ref I(5), arg1: ref I(3));
        }
        finally
        {
            var temp = I(5);
            RefMethod(arg2: ref temp, arg1: ref I(3));
        }
    }
 
    public static ref S RefMethod(ref S arg1, ref S arg2)
    {
        System.Console.Write(arg2.x);
        return ref arg2;
    }
 
    private static S[] arr = new S[] { new S() };
 
    public static ref S I(int arg)
    {
        arr[0] = new S(arg);
        return ref arr[0];
    }
 
    public static S I_Val(int arg)
    {
        arr[0] = new S(arg);
        return arr[0];
    }
}
 
";
 
            var compilation = CompileAndVerify(source, verify: Verification.Fails, expectedOutput: @"353
353");
 
            compilation.VerifyIL("S.TestRO",
@"
{
  // Code size       46 (0x2e)
  .maxstack  2
  .locals init (S& V_0,
                S& V_1,
                S V_2)
  .try
  {
    IL_0000:  ldc.i4.5
    IL_0001:  call       ""ref S S.I(int)""
    IL_0006:  stloc.0
    IL_0007:  ldc.i4.3
    IL_0008:  call       ""ref S S.I(int)""
    IL_000d:  ldloc.0
    IL_000e:  call       ""ref readonly S S.RefMethodRO(in S, in S)""
    IL_0013:  stloc.1
    IL_0014:  leave.s    IL_002c
  }
  finally
  {
    IL_0016:  ldc.i4.5
    IL_0017:  call       ""S S.I_Val(int)""
    IL_001c:  stloc.2
    IL_001d:  ldc.i4.3
    IL_001e:  call       ""ref S S.I(int)""
    IL_0023:  ldloca.s   V_2
    IL_0025:  call       ""ref readonly S S.RefMethodRO(in S, in S)""
    IL_002a:  pop
    IL_002b:  endfinally
  }
  IL_002c:  ldloc.1
  IL_002d:  ret
}
");
        }
 
        [WorkItem(842477, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/842477")]
        [Fact]
        public void DecimalConst()
        {
            string source = @"
 
#pragma warning disable 458, 169, 414
using System;
 
public class NullableTest
{
	static decimal? NULL = null;
 
	public static void EqualEqual()
	{
		Test.Eval((decimal?)1m == null, false);
		Test.Eval((decimal?)1m == NULL, false);
		Test.Eval((decimal?)0 == NULL, false);		
	}
}
 
public class Test
{
    public static void Eval(object obj1, object obj2)
    {
    }
}
 
 
";
 
            var compilation = CompileAndVerify(source);
 
            compilation.VerifyIL("NullableTest.EqualEqual",
@"
{
  // Code size      112 (0x70)
  .maxstack  2
  .locals init (decimal? V_0)
  IL_0000:  ldc.i4.0
  IL_0001:  box        ""bool""
  IL_0006:  ldc.i4.0
  IL_0007:  box        ""bool""
  IL_000c:  call       ""void Test.Eval(object, object)""
  IL_0011:  ldsfld     ""decimal decimal.One""
  IL_0016:  ldsfld     ""decimal? NullableTest.NULL""
  IL_001b:  stloc.0
  IL_001c:  ldloca.s   V_0
  IL_001e:  call       ""decimal decimal?.GetValueOrDefault()""
  IL_0023:  call       ""bool decimal.op_Equality(decimal, decimal)""
  IL_0028:  ldloca.s   V_0
  IL_002a:  call       ""bool decimal?.HasValue.get""
  IL_002f:  and
  IL_0030:  box        ""bool""
  IL_0035:  ldc.i4.0
  IL_0036:  box        ""bool""
  IL_003b:  call       ""void Test.Eval(object, object)""
  IL_0040:  ldsfld     ""decimal decimal.Zero""
  IL_0045:  ldsfld     ""decimal? NullableTest.NULL""
  IL_004a:  stloc.0
  IL_004b:  ldloca.s   V_0
  IL_004d:  call       ""decimal decimal?.GetValueOrDefault()""
  IL_0052:  call       ""bool decimal.op_Equality(decimal, decimal)""
  IL_0057:  ldloca.s   V_0
  IL_0059:  call       ""bool decimal?.HasValue.get""
  IL_005e:  and
  IL_005f:  box        ""bool""
  IL_0064:  ldc.i4.0
  IL_0065:  box        ""bool""
  IL_006a:  call       ""void Test.Eval(object, object)""
  IL_006f:  ret
}
");
        }
 
        [Fact]
        public void FieldLoad001()
        {
            string source = @"
    using System;
 
    struct Point
    {
        public int x;
        public int y;
    }
 
    class Rectangle
    {
        public Point topLeft;
        public Point bottomRight;
    }
 
    struct C1
    {
        public C1(int i)
        {
            r = new Rectangle();
        }
 
        public Rectangle r;
    }
 
    class Program
    {
        static object p = new C1(1);
 
        static void Main(string[] args)
        {
            System.Console.WriteLine(((C1)p).r.topLeft.x);
        }
    }
 
";
            var compilation = CompileAndVerify(source, expectedOutput: "0");
 
            compilation.VerifyIL("Program.Main",
@"
{
  // Code size       31 (0x1f)
  .maxstack  1
  IL_0000:  ldsfld     ""object Program.p""
  IL_0005:  unbox      ""C1""
  IL_000a:  ldfld      ""Rectangle C1.r""
  IL_000f:  ldflda     ""Point Rectangle.topLeft""
  IL_0014:  ldfld      ""int Point.x""
  IL_0019:  call       ""void System.Console.WriteLine(int)""
  IL_001e:  ret
}
");
        }
 
        #endregion
    }
}