/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenStackAllocInitializerTests.cs
1 704 строки
54 KB
Jan Jones
Fix stack adjustment when emitting stackalloc (#75042)
12 сен 2024, 12:26
Не верифицирован
12 сен 2024, 12:26
0654505
Код
Авторство
О чём код?
// 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 { [CompilerTrait(CompilerFeature.StackAllocInitializer)] public class CodeGenStackAllocInitializerTests : CompilingTestBase { [Fact] [WorkItem(29092, "https://github.com/dotnet/roslyn/issues/29092")] public void TestMixedWithInitBlock() { var text = @" using System; class Program { static void Main(string[] args) { MakeBlock(1, 2, 3); } static unsafe void MakeBlock(int a, int b, int c) { int* ptr = stackalloc int[] { 0, 0, 0, a, b, c }; PrintBytes(ptr, 6); } static unsafe void PrintBytes(int* ptr, int count) { for (int i = 0; i < count; i++) { Console.Write(ptr[i]); } } }"; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, expectedOutput: "000123", verify: Verification.Fails).VerifyIL("Program.MakeBlock", @"{ // Code size 42 (0x2a) .maxstack 4 IL_0000: ldc.i4.s 24 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldc.i4.0 IL_0007: ldc.i4.s 24 IL_0009: initblk IL_000b: dup IL_000c: ldc.i4.3 IL_000d: conv.i IL_000e: ldc.i4.4 IL_000f: mul IL_0010: add IL_0011: ldarg.0 IL_0012: stind.i4 IL_0013: dup IL_0014: ldc.i4.4 IL_0015: conv.i IL_0016: ldc.i4.4 IL_0017: mul IL_0018: add IL_0019: ldarg.1 IL_001a: stind.i4 IL_001b: dup IL_001c: ldc.i4.5 IL_001d: conv.i IL_001e: ldc.i4.4 IL_001f: mul IL_0020: add IL_0021: ldarg.2 IL_0022: stind.i4 IL_0023: ldc.i4.6 IL_0024: call ""void Program.PrintBytes(int*, int)"" IL_0029: ret }"); } [Fact] public void TestUnmanaged_Pointer() { var text = @" using System; unsafe class Test { static void Print<T>(T* p) where T : unmanaged { for (int i = 0; i < 3; i++) Console.Write(p[i]); } static void M<T>(T arg) where T : unmanaged { var obj1 = stackalloc T[3] { arg, arg, arg }; Print<T>(obj1); var obj2 = stackalloc T[ ] { arg, arg, arg }; Print<T>(obj2); var obj3 = stackalloc [ ] { arg, arg, arg }; Print<T>(obj3); } public static void Main() { M(42); } }"; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, expectedOutput: "424242424242424242", verify: Verification.Fails).VerifyIL("Test.M<T>(T)", @"{ // Code size 163 (0xa3) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: sizeof ""T"" IL_0008: mul.ovf.un IL_0009: localloc IL_000b: dup IL_000c: ldarg.0 IL_000d: stobj ""T"" IL_0012: dup IL_0013: sizeof ""T"" IL_0019: add IL_001a: ldarg.0 IL_001b: stobj ""T"" IL_0020: dup IL_0021: ldc.i4.2 IL_0022: conv.i IL_0023: sizeof ""T"" IL_0029: mul IL_002a: add IL_002b: ldarg.0 IL_002c: stobj ""T"" IL_0031: call ""void Test.Print<T>(T*)"" IL_0036: ldc.i4.3 IL_0037: conv.u IL_0038: sizeof ""T"" IL_003e: mul.ovf.un IL_003f: localloc IL_0041: dup IL_0042: ldarg.0 IL_0043: stobj ""T"" IL_0048: dup IL_0049: sizeof ""T"" IL_004f: add IL_0050: ldarg.0 IL_0051: stobj ""T"" IL_0056: dup IL_0057: ldc.i4.2 IL_0058: conv.i IL_0059: sizeof ""T"" IL_005f: mul IL_0060: add IL_0061: ldarg.0 IL_0062: stobj ""T"" IL_0067: call ""void Test.Print<T>(T*)"" IL_006c: ldc.i4.3 IL_006d: conv.u IL_006e: sizeof ""T"" IL_0074: mul.ovf.un IL_0075: localloc IL_0077: dup IL_0078: ldarg.0 IL_0079: stobj ""T"" IL_007e: dup IL_007f: sizeof ""T"" IL_0085: add IL_0086: ldarg.0 IL_0087: stobj ""T"" IL_008c: dup IL_008d: ldc.i4.2 IL_008e: conv.i IL_008f: sizeof ""T"" IL_0095: mul IL_0096: add IL_0097: ldarg.0 IL_0098: stobj ""T"" IL_009d: call ""void Test.Print<T>(T*)"" IL_00a2: ret }"); } [Fact] public void TestUnmanaged_Span() { var comp = CreateCompilationWithMscorlibAndSpan(@" using System; class Test { public void M<T>(T arg) where T : unmanaged { Span<T> obj1 = stackalloc T[3] { arg, arg, arg }; Span<T> obj2 = stackalloc T[ ] { arg, arg, arg }; Span<T> obj3 = stackalloc [ ] { arg, arg, arg }; } } ", options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3)); CompileAndVerify(comp, verify: Verification.Fails).VerifyIL("Test.M<T>(T)", @"{ // Code size 169 (0xa9) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: sizeof ""T"" IL_0008: mul.ovf.un IL_0009: localloc IL_000b: dup IL_000c: ldarg.1 IL_000d: stobj ""T"" IL_0012: dup IL_0013: sizeof ""T"" IL_0019: add IL_001a: ldarg.1 IL_001b: stobj ""T"" IL_0020: dup IL_0021: ldc.i4.2 IL_0022: conv.i IL_0023: sizeof ""T"" IL_0029: mul IL_002a: add IL_002b: ldarg.1 IL_002c: stobj ""T"" IL_0031: ldc.i4.3 IL_0032: newobj ""System.Span<T>..ctor(void*, int)"" IL_0037: pop IL_0038: ldc.i4.3 IL_0039: conv.u IL_003a: sizeof ""T"" IL_0040: mul.ovf.un IL_0041: localloc IL_0043: dup IL_0044: ldarg.1 IL_0045: stobj ""T"" IL_004a: dup IL_004b: sizeof ""T"" IL_0051: add IL_0052: ldarg.1 IL_0053: stobj ""T"" IL_0058: dup IL_0059: ldc.i4.2 IL_005a: conv.i IL_005b: sizeof ""T"" IL_0061: mul IL_0062: add IL_0063: ldarg.1 IL_0064: stobj ""T"" IL_0069: ldc.i4.3 IL_006a: newobj ""System.Span<T>..ctor(void*, int)"" IL_006f: pop IL_0070: ldc.i4.3 IL_0071: conv.u IL_0072: sizeof ""T"" IL_0078: mul.ovf.un IL_0079: localloc IL_007b: dup IL_007c: ldarg.1 IL_007d: stobj ""T"" IL_0082: dup IL_0083: sizeof ""T"" IL_0089: add IL_008a: ldarg.1 IL_008b: stobj ""T"" IL_0090: dup IL_0091: ldc.i4.2 IL_0092: conv.i IL_0093: sizeof ""T"" IL_0099: mul IL_009a: add IL_009b: ldarg.1 IL_009c: stobj ""T"" IL_00a1: ldc.i4.3 IL_00a2: newobj ""System.Span<T>..ctor(void*, int)"" IL_00a7: pop IL_00a8: ret }"); } [Fact] public void TestLambdaCapture() { var text = @" using System; public class C { unsafe public static void Main() { // captured by the lambda. byte x = 1; byte* b = stackalloc byte[] {((Func<byte>)(() => x++))(), x}; Console.Write(b[1]); } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, expectedOutput: "2", verify: Verification.Fails).VerifyIL("C.Main", @"{ // Code size 55 (0x37) .maxstack 4 .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 IL_0000: newobj ""C.<>c__DisplayClass0_0..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: ldc.i4.1 IL_0008: stfld ""byte C.<>c__DisplayClass0_0.x"" IL_000d: ldc.i4.2 IL_000e: conv.u IL_000f: localloc IL_0011: dup IL_0012: ldloc.0 IL_0013: ldftn ""byte C.<>c__DisplayClass0_0.<Main>b__0()"" IL_0019: newobj ""System.Func<byte>..ctor(object, System.IntPtr)"" IL_001e: callvirt ""byte System.Func<byte>.Invoke()"" IL_0023: stind.i1 IL_0024: dup IL_0025: ldc.i4.1 IL_0026: add IL_0027: ldloc.0 IL_0028: ldfld ""byte C.<>c__DisplayClass0_0.x"" IL_002d: stind.i1 IL_002e: ldc.i4.1 IL_002f: add IL_0030: ldind.u1 IL_0031: call ""void System.Console.Write(int)"" IL_0036: ret }"); } [Fact] public void TestElementThrow() { var text = @" using System; static unsafe class C { static void Use(int* i) {} static int M() { return 0; } static void Main() { var p = stackalloc[] { M(), true ? throw null : M(), M() }; Use(p); } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails).VerifyIL("C.Main", @"{ // Code size 17 (0x11) .maxstack 4 IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: call ""int C.M()"" IL_000b: stind.i4 IL_000c: dup IL_000d: ldc.i4.4 IL_000e: add IL_000f: ldnull IL_0010: throw }"); } [Fact] public void TestUnused() { var text = @" using System; static unsafe class C { static byte Method(int i) { Console.Write(i); return 0; } static void Main() { var p = stackalloc[] { 42, Method(1), 42, Method(2) }; } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, expectedOutput: "12", verify: Verification.Passes).VerifyIL("C.Main", @"{ // Code size 19 (0x13) .maxstack 1 IL_0000: ldc.i4.s 16 IL_0002: conv.u IL_0003: pop IL_0004: ldc.i4.1 IL_0005: call ""byte C.Method(int)"" IL_000a: pop IL_000b: ldc.i4.2 IL_000c: call ""byte C.Method(int)"" IL_0011: pop IL_0012: ret }"); CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeDebugExe, expectedOutput: "12", verify: Verification.Fails).VerifyIL("C.Main", @"{ // Code size 44 (0x2c) .maxstack 4 .locals init (int* V_0) //p IL_0000: nop IL_0001: ldc.i4.s 16 IL_0003: conv.u IL_0004: localloc IL_0006: dup IL_0007: ldc.i4.s 42 IL_0009: stind.i4 IL_000a: dup IL_000b: ldc.i4.4 IL_000c: add IL_000d: ldc.i4.1 IL_000e: call ""byte C.Method(int)"" IL_0013: stind.i4 IL_0014: dup IL_0015: ldc.i4.2 IL_0016: conv.i IL_0017: ldc.i4.4 IL_0018: mul IL_0019: add IL_001a: ldc.i4.s 42 IL_001c: stind.i4 IL_001d: dup IL_001e: ldc.i4.3 IL_001f: conv.i IL_0020: ldc.i4.4 IL_0021: mul IL_0022: add IL_0023: ldc.i4.2 IL_0024: call ""byte C.Method(int)"" IL_0029: stind.i4 IL_002a: stloc.0 IL_002b: ret }"); } [Fact] public void TestEmpty() { var text = @" using System; static unsafe class C { static void Use(int* p) { } static void Main() { var p = stackalloc int[] {}; Use(p); } } "; // PEVerify: [ : C::Main][mdToken=0x6000002][offset 0x00000002][found Native Int][expected unmanaged pointer] Unexpected type on the stack. CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.FailsPEVerify).VerifyIL("C.Main", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldc.i4.0 IL_0001: conv.u IL_0002: call ""void C.Use(int*)"" IL_0007: ret }"); } [Fact] public void TestIdenticalBytes1() { var text = @" using System; static unsafe class C { static void Print(byte* p) { for (int i = 0; i < 3; i++) Console.Write(p[i]); } static void Main() { byte* p = stackalloc byte[3] { 42, 42, 42 }; Print(p); } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"424242").VerifyIL("C.Main", @"{ // Code size 16 (0x10) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldc.i4.s 42 IL_0007: ldc.i4.3 IL_0008: initblk IL_000a: call ""void C.Print(byte*)"" IL_000f: ret }"); } [Fact] public void TestIdenticalBytes2() { var text = @" using System; static unsafe class C { static void Print(uint* p) { for (int i = 0; i < 3; i++) Console.Write(p[i].ToString(""x"")); } static void Main() { var p = stackalloc[] { 0xffffffff, 0xffffffff, 0xffffffff }; Print(p); } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"ffffffffffffffffffffffff").VerifyIL("C.Main", @"{ // Code size 21 (0x15) .maxstack 4 IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldc.i4 0xff IL_000b: ldc.i4.s 12 IL_000d: initblk IL_000f: call ""void C.Print(uint*)"" IL_0014: ret }"); } [Fact] public void TestEnum() { var text = """ using System; static unsafe class C { static void Print(E* p) { for (int i = 0; i < 3; i++) Console.Write(p[i]); } static void Main() { var p1 = stackalloc[] { E.A, E.B, E.C }; var p2 = stackalloc[] { E.D, E.D, E.D }; Print(p1); Print(p2); } enum E : byte { A, B, C, D } } """; CompileAndVerify(text, options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"ABCDDD").VerifyIL("C.Main", """ { // Code size 38 (0x26) .maxstack 4 .locals init (C.E* V_0) //p1 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldsflda "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=3 <PrivateImplementationDetails>.AE4B3280E56E2FAF83F414A6E3DABE9D5FBE18976544C05FED121ACCB85B53FC" IL_000a: ldc.i4.3 IL_000b: unaligned. 1 IL_000e: cpblk IL_0010: stloc.0 IL_0011: ldc.i4.3 IL_0012: conv.u IL_0013: localloc IL_0015: dup IL_0016: ldc.i4.3 IL_0017: ldc.i4.3 IL_0018: initblk IL_001a: ldloc.0 IL_001b: call "void C.Print(C.E*)" IL_0020: call "void C.Print(C.E*)" IL_0025: ret } """); } [Fact] public void TestMixedBlockInit() { var text = @" using System; static unsafe class C { static void Print(byte* p) { for (int i = 0; i < 9; i++) Console.Write(p[i]); } static byte M() { return 9; } static void Main() { byte* p = stackalloc byte[9] { 1, 2, 3, 4, 5, 6, 7, 8, M() }; Print(p); } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"123456789").VerifyIL("C.Main", @"{ // Code size 33 (0x21) .maxstack 4 IL_0000: ldc.i4.s 9 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldsflda ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=9 <PrivateImplementationDetails>.5248358BD96335E3BA4BB5D100E25AD64FAF4ADA8E613568E449FF981304C025"" IL_000b: ldc.i4.s 9 IL_000d: unaligned. 1 IL_0010: cpblk IL_0012: dup IL_0013: ldc.i4.8 IL_0014: add IL_0015: call ""byte C.M()"" IL_001a: stind.i1 IL_001b: call ""void C.Print(byte*)"" IL_0020: ret }"); } [Fact] public void TestElementInit() { var text = @" using System; struct S { public int i; } static unsafe class C { static void Print(S* p) { for (int i = 0; i < 3; i++) Console.Write(p[i].i); } static S M(int i) { return new S { i = i }; } static void Main() { S* p = stackalloc S[3] { M(1), M(2), M(3) }; Print(p); } } "; CompileAndVerify(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"123").VerifyIL("C.Main", @"{ // Code size 70 (0x46) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: sizeof ""S"" IL_0008: mul.ovf.un IL_0009: localloc IL_000b: dup IL_000c: ldc.i4.1 IL_000d: call ""S C.M(int)"" IL_0012: stobj ""S"" IL_0017: dup IL_0018: sizeof ""S"" IL_001e: add IL_001f: ldc.i4.2 IL_0020: call ""S C.M(int)"" IL_0025: stobj ""S"" IL_002a: dup IL_002b: ldc.i4.2 IL_002c: conv.i IL_002d: sizeof ""S"" IL_0033: mul IL_0034: add IL_0035: ldc.i4.3 IL_0036: call ""S C.M(int)"" IL_003b: stobj ""S"" IL_0040: call ""void C.Print(S*)"" IL_0045: ret }"); } [Fact] public void TestBytePointer() { Test("System.Byte", @"{ // Code size 22 (0x16) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldsflda ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=3 <PrivateImplementationDetails>.039058C6F2C0CB492C533B0A4D14EF77CC0F78ABCCCED5287D84A1A2011CFB81"" IL_000a: ldc.i4.3 IL_000b: unaligned. 1 IL_000e: cpblk IL_0010: call ""void C.Print(byte*)"" IL_0015: ret }"); } [Fact] public void TestInt32Pointer() { Test("System.Int32", @"{ // Code size 27 (0x1b) .maxstack 4 IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldc.i4.1 IL_0007: stind.i4 IL_0008: dup IL_0009: ldc.i4.4 IL_000a: add IL_000b: ldc.i4.2 IL_000c: stind.i4 IL_000d: dup IL_000e: ldc.i4.2 IL_000f: conv.i IL_0010: ldc.i4.4 IL_0011: mul IL_0012: add IL_0013: ldc.i4.3 IL_0014: stind.i4 IL_0015: call ""void C.Print(int*)"" IL_001a: ret }"); } [Fact] public void TestInt64Pointer() { Test("System.Int64", @"{ // Code size 30 (0x1e) .maxstack 4 IL_0000: ldc.i4.s 24 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldc.i4.1 IL_0007: conv.i8 IL_0008: stind.i8 IL_0009: dup IL_000a: ldc.i4.8 IL_000b: add IL_000c: ldc.i4.2 IL_000d: conv.i8 IL_000e: stind.i8 IL_000f: dup IL_0010: ldc.i4.2 IL_0011: conv.i IL_0012: ldc.i4.8 IL_0013: mul IL_0014: add IL_0015: ldc.i4.3 IL_0016: conv.i8 IL_0017: stind.i8 IL_0018: call ""void C.Print(long*)"" IL_001d: ret }"); } [Fact] public void TestSpan() { var comp = CreateCompilation(@" using System; static class C { static void Main() { Span<byte> p = stackalloc byte[3] { 1, 2, 3 }; } } namespace System { public ref struct Span<T> { public unsafe Span(void* p, int length) { for (int i = 0; i < 3; i++) Console.Write(((byte*)p)[i]); } } } ", options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3)); CompileAndVerify(comp, verify: Verification.Fails, expectedOutput: @"123") .VerifyDiagnostics() .VerifyIL("C.Main", @" { // Code size 24 (0x18) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldsflda ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=3 <PrivateImplementationDetails>.039058C6F2C0CB492C533B0A4D14EF77CC0F78ABCCCED5287D84A1A2011CFB81"" IL_000a: ldc.i4.3 IL_000b: unaligned. 1 IL_000e: cpblk IL_0010: ldc.i4.3 IL_0011: newobj ""System.Span<byte>..ctor(void*, int)"" IL_0016: pop IL_0017: ret } "); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestSpan_ZeroElements() { var source = """ using System; static class C { static void Main() { Span<byte> p = stackalloc byte[0]; Write(p); } static void Write(Span<byte> span) { foreach (byte x in span) Console.Write(x); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "" : null, verify: Verification.FailsPEVerify, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 15 (0xf) .maxstack 1 .locals init (System.Span<byte> V_0) IL_0000: ldloca.s V_0 IL_0002: initobj "System.Span<byte>" IL_0008: ldloc.0 IL_0009: call "void C.Write(System.Span<byte>)" IL_000e: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestSpanInt() { var source = """ using System; static class C { static void Main() { Span<int> p = stackalloc int[3] { 1, 2, 3 }; Write(p); } static void Write(Span<int> span) { foreach (int x in span) Console.Write(x); } } """; var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "123" : null; var verifier = CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 44 (0x2c) .maxstack 4 .locals init (System.ReadOnlySpan<int> V_0) IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12_Align=4 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D4" IL_000b: call "System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)" IL_0010: stloc.0 IL_0011: ldloca.s V_0 IL_0013: ldc.i4.0 IL_0014: call "ref readonly int System.ReadOnlySpan<int>.this[int].get" IL_0019: ldc.i4.s 12 IL_001b: unaligned. 4 IL_001e: cpblk IL_0020: ldc.i4.3 IL_0021: newobj "System.Span<int>..ctor(void*, int)" IL_0026: call "void C.Write(System.Span<int>)" IL_002b: ret } """); CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70, options: TestOptions.DebugExe).VerifyDiagnostics(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestSpanInt_ZeroElements() { var source = """ using System; static class C { static void Main() { Span<int> p = stackalloc int[0]; Write(p); } static void Write(Span<int> span) { foreach (int x in span) Console.Write(x); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "" : null, verify: Verification.FailsPEVerify, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 15 (0xf) .maxstack 1 .locals init (System.Span<int> V_0) IL_0000: ldloca.s V_0 IL_0002: initobj "System.Span<int>" IL_0008: ldloc.0 IL_0009: call "void C.Write(System.Span<int>)" IL_000e: ret } """); } [Fact] public void TestReadOnlySpan() { var comp = CreateCompilation(@" using System; static class C { static void Main() { ReadOnlySpan<int> p = stackalloc int[3] { 1, 2, 3 }; } } namespace System { public ref struct Span<T> { public unsafe Span(void* p, int length) { for (int i = 0; i < 3; i++) Console.Write(((int*)p)[i]); } } public readonly ref struct ReadOnlySpan<T> { public static implicit operator System.ReadOnlySpan<T> (System.Span<T> span) => default; } } ", options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3)); CompileAndVerify(comp, verify: Verification.Fails, expectedOutput: @"123") .VerifyDiagnostics() .VerifyIL("C.Main", @" { // Code size 34 (0x22) .maxstack 4 IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldc.i4.1 IL_0007: stind.i4 IL_0008: dup IL_0009: ldc.i4.4 IL_000a: add IL_000b: ldc.i4.2 IL_000c: stind.i4 IL_000d: dup IL_000e: ldc.i4.2 IL_000f: conv.i IL_0010: ldc.i4.4 IL_0011: mul IL_0012: add IL_0013: ldc.i4.3 IL_0014: stind.i4 IL_0015: ldc.i4.3 IL_0016: newobj ""System.Span<int>..ctor(void*, int)"" IL_001b: call ""System.ReadOnlySpan<int> System.ReadOnlySpan<int>.op_Implicit(System.Span<int>)"" IL_0020: pop IL_0021: ret } "); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_Net7() { var source = """ using System; static class C { static void Main() { ReadOnlySpan<int> p = stackalloc int[3] { 1, 2, 3 }; Write(p); } static void Write(ReadOnlySpan<int> span) { foreach (int x in span) Console.Write(x); } } """; var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "123" : null; var verifier = CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 49 (0x31) .maxstack 4 .locals init (System.ReadOnlySpan<int> V_0) IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12_Align=4 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D4" IL_000b: call "System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)" IL_0010: stloc.0 IL_0011: ldloca.s V_0 IL_0013: ldc.i4.0 IL_0014: call "ref readonly int System.ReadOnlySpan<int>.this[int].get" IL_0019: ldc.i4.s 12 IL_001b: unaligned. 4 IL_001e: cpblk IL_0020: ldc.i4.3 IL_0021: newobj "System.Span<int>..ctor(void*, int)" IL_0026: call "System.ReadOnlySpan<int> System.Span<int>.op_Implicit(System.Span<int>)" IL_002b: call "void C.Write(System.ReadOnlySpan<int>)" IL_0030: ret } """); CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70, options: TestOptions.DebugExe).VerifyDiagnostics(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_Net7_Byte() { var source = """ using System; static class C { static void Main() { ReadOnlySpan<byte> p = stackalloc byte[3] { 1, 2, 3 }; Write(p); } static void Write(ReadOnlySpan<byte> span) { foreach (byte x in span) Console.Write(x); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "123" : null, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 33 (0x21) .maxstack 4 IL_0000: ldc.i4.3 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldsflda "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=3 <PrivateImplementationDetails>.039058C6F2C0CB492C533B0A4D14EF77CC0F78ABCCCED5287D84A1A2011CFB81" IL_000a: ldc.i4.3 IL_000b: unaligned. 1 IL_000e: cpblk IL_0010: ldc.i4.3 IL_0011: newobj "System.Span<byte>..ctor(void*, int)" IL_0016: call "System.ReadOnlySpan<byte> System.Span<byte>.op_Implicit(System.Span<byte>)" IL_001b: call "void C.Write(System.ReadOnlySpan<byte>)" IL_0020: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_Net7_Short() { var source = """ using System; static class C { static void Main() { ReadOnlySpan<short> p = stackalloc short[3] { 1, 2, 3 }; Write(p); } static void Write(ReadOnlySpan<short> span) { foreach (short x in span) Console.Write(x); } } """; var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "123" : null; var verifier = CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 47 (0x2f) .maxstack 4 .locals init (System.ReadOnlySpan<short> V_0) IL_0000: ldc.i4.6 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=6_Align=2 <PrivateImplementationDetails>.047DBF5366372631BA7E3E02520E651446B899C96C4B64663BAC378A298A7BF72" IL_000a: call "System.ReadOnlySpan<short> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<short>(System.RuntimeFieldHandle)" IL_000f: stloc.0 IL_0010: ldloca.s V_0 IL_0012: ldc.i4.0 IL_0013: call "ref readonly short System.ReadOnlySpan<short>.this[int].get" IL_0018: ldc.i4.6 IL_0019: unaligned. 2 IL_001c: cpblk IL_001e: ldc.i4.3 IL_001f: newobj "System.Span<short>..ctor(void*, int)" IL_0024: call "System.ReadOnlySpan<short> System.Span<short>.op_Implicit(System.Span<short>)" IL_0029: call "void C.Write(System.ReadOnlySpan<short>)" IL_002e: ret } """); CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70, options: TestOptions.DebugExe).VerifyDiagnostics(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_Net7_Double() { var source = """ using System; using System.Globalization; static class C { static void Main() { ReadOnlySpan<double> p = stackalloc double[3] { 1.0, 2.9, 3.8 }; Write(p); } static void Write(ReadOnlySpan<double> span) { foreach (double x in span) Console.Write(x.ToString(CultureInfo.InvariantCulture) + " "); } } """; var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "1 2.9 3.8" : null; var verifier = CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 46 (0x2e) .maxstack 4 .locals init (System.ReadOnlySpan<double> V_0) IL_0000: ldc.i4.s 24 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=24_Align=8 <PrivateImplementationDetails>.A469E23C2EF824690D849F86F0B660CC6E91A9E4BE44208A7103F98510BF64F58" IL_000b: call "System.ReadOnlySpan<double> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<double>(System.RuntimeFieldHandle)" IL_0010: stloc.0 IL_0011: ldloca.s V_0 IL_0013: ldc.i4.0 IL_0014: call "ref readonly double System.ReadOnlySpan<double>.this[int].get" IL_0019: ldc.i4.s 24 IL_001b: cpblk IL_001d: ldc.i4.3 IL_001e: newobj "System.Span<double>..ctor(void*, int)" IL_0023: call "System.ReadOnlySpan<double> System.Span<double>.op_Implicit(System.Span<double>)" IL_0028: call "void C.Write(System.ReadOnlySpan<double>)" IL_002d: ret } """); CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70, options: TestOptions.DebugExe).VerifyDiagnostics(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_Net7_Enum() { var source = """ using System; enum E : long { X, Y, Z } static class C { static void Main() { ReadOnlySpan<E> p = stackalloc E[3] { E.X, E.Y, E.Z }; Write(p); } static void Write(ReadOnlySpan<E> span) { foreach (E x in span) Console.Write(x); } } """; var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "XYZ" : null; var verifier = CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 46 (0x2e) .maxstack 4 .locals init (System.ReadOnlySpan<E> V_0) IL_0000: ldc.i4.s 24 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=24_Align=8 <PrivateImplementationDetails>.AB25350E3E65EFEBE24584461683ECDA68725576E825E550038B90E7B14799468" IL_000b: call "System.ReadOnlySpan<E> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<E>(System.RuntimeFieldHandle)" IL_0010: stloc.0 IL_0011: ldloca.s V_0 IL_0013: ldc.i4.0 IL_0014: call "ref readonly E System.ReadOnlySpan<E>.this[int].get" IL_0019: ldc.i4.s 24 IL_001b: cpblk IL_001d: ldc.i4.3 IL_001e: newobj "System.Span<E>..ctor(void*, int)" IL_0023: call "System.ReadOnlySpan<E> System.Span<E>.op_Implicit(System.Span<E>)" IL_0028: call "void C.Write(System.ReadOnlySpan<E>)" IL_002d: ret } """); CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70, options: TestOptions.DebugExe).VerifyDiagnostics(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_Net7_FewElements() { var source = """ using System; static class C { static void Main() { ReadOnlySpan<int> p = stackalloc int[] { 1, 2 }; Write(p); } static void Write(ReadOnlySpan<int> span) { foreach (int x in span) Console.Write(x); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "12" : null, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 29 (0x1d) .maxstack 3 IL_0000: ldc.i4.8 IL_0001: conv.u IL_0002: localloc IL_0004: dup IL_0005: ldc.i4.1 IL_0006: stind.i4 IL_0007: dup IL_0008: ldc.i4.4 IL_0009: add IL_000a: ldc.i4.2 IL_000b: stind.i4 IL_000c: ldc.i4.2 IL_000d: newobj "System.Span<int>..ctor(void*, int)" IL_0012: call "System.ReadOnlySpan<int> System.Span<int>.op_Implicit(System.Span<int>)" IL_0017: call "void C.Write(System.ReadOnlySpan<int>)" IL_001c: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_ZeroElements_Byte() { var source = """ using System; static class C { static void Main() { ReadOnlySpan<byte> p = stackalloc byte[0]; Write(p); } static void Write(ReadOnlySpan<byte> span) { foreach (byte x in span) Console.Write(x); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "" : null, verify: Verification.FailsPEVerify, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 20 (0x14) .maxstack 1 .locals init (System.Span<byte> V_0) IL_0000: ldloca.s V_0 IL_0002: initobj "System.Span<byte>" IL_0008: ldloc.0 IL_0009: call "System.ReadOnlySpan<byte> System.Span<byte>.op_Implicit(System.Span<byte>)" IL_000e: call "void C.Write(System.ReadOnlySpan<byte>)" IL_0013: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestReadOnlySpan_ZeroElements_Int() { var source = """ using System; static class C { static void Main() { ReadOnlySpan<int> p = stackalloc int[0]; Write(p); } static void Write(ReadOnlySpan<int> span) { foreach (int x in span) Console.Write(x); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "" : null, verify: Verification.FailsPEVerify, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 20 (0x14) .maxstack 1 .locals init (System.Span<int> V_0) IL_0000: ldloca.s V_0 IL_0002: initobj "System.Span<int>" IL_0008: ldloc.0 IL_0009: call "System.ReadOnlySpan<int> System.Span<int>.op_Implicit(System.Span<int>)" IL_000e: call "void C.Write(System.ReadOnlySpan<int>)" IL_0013: ret } """); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] [InlineData((int)WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__CreateSpanRuntimeFieldHandle)] [InlineData((int)WellKnownMember.System_ReadOnlySpan_T__get_Item)] public void TestPointerCreateSpan(int missingMember) { var source = """ using System; unsafe static class C { static void Main() { int* p = stackalloc int[3] { 1, 2, 3 }; Write(p); } static void Write(int* span) { for (int i = 0; i < 3; i++) Console.Write(span[i]); } } """; var output = "123"; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? output : null, verify: Verification.Fails, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 38 (0x26) .maxstack 4 .locals init (System.ReadOnlySpan<int> V_0) IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12_Align=4 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D4" IL_000b: call "System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)" IL_0010: stloc.0 IL_0011: ldloca.s V_0 IL_0013: ldc.i4.0 IL_0014: call "ref readonly int System.ReadOnlySpan<int>.this[int].get" IL_0019: ldc.i4.s 12 IL_001b: unaligned. 4 IL_001e: cpblk IL_0020: call "void C.Write(int*)" IL_0025: ret } """); CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? output : null, verify: Verification.Fails, options: TestOptions.UnsafeDebugExe, targetFramework: TargetFramework.Net70).VerifyDiagnostics(); var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); comp.MakeMemberMissing((WellKnownMember)missingMember); verifier = CompileAndVerify(comp, expectedOutput: ExecutionConditionUtil.IsCoreClr ? output : null, verify: Verification.Fails); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 27 (0x1b) .maxstack 4 IL_0000: ldc.i4.s 12 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldc.i4.1 IL_0007: stind.i4 IL_0008: dup IL_0009: ldc.i4.4 IL_000a: add IL_000b: ldc.i4.2 IL_000c: stind.i4 IL_000d: dup IL_000e: ldc.i4.2 IL_000f: conv.i IL_0010: ldc.i4.4 IL_0011: mul IL_0012: add IL_0013: ldc.i4.3 IL_0014: stind.i4 IL_0015: call "void C.Write(int*)" IL_001a: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestPointerCreateSpan_NonBlittableType() { var source = """ using System; unsafe static class C { static void Main() { decimal* p = stackalloc decimal[3] { 1m, 2m, 3m }; Write(p); } static void Write(decimal* span) { for (int i = 0; i < 3; i++) Console.Write(span[i]); } } """; var verifier = CompileAndVerify(source, expectedOutput: ExecutionConditionUtil.IsCoreClr ? "123" : null, verify: Verification.Fails, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.Main", """ { // Code size 55 (0x37) .maxstack 4 IL_0000: ldc.i4.s 48 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldsfld "decimal decimal.One" IL_000b: stobj "decimal" IL_0010: dup IL_0011: ldc.i4.s 16 IL_0013: add IL_0014: ldc.i4.2 IL_0015: newobj "decimal..ctor(int)" IL_001a: stobj "decimal" IL_001f: dup IL_0020: ldc.i4.2 IL_0021: conv.i IL_0022: ldc.i4.s 16 IL_0024: mul IL_0025: add IL_0026: ldc.i4.3 IL_0027: newobj "decimal..ctor(int)" IL_002c: stobj "decimal" IL_0031: call "void C.Write(decimal*)" IL_0036: ret } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69325")] public void TestMixed() { var source = """ using System; static class C { static void Main() => M(4); static void M(int i) { ReadOnlySpan<int> p = stackalloc int[] { 1, 2, 3, i }; Write(p); } static void Write(ReadOnlySpan<int> span) { foreach (int x in span) Console.Write(x); } } """; var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "1234" : null; var verifier = CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.M", """ { // Code size 57 (0x39) .maxstack 4 .locals init (System.ReadOnlySpan<int> V_0) IL_0000: ldc.i4.s 16 IL_0002: conv.u IL_0003: localloc IL_0005: dup IL_0006: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=16_Align=4 <PrivateImplementationDetails>.81C1A5A2F482E82CA2C66653482AB24E6D90944BF183C8164E8F8F8D72DB60DB4" IL_000b: call "System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)" IL_0010: stloc.0 IL_0011: ldloca.s V_0 IL_0013: ldc.i4.0 IL_0014: call "ref readonly int System.ReadOnlySpan<int>.this[int].get" IL_0019: ldc.i4.s 16 IL_001b: unaligned. 4 IL_001e: cpblk IL_0020: dup IL_0021: ldc.i4.3 IL_0022: conv.i IL_0023: ldc.i4.4 IL_0024: mul IL_0025: add IL_0026: ldarg.0 IL_0027: stind.i4 IL_0028: ldc.i4.4 IL_0029: newobj "System.Span<int>..ctor(void*, int)" IL_002e: call "System.ReadOnlySpan<int> System.Span<int>.op_Implicit(System.Span<int>)" IL_0033: call "void C.Write(System.ReadOnlySpan<int>)" IL_0038: ret } """); CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.Fails, targetFramework: TargetFramework.Net70, options: TestOptions.DebugExe).VerifyDiagnostics(); } private static string GetSource(string pointerType) => $@" using System; using T = {pointerType}; static unsafe class C {{ static void Print(T* p) {{ for (int i = 0; i < 3; i++) Console.Write(p[i]); }} static void Main() {{ T* p = stackalloc T[3] {{ 1, 2, 3 }}; Print(p); }} }} "; private void Test(string pointerType, string il) => CompileAndVerify(GetSource(pointerType), parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3), options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"123").VerifyIL("C.Main", il); } }