/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConversionTests.cs
1 260 строк
29 KB
Jared Parsons
Move net451 test assets to net461 (#74766)
17 авг 2024, 19:21
Не верифицирован
17 авг 2024, 19:21
75b26a2
Код
Авторство
О чём код?
// 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.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; 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 CodeGenConversionTests : CSharpTestBase { [Fact] public void ExplicitConversionRuntimeGrabbag() { var source = @" using System; enum E1 { e1, e2 } enum E2 { e3, e4 } interface I { } interface J { } class C : I, J { } public class Program { public static void Assert(bool condition) { if (!condition) throw new Exception(); } public static void Main(string[] args) { // explicit numeric conversions 6.2.1 int i = 12; byte b = (byte)i; Assert(b == 12); double d = 12.0; float f = (float)d; Assert(f == 12.0F); // explicit enumeration conversions 6.2.2 b = 1; E1 e1 = (E1)b; Assert(e1 == E1.e2); E2 e2 = (E2)e1; Assert(e2 == E2.e4); // explicit nullable conversions 6.2.3 int? ni = 0; byte? nb = (byte?)ni; Assert(nb == 0); ni = null; nb = (byte?)ni; Assert(!nb.HasValue); // explicit reference conversions 6.2.4 I[] ia = new C[20]; J[] ja = (J[])ia; // unboxing conversions 6.2.5 i = 12; object o = i; i = (int)o; Assert(i == 12); e1 = E1.e1; Enum e = e1; e1 = (E1)e; Assert(e1 == E1.e1); // explicit dynamic conversions 6.2.6 // explicit conversions involving type parameters 6.2.7 // user defined explicit conversions 6.2.8 } } "; var compilationVerifier = CompileAndVerify(source, expectedOutput: @""); } [Fact] public void InaccessibleConversion() { var source = @" using System; interface J<T> { } interface I<T> : J<object> { } class A { private class B { } public class C : I<B> { } } class Program { static void Main() { Goo(new A.C()); } static void Goo<T>(I<T> x) { Console.WriteLine(""Goo<T>(I<T> x)""); } static void Goo<T>(J<T> x) { Console.WriteLine(""Goo<T>(J<T> x)""); } } "; var compilationVerifier = CompileAndVerify(source, expectedOutput: @"Goo<T>(J<T> x) "); } [Fact] public void BadCodeCast() { var csSource = @"using System; class G<K> { K k; public G(K k) { this.k = k; } public void M() { N((IComparable)k); } void N(IComparable ic) { Console.WriteLine(ic); } } class Program { public static void Main(string[] args) { G<string> g1 = new G<string>(""hello""); g1.M(); } }"; CompileAndVerify(csSource, expectedOutput: "hello"); } [WorkItem(544427, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544427")] [Fact] public void WrongOrderConversion() { var text = @"using System; public class Test { public static explicit operator int(Test x) { return 1; } static long? M(Test t) { return (long?) t; } static void Main() { } }"; var compilation = CompileAndVerify(text); compilation.VerifyIL("Test.M", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""int Test.op_Explicit(Test)"" IL_0006: conv.i8 IL_0007: newobj ""long?..ctor(long)"" IL_000c: ret }"); } [WorkItem(602009, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/602009")] [Fact] public void DefaultParameterValue_DateTimeConstant() { var source1 = @" using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; public static class Test { public static void Generic<T>([Optional][DateTimeConstant(634953547672667479L)] T x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void DateTime([Optional][DateTimeConstant(634953547672667479L)] DateTime x) { Console.WriteLine(x.ToString()); } public static void NullableDateTime([Optional][DateTimeConstant(634953547672667479L)] DateTime? x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void Object([Optional][DateTimeConstant(634953547672667479L)] object x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void String([Optional][DateTimeConstant(634953547672667479L)] string x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void Int32([Optional][DateTimeConstant(634953547672667479L)] int x) { Console.WriteLine(x.ToString()); } public static void IComparable([Optional][DateTimeConstant(634953547672667479L)] IComparable x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void ValueType([Optional][DateTimeConstant(634953547672667479L)] ValueType x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } } "; var source2 = @" class Program { public static void Main() { // To avoid failures if the test ran on different culture System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; // Respects default value Test.Generic<System.DateTime>(); Test.Generic<System.DateTime?>(); Test.Generic<object>(); Test.DateTime(); Test.NullableDateTime(); Test.Object(); Test.IComparable(); Test.ValueType(); // Null, since not convertible Test.Generic<string>(); Test.String(); Test.Int32(); } } "; var expectedOutput = @" 02/01/2013 22:32:47 02/01/2013 22:32:47 02/01/2013 22:32:47 02/01/2013 22:32:47 02/01/2013 22:32:47 02/01/2013 22:32:47 02/01/2013 22:32:47 02/01/2013 22:32:47 null null 0 "; // When the method with the attribute is in source. var verifier1 = CompileAndVerify(source1 + source2, expectedOutput: expectedOutput); // When the method with the attribute is from metadata. var comp2 = CreateCompilation(source2, new[] { MetadataReference.CreateFromImage(verifier1.EmittedAssemblyData) }, TestOptions.ReleaseExe); CompileAndVerify(comp2, expectedOutput: expectedOutput); } [WorkItem(602009, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/602009")] [Fact] public void DefaultParameterValue_DecimalConstant() { var source1 = @" using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; public static class Test { public static void Generic<T>([Optional][DecimalConstant(0, 0, 0, 0, 50)] T x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void Decimal([Optional][DecimalConstant(0, 0, 0, 0, 50)] Decimal x) { Console.WriteLine(x.ToString()); } public static void NullableDecimal([Optional][DecimalConstant(0, 0, 0, 0, 50)] Decimal? x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void Object([Optional][DecimalConstant(0, 0, 0, 0, 50)] object x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void String([Optional][DecimalConstant(0, 0, 0, 0, 50)] string x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void Int32([Optional][DecimalConstant(0, 0, 0, 0, 50)] int x) { Console.WriteLine(x.ToString()); } public static void IComparable([Optional][DecimalConstant(0, 0, 0, 0, 50)] IComparable x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } public static void ValueType([Optional][DecimalConstant(0, 0, 0, 0, 50)] ValueType x) { Console.WriteLine(x == null ? ""null"" : x.ToString()); } } "; var source2 = @" class Program { public static void Main() { // Respects default value Test.Generic<decimal>(); Test.Generic<decimal?>(); Test.Generic<object>(); Test.Decimal(); Test.NullableDecimal(); Test.Object(); Test.IComparable(); Test.ValueType(); Test.Int32(); // Null, since not convertible Test.Generic<string>(); Test.String(); } } "; var expectedOutput = @" 50 50 50 50 50 50 50 50 50 null null "; // When the method with the attribute is in source. var verifier1 = CompileAndVerify(source1 + source2, expectedOutput: expectedOutput); // When the method with the attribute is from metadata. var comp2 = CreateCompilation(source2, new[] { MetadataReference.CreateFromImage(verifier1.EmittedAssemblyData) }, TestOptions.ReleaseExe); CompileAndVerify(comp2, expectedOutput: expectedOutput); } [WorkItem(659424, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/659424")] [Fact] public void FloatConversion001() { var text = @"using System; public class Program { static float Test(decimal d) { return (float)d; } static void Main() { } }"; var compilation = CompileAndVerify(text); compilation.VerifyIL("Program.Test(decimal)", @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""float decimal.op_Explicit(decimal)"" IL_0006: conv.r4 IL_0007: ret }"); } [WorkItem(659424, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/659424")] [Fact] public void FloatConversion002() { var text = @"using System; class Program { static void Main(string[] args) { System.Console.WriteLine(Test1(float.MaxValue)); System.Console.WriteLine(Test2(float.MaxValue)); } static float Test1(float arg) { var temp = Mul2(arg); return temp / 2; } static float Test2(float arg) { var temp = (float)Mul2(arg); // conv.r4 here. We want result of Mul2 to have float precision. return temp / 2; } private static float Mul2(float arg) { return arg * 2; } } "; var compilation = CompileAndVerify(text); compilation.VerifyIL("Program.Test2(float)", @" { // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: call ""float Program.Mul2(float)"" IL_0006: conv.r4 IL_0007: ldc.r4 2 IL_000c: div IL_000d: ret }"); } [WorkItem(659424, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/659424")] [Fact] public void FloatConversion003() { var text = @"using System; class Program { static void Main(string[] args) { System.Console.WriteLine(Test1(float.MaxValue)); System.Console.WriteLine(Test2(float.MaxValue)); } static float Test1(float arg) { var temp = Mul2(arg); return temp / 2; } static float Test2(float arg) { var temp = (float)(float?)Mul2(arg); // conv.r4 here. We want result of Mul2 to have float precision. return temp / 2; } private static float Mul2(float arg) { return arg * 2; } } "; var compilation = CompileAndVerify(text); compilation.VerifyIL("Program.Test2(float)", @" { // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: call ""float Program.Mul2(float)"" IL_0006: conv.r4 IL_0007: ldc.r4 2 IL_000c: div IL_000d: ret }"); } [WorkItem(448900, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/448900")] [Fact] public void Regress448900() { var text = @" using System; class Class1 { static void Main() { int? a = 1; a.ToString(); MyClass b = a; b.ToString(); } } class MyClass { public static implicit operator MyClass(decimal Value) { Console.WriteLine(""Value is: "" + Value); return new MyClass(); } } "; var compilation = CompileAndVerify(text, expectedOutput: "Value is: 1"); compilation.VerifyIL("Class1.Main()", @" { // Code size 60 (0x3c) .maxstack 2 .locals init (int? V_0, //a int? V_1) IL_0000: ldloca.s V_0 IL_0002: ldc.i4.1 IL_0003: call ""int?..ctor(int)"" IL_0008: ldloca.s V_0 IL_000a: constrained. ""int?"" IL_0010: callvirt ""string object.ToString()"" IL_0015: pop IL_0016: ldloc.0 IL_0017: stloc.1 IL_0018: ldloca.s V_1 IL_001a: call ""bool int?.HasValue.get"" IL_001f: brtrue.s IL_0024 IL_0021: ldnull IL_0022: br.s IL_0035 IL_0024: ldloca.s V_1 IL_0026: call ""int int?.GetValueOrDefault()"" IL_002b: call ""decimal decimal.op_Implicit(int)"" IL_0030: call ""MyClass MyClass.op_Implicit(decimal)"" IL_0035: callvirt ""string object.ToString()"" IL_003a: pop IL_003b: ret }"); } [WorkItem(448900, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/448900")] [Fact] public void Regress448900_Optimized() { var text = @" using System; class Class1 { static void Main() { int? a = 1; MyClass b = a; } } class MyClass { public static implicit operator MyClass(decimal Value) { Console.WriteLine(""Value is: "" + Value); return new MyClass(); } } "; var compilation = CompileAndVerify(text, expectedOutput: "Value is: 1"); compilation.VerifyIL("Class1.Main()", @" { // Code size 35 (0x23) .maxstack 1 .locals init (int? V_0) IL_0000: ldc.i4.1 IL_0001: newobj ""int?..ctor(int)"" IL_0006: stloc.0 IL_0007: ldloca.s V_0 IL_0009: call ""bool int?.HasValue.get"" IL_000e: brfalse.s IL_0022 IL_0010: ldloca.s V_0 IL_0012: call ""int int?.GetValueOrDefault()"" IL_0017: call ""decimal decimal.op_Implicit(int)"" IL_001c: call ""MyClass MyClass.op_Implicit(decimal)"" IL_0021: pop IL_0022: ret }"); } [WorkItem(448900, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/448900")] [Fact] public void Regress448900_Folded() { var text = @" using System; class Class1 { static void Main() { MyClass b = (int?)1; } } class MyClass { public static implicit operator MyClass(decimal Value) { Console.WriteLine(""Value is: "" + Value); return new MyClass(); } } "; var compilation = CompileAndVerify(text, expectedOutput: "Value is: 1"); compilation.VerifyIL("Class1.Main()", @" { // Code size 13 (0xd) .maxstack 1 IL_0000: ldc.i4.1 IL_0001: call ""decimal decimal.op_Implicit(int)"" IL_0006: call ""MyClass MyClass.op_Implicit(decimal)"" IL_000b: pop IL_000c: ret }"); } [WorkItem(674803, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/674803")] [Fact] public void CastFrom0ToExplicitConversionViaEnum01() { var text = @"enum E { a, b, c } class C { public static explicit operator C(E x) { return null; } public static explicit operator C(ulong x) { return null; } public static void Main() { C x = (C)0; } }"; // The native compiler does not consider an encompassing conversion from // a constant zero to an enum type to exist. We reproduce that bug in // Roslyn for compatibility. CreateCompilation(text).VerifyDiagnostics(); } [WorkItem(844635, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844635")] [Fact] public void RuntimeTypeCheckForGenericEnum() { string source = @" using System; class Program { static void Main() { Goo(new G<int>.E(), new G<int>.E()); } static void Goo<T>(G<T>.E x, G<int>.E y) { Console.Write(x is G<int>.E); Console.Write(y is G<T>.E); } } class G<T> { public enum E { } } "; var compilation = CompileAndVerify(source, expectedOutput: "TrueTrue"); compilation.VerifyIL("Program.Goo<T>(G<T>.E, G<int>.E)", @" { // Code size 39 (0x27) .maxstack 2 IL_0000: ldarg.0 IL_0001: box ""G<T>.E"" IL_0006: isinst ""G<int>.E"" IL_000b: ldnull IL_000c: cgt.un IL_000e: call ""void System.Console.Write(bool)"" IL_0013: ldarg.1 IL_0014: box ""G<int>.E"" IL_0019: isinst ""G<T>.E"" IL_001e: ldnull IL_001f: cgt.un IL_0021: call ""void System.Console.Write(bool)"" IL_0026: ret }"); } [WorkItem(864605, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/864605")] [WorkItem(864740, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/864740")] [Fact] public void MethodGroupIsExpression() { string source = @" using System; class Program { static void Main() { var x = ICloneable.Clone is object; } } "; CreateCompilation(source).VerifyEmitDiagnostics( // (8,17): error CS0837: The first operand of an 'is' or 'as' operator may not be a lambda expression, anonymous method, or method group. // var x = ICloneable.Clone is object; Diagnostic(ErrorCode.ERR_LambdaInIsAs, "ICloneable.Clone is object").WithLocation(8, 17)); } [Fact] [WorkItem(1084278, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1084278")] public void NullableConversionFromConst() { var source = @" using System; class C { static void Main() { Use((int?)3.5f); Use((int?)3.5d); } static void Use(int? p) { } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.Main()", @" { // Code size 23 (0x17) .maxstack 1 IL_0000: ldc.i4.3 IL_0001: newobj ""int?..ctor(int)"" IL_0006: call ""void C.Use(int?)"" IL_000b: ldc.i4.3 IL_000c: newobj ""int?..ctor(int)"" IL_0011: call ""void C.Use(int?)"" IL_0016: ret }"); } [Fact] public void LiftedFromIntPtrConversions() { var source = @" using System; class C { static void Main(string[] args) { Console.WriteLine((int?)M(null)); Console.WriteLine((int?)M((IntPtr)42)); } static IntPtr? M(IntPtr? p) { return p; } } "; CompileAndVerify(source, expectedOutput: @" 42"); } [Fact] public void LiftedToIntPtrConversions() { var source = @" using System; class C { static void Main() { Console.WriteLine((IntPtr?)M_int()); Console.WriteLine((IntPtr?)M_int(42)); Console.WriteLine((IntPtr?)M_long()); Console.WriteLine((IntPtr?)M_long(300)); } static int? M_int(int? p = null) { return p; } static long? M_long(long? p = null) { return p; } } "; CompileAndVerify(source, expectedOutput: @" 42 300 "); } [Fact] public void LiftedToIntPtrConversionsOptimized() { var source = @" using System; class C { static void Main() { Use((IntPtr?)(int?)(null)); Use((IntPtr?)(int?)(42)); } static void Use(IntPtr? p) { } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.Main()", @" { // Code size 32 (0x20) .maxstack 1 .locals init (System.IntPtr? V_0) IL_0000: ldloca.s V_0 IL_0002: initobj ""System.IntPtr?"" IL_0008: ldloc.0 IL_0009: call ""void C.Use(System.IntPtr?)"" IL_000e: ldc.i4.s 42 IL_0010: call ""System.IntPtr System.IntPtr.op_Explicit(int)"" IL_0015: newobj ""System.IntPtr?..ctor(System.IntPtr)"" IL_001a: call ""void C.Use(System.IntPtr?)"" IL_001f: ret }"); } [Fact] public void NullableNumericToIntPtr() { var source = @" using System; class C { static void Test() { byte? b = 0; IntPtr p = (IntPtr)b; Console.WriteLine(p); } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.Test()", @" { // Code size 31 (0x1f) .maxstack 2 .locals init (byte? V_0) //b IL_0000: ldloca.s V_0 IL_0002: ldc.i4.0 IL_0003: call ""byte?..ctor(byte)"" IL_0008: ldloca.s V_0 IL_000a: call ""byte byte?.Value.get"" IL_000f: call ""System.IntPtr System.IntPtr.op_Explicit(int)"" IL_0014: box ""System.IntPtr"" IL_0019: call ""void System.Console.WriteLine(object)"" IL_001e: ret }"); } [Fact] public void NullableNumericToIntPtr1() { var source = @" using System; class C { static void Test() { byte? b = 0 + 1; IntPtr p = (IntPtr)b; Console.WriteLine(p); } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.Test()", @" { // Code size 32 (0x20) .maxstack 2 .locals init (byte? V_0) //b IL_0000: ldloca.s V_0 IL_0002: ldc.i4.1 IL_0003: conv.u1 IL_0004: call ""byte?..ctor(byte)"" IL_0009: ldloca.s V_0 IL_000b: call ""byte byte?.Value.get"" IL_0010: call ""System.IntPtr System.IntPtr.op_Explicit(int)"" IL_0015: box ""System.IntPtr"" IL_001a: call ""void System.Console.WriteLine(object)"" IL_001f: ret }"); } [Fact] public void NumericToNullableIntPtr() { var source = @" using System; class C { static void Test() { byte b = 0; IntPtr? p = (IntPtr?)b; Console.WriteLine(p); } }"; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.Test()", @" { // Code size 24 (0x18) .maxstack 1 .locals init (byte V_0) //b IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldloc.0 IL_0003: call ""System.IntPtr System.IntPtr.op_Explicit(int)"" IL_0008: newobj ""System.IntPtr?..ctor(System.IntPtr)"" IL_000d: box ""System.IntPtr?"" IL_0012: call ""void System.Console.WriteLine(object)"" IL_0017: ret }"); } [Fact] [WorkItem(1210529, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1210529")] public void LiftedIntToIntPtr() { var source = @" using System; class C { static void Main() { Use((IntPtr?)M()); } static int? M() { return 0; } static void Use(IntPtr? p) { } } "; var compilation = CompileAndVerify(source); compilation.VerifyIL("C.Main()", @" { // Code size 49 (0x31) .maxstack 1 .locals init (int? V_0, System.IntPtr? V_1) IL_0000: call ""int? C.M()"" IL_0005: stloc.0 IL_0006: ldloca.s V_0 IL_0008: call ""bool int?.HasValue.get"" IL_000d: brtrue.s IL_001a IL_000f: ldloca.s V_1 IL_0011: initobj ""System.IntPtr?"" IL_0017: ldloc.1 IL_0018: br.s IL_002b IL_001a: ldloca.s V_0 IL_001c: call ""int int?.GetValueOrDefault()"" IL_0021: call ""System.IntPtr System.IntPtr.op_Explicit(int)"" IL_0026: newobj ""System.IntPtr?..ctor(System.IntPtr)"" IL_002b: call ""void C.Use(System.IntPtr?)"" IL_0030: ret }"); } [Fact] [WorkItem(11751, "https://github.com/dotnet/roslyn/issues/11751")] public void ExprTreeCOM_IntPtr() { var source = @" using System; using System.Linq.Expressions; using System.Runtime.InteropServices; unsafe class Program { static void Main(string[] args) { IntPtr y = new IntPtr(); IAaa i = null; Expression<Action> e = () => i.Test((ulong)y, null); } } [ComImport] [Guid(""A88A175D-2448-447A-B786-64682CBEF156"")] public interface IAaa { void Test(ulong y, object z); } "; var compilation = CreateCompilationWithMscorlib461AndCSharp(source, options: TestOptions.ReleaseExe.WithAllowUnsafe(true)); CompileAndVerify(compilation); } [Fact, WorkItem(17756, "https://github.com/dotnet/roslyn/issues/17756")] public void TestIdentityConversionNotLvalue() { var source = @" class Program { struct S1 { public int field; public int Increment() => field++; } static void Main() { S1 v = default(S1); v.Increment(); ((S1)v).Increment(); System.Console.WriteLine(v.field); } } "; string expectedOutput = @"1"; CompileAndVerify(source, expectedOutput: expectedOutput); } [Fact, WorkItem(22533, "https://github.com/dotnet/roslyn/issues/22533")] public void TestDoubleConversionEmitted() { var source = @" class Program { static bool M() { double dValue = 600.1; int iValue = 600; byte mbytDeciWgt = 1; bool value = (dValue > iValue + (10 ^ -mbytDeciWgt)); return value; } } "; var comp = CompileAndVerify(source); comp.VerifyIL("Program.M", @"{ // Code size 28 (0x1c) .maxstack 4 .locals init (int V_0, //iValue byte V_1) //mbytDeciWgt IL_0000: ldc.r8 600.1 IL_0009: ldc.i4 0x258 IL_000e: stloc.0 IL_000f: ldc.i4.1 IL_0010: stloc.1 IL_0011: ldloc.0 IL_0012: ldc.i4.s 10 IL_0014: ldloc.1 IL_0015: neg IL_0016: xor IL_0017: add IL_0018: conv.r8 IL_0019: cgt IL_001b: ret }"); } [Fact, WorkItem(22533, "https://github.com/dotnet/roslyn/issues/22533")] public void TestExplicitDoubleConversionEmitted() { var source = @" class Program { static bool M() { double dValue = 600.1; int iValue = 600; byte mbytDeciWgt = 1; bool value = ((double)dValue > (double)((double)iValue + (double)System.Math.Pow(10, -mbytDeciWgt))); return value; } } "; var comp = CompileAndVerify(source); comp.VerifyIL("Program.M", @"{ // Code size 43 (0x2b) .maxstack 4 .locals init (int V_0, //iValue byte V_1) //mbytDeciWgt IL_0000: ldc.r8 600.1 IL_0009: ldc.i4 0x258 IL_000e: stloc.0 IL_000f: ldc.i4.1 IL_0010: stloc.1 IL_0011: conv.r8 IL_0012: ldloc.0 IL_0013: conv.r8 IL_0014: ldc.r8 10 IL_001d: ldloc.1 IL_001e: neg IL_001f: conv.r8 IL_0020: call ""double System.Math.Pow(double, double)"" IL_0025: conv.r8 IL_0026: add IL_0027: conv.r8 IL_0028: cgt IL_002a: ret }"); } [Fact, WorkItem(31587, "https://github.com/dotnet/roslyn/issues/31587")] public void NullableDecimalToEnumConversion() { var source = @" enum E { } class C { static E F(decimal? d) => (E)d; } "; CompileAndVerify(source).VerifyDiagnostics(); } [Fact, WorkItem(31587, "https://github.com/dotnet/roslyn/issues/31587")] public void NullableMethodGroupConversion() { var source = @" using System; class C { static void M(decimal? d) { Func<string> f = d.ToString; } } "; CompileAndVerify(source).VerifyDiagnostics(); } [Fact] [WorkItem(54113, "https://github.com/dotnet/roslyn/issues/54113")] public void DisallowedModreqOnConversion() { var il = @" .class public auto ansi beforefieldinit C extends [mscorlib]System.Object { .method public hidebysig specialname static int32 modreq([mscorlib]System.Runtime.CompilerServices.OutAttribute) op_Implicit ( class C i ) cil managed { IL_0000: ldc.i4.0 IL_0001: ret } .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } } "; var comp = CreateCompilationWithIL(@" class Test { void M(C x) { _ = (int)x; } } ", il); comp.VerifyDiagnostics( // (6,13): error CS0570: 'C.implicit operator int(C)' is not supported by the language // _ = (int)x; Diagnostic(ErrorCode.ERR_BindToBogus, "(int)x").WithArguments("C.implicit operator int(C)").WithLocation(6, 13) ); } } }