// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Text; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.PdbUtilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.PDB { public class PDBTests : CSharpPDBTestBase { private static readonly MetadataReference[] s_valueTupleRefs = new[] { SystemRuntimeFacadeRef, ValueTupleRef }; #region General [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void EmitDebugInfoForSourceTextWithoutEncoding1() { var tree1 = SyntaxFactory.ParseSyntaxTree("class A { }", encoding: null, path: "Foo.cs"); var tree2 = SyntaxFactory.ParseSyntaxTree("class B { }", encoding: null, path: ""); var tree3 = SyntaxFactory.ParseSyntaxTree(SourceText.From("class C { }", encoding: null), path: "Bar.cs"); var tree4 = SyntaxFactory.ParseSyntaxTree("class D { }", encoding: Encoding.UTF8, path: "Baz.cs"); var comp = CSharpCompilation.Create("Compilation", new[] { tree1, tree2, tree3, tree4 }, new[] { MscorlibRef }, options: TestOptions.ReleaseDll); var result = comp.Emit(new MemoryStream(), pdbStream: new MemoryStream()); result.Diagnostics.Verify( // Foo.cs(1,1): error CS8055: Cannot emit debug information for a source text without encoding. Diagnostic(ErrorCode.ERR_EncodinglessSyntaxTree, "class A { }").WithLocation(1, 1), // Bar.cs(1,1): error CS8055: Cannot emit debug information for a source text without encoding. Diagnostic(ErrorCode.ERR_EncodinglessSyntaxTree, "class C { }").WithLocation(1, 1)); Assert.False(result.Success); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void EmitDebugInfoForSourceTextWithoutEncoding2() { var tree1 = SyntaxFactory.ParseSyntaxTree("class A { public void F() { } }", encoding: Encoding.Unicode, path: "Foo.cs"); var tree2 = SyntaxFactory.ParseSyntaxTree("class B { public void F() { } }", encoding: null, path: ""); var tree3 = SyntaxFactory.ParseSyntaxTree("class C { public void F() { } }", encoding: new UTF8Encoding(true, false), path: "Bar.cs"); var tree4 = SyntaxFactory.ParseSyntaxTree(SourceText.From("class D { public void F() { } }", new UTF8Encoding(false, false)), path: "Baz.cs"); var comp = CSharpCompilation.Create("Compilation", new[] { tree1, tree2, tree3, tree4 }, new[] { MscorlibRef }, options: TestOptions.ReleaseDll); var result = comp.Emit(new MemoryStream(), pdbStream: new MemoryStream()); result.Diagnostics.Verify(); Assert.True(result.Success); var hash1 = CryptographicHashProvider.ComputeSha1(Encoding.Unicode.GetBytesWithPreamble(tree1.ToString())).ToArray(); var hash3 = CryptographicHashProvider.ComputeSha1(new UTF8Encoding(true, false).GetBytesWithPreamble(tree3.ToString())).ToArray(); var hash4 = CryptographicHashProvider.ComputeSha1(new UTF8Encoding(false, false).GetBytesWithPreamble(tree4.ToString())).ToArray(); comp.VerifyPdb(@" ", options: PdbValidationOptions.ExcludeMethods); } [WorkItem(846584, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/846584")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void RelativePathForExternalSource_Sha1() { var text1 = @" #pragma checksum ""..\Test2.cs"" ""{406ea660-64cf-4c82-b6f0-42d48172a799}"" ""BA8CBEA9C2EFABD90D53B616FB80A081"" public class C { public void InitializeComponent() { #line 4 ""..\Test2.cs"" InitializeComponent(); #line default } } "; var compilation = CreateCompilation( new[] { Parse(text1, @"C:\Folder1\Folder2\Test1.cs") }, options: TestOptions.DebugDll.WithSourceReferenceResolver(SourceFileResolver.Default)); compilation.VerifyPdb(@" "); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SymWriterErrors() { var source0 = @"class C { }"; var compilation = CreateCompilation(source0, options: TestOptions.DebugDll); // Verify full metadata contains expected rows. var result = compilation.Emit( peStream: new MemoryStream(), metadataPEStream: null, pdbStream: new MemoryStream(), xmlDocumentationStream: null, cancellationToken: default, win32Resources: null, manifestResources: null, options: null, debugEntryPoint: null, sourceLinkStream: null, embeddedTexts: null, testData: new CompilationTestData() { SymWriterFactory = _ => new MockSymUnmanagedWriter() }); result.Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'MockSymUnmanagedWriter error message' Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments("MockSymUnmanagedWriter error message")); Assert.False(result.Success); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SymWriterErrors2() { var source0 = @"class C { }"; var compilation = CreateCompilation(source0, options: TestOptions.DebugDll); // Verify full metadata contains expected rows. var result = compilation.Emit( peStream: new MemoryStream(), metadataPEStream: null, pdbStream: new MemoryStream(), xmlDocumentationStream: null, cancellationToken: default, win32Resources: null, manifestResources: null, options: null, debugEntryPoint: null, sourceLinkStream: null, embeddedTexts: null, testData: new CompilationTestData() { SymWriterFactory = SymWriterTestUtilities.ThrowingFactory }); result.Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'The version of Windows PDB writer is older than required: ''' Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(string.Format(CodeAnalysisResources.SymWriterOlderVersionThanRequired, ""))); Assert.False(result.Success); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SymWriterErrors3() { var source0 = @"class C { }"; var compilation = CreateCompilation(source0, options: TestOptions.DebugDll.WithDeterministic(true)); // Verify full metadata contains expected rows. var result = compilation.Emit( peStream: new MemoryStream(), metadataPEStream: null, pdbStream: new MemoryStream(), xmlDocumentationStream: null, cancellationToken: default, win32Resources: null, manifestResources: null, options: null, debugEntryPoint: null, sourceLinkStream: null, embeddedTexts: null, testData: new CompilationTestData() { SymWriterFactory = SymWriterTestUtilities.ThrowingFactory }); result.Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'Windows PDB writer doesn't support deterministic compilation: ''' Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments(string.Format(CodeAnalysisResources.SymWriterNotDeterministic, ""))); Assert.False(result.Success); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SymWriterErrors4() { var source0 = @"class C { }"; var compilation = CreateCompilation(source0); // Verify full metadata contains expected rows. var result = compilation.Emit( peStream: new MemoryStream(), metadataPEStream: null, pdbStream: new MemoryStream(), xmlDocumentationStream: null, cancellationToken: default, win32Resources: null, manifestResources: null, options: null, debugEntryPoint: null, sourceLinkStream: null, embeddedTexts: null, testData: new CompilationTestData() { SymWriterFactory = _ => throw new DllNotFoundException("xxx") }); result.Diagnostics.Verify( // error CS0041: Unexpected error writing debug information -- 'xxx' Diagnostic(ErrorCode.FTL_DebugEmitFailure).WithArguments("xxx")); Assert.False(result.Success); } [WorkItem(1067635, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067635")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SuppressDynamicAndEncCDIForWinRT() { var source = @" public class C { public static void F() { dynamic a = 1; int b = 2; foreach (var x in new[] { 1,2,3 }) { System.Console.WriteLine(a * b); } } } "; var debug = CreateCompilation(source, new[] { CSharpRef }, options: TestOptions.DebugWinMD); debug.VerifyPdb(@" ", format: DebugInformationFormat.Pdb, options: PdbValidationOptions.SkipConversionValidation); var release = CreateCompilation(source, new[] { CSharpRef }, options: TestOptions.ReleaseWinMD); release.VerifyPdb(@" ", format: DebugInformationFormat.Pdb, options: PdbValidationOptions.SkipConversionValidation); } [WorkItem(1067635, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067635")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SuppressTupleElementNamesCDIForWinRT() { var source = @"class C { static void F() { (int A, int B) o = (1, 2); } }"; var debug = CreateCompilation(source, options: TestOptions.DebugWinMD); debug.VerifyPdb( @" ", format: DebugInformationFormat.Pdb, options: PdbValidationOptions.SkipConversionValidation); var release = CreateCompilation(source, options: TestOptions.ReleaseWinMD); release.VerifyPdb( @" ", format: DebugInformationFormat.Pdb, options: PdbValidationOptions.SkipConversionValidation); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void DuplicateDocuments() { var source1 = @"class C { static void F() { } }"; var source2 = @"class D { static void F() { } }"; var tree1 = Parse(source1, @"foo.cs"); var tree2 = Parse(source2, @"foo.cs"); var comp = CreateCompilation(new[] { tree1, tree2 }); // the first file wins (checksum CB 22 ...) comp.VerifyPdb(@" "); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void CustomDebugEntryPoint_DLL() { var source = @"class C { static void F() { } }"; var c = CreateCompilation(source, options: TestOptions.DebugDll); var f = c.GetMember("C.F"); c.VerifyPdb(@" ", debugEntryPoint: f, options: PdbValidationOptions.ExcludeScopes | PdbValidationOptions.ExcludeSequencePoints | PdbValidationOptions.ExcludeCustomDebugInformation); var peReader = new PEReader(c.EmitToArray(debugEntryPoint: f)); int peEntryPointToken = peReader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress; Assert.Equal(0, peEntryPointToken); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void CustomDebugEntryPoint_EXE() { var source = @"class M { static void Main() { } } class C { static void F() { } }"; var c = CreateCompilation(source, options: TestOptions.DebugExe); var f = c.GetMember("C.F"); c.VerifyPdb(@" ", debugEntryPoint: f, options: PdbValidationOptions.ExcludeScopes | PdbValidationOptions.ExcludeSequencePoints | PdbValidationOptions.ExcludeCustomDebugInformation); var peReader = new PEReader(c.EmitToArray(debugEntryPoint: f)); int peEntryPointToken = peReader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress; var mdReader = peReader.GetMetadataReader(); var methodDef = mdReader.GetMethodDefinition((MethodDefinitionHandle)MetadataTokens.Handle(peEntryPointToken)); Assert.Equal("Main", mdReader.GetString(methodDef.Name)); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void CustomDebugEntryPoint_Errors() { var source1 = @"class C { static void F() { } } class D { static void G() {} }"; var source2 = @"class C { static void F() { } }"; var c1 = CreateCompilation(source1, options: TestOptions.DebugDll); var c2 = CreateCompilation(source2, options: TestOptions.DebugDll); var f1 = c1.GetMember("C.F"); var f2 = c2.GetMember("C.F"); var g = c1.GetMember("D.G"); var d = c1.GetMember("D"); Assert.NotNull(f1); Assert.NotNull(f2); Assert.NotNull(g); Assert.NotNull(d); var stInt = c1.GetSpecialType(SpecialType.System_Int32); var d_t_g_int = g.Construct(stInt); var d_int = d.Construct(stInt); var d_int_g = d_int.GetMember("G"); var d_int_g_int = d_int_g.Construct(stInt); var result = c1.Emit(new MemoryStream(), new MemoryStream(), debugEntryPoint: f2); result.Diagnostics.Verify( // error CS8096: Debug entry point must be a definition of a source method in the current compilation. Diagnostic(ErrorCode.ERR_DebugEntryPointNotSourceMethodDefinition)); result = c1.Emit(new MemoryStream(), new MemoryStream(), debugEntryPoint: d_t_g_int); result.Diagnostics.Verify( // error CS8096: Debug entry point must be a definition of a source method in the current compilation. Diagnostic(ErrorCode.ERR_DebugEntryPointNotSourceMethodDefinition)); result = c1.Emit(new MemoryStream(), new MemoryStream(), debugEntryPoint: d_int_g); result.Diagnostics.Verify( // error CS8096: Debug entry point must be a definition of a source method in the current compilation. Diagnostic(ErrorCode.ERR_DebugEntryPointNotSourceMethodDefinition)); result = c1.Emit(new MemoryStream(), new MemoryStream(), debugEntryPoint: d_int_g_int); result.Diagnostics.Verify( // error CS8096: Debug entry point must be a definition of a source method in the current compilation. Diagnostic(ErrorCode.ERR_DebugEntryPointNotSourceMethodDefinition)); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem(768862, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/768862")] public void TestLargeLineDelta() { var verbatim = string.Join("\r\n", Enumerable.Repeat("x", 1000)); var source = $@" class C {{ public static void Main() => System.Console.WriteLine(@""{verbatim}""); }} "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C.Main", @" ", format: DebugInformationFormat.PortablePdb); // Native PDBs only support spans with line delta <= 127 (7 bit) // https://github.com/Microsoft/microsoft-pdb/blob/master/include/cvinfo.h#L4621 c.VerifyPdb("C.Main", @" ", format: DebugInformationFormat.Pdb); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem(20118, "https://github.com/dotnet/roslyn/issues/20118")] public void TestLargeStartAndEndColumn_SameLine() { var spaces = new string(' ', 0x10000); var source = $@" class C {{ public static void Main() => {spaces}System.Console.WriteLine(""{spaces}""); }} "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C.Main", @" "); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] [WorkItem(20118, "https://github.com/dotnet/roslyn/issues/20118")] public void TestLargeStartAndEndColumn_DifferentLine() { var spaces = new string(' ', 0x10000); var source = $@" class C {{ public static void Main() => {spaces}System.Console.WriteLine( ""{spaces}""); }} "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C.Main", @" "); } #endregion #region Method Bodies [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void TestBasic() { var source = @" class Program { Program() { } static void Main(string[] args) { Program p = new Program(); } } "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("Program.Main", @" "); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void TestSimpleLocals() { var source = @" class C { void Method() { //local at method scope object version = 6; System.Console.WriteLine(""version {0}"", version); { //a scope that defines no locals { //a nested local object foob = 1; System.Console.WriteLine(""foob {0}"", foob); } { //a nested local int foob1 = 1; System.Console.WriteLine(""foob1 {0}"", foob1); } System.Console.WriteLine(""Eva""); } } } "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C.Method", @" "); } [WorkItem(7244, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/7244")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void ConstructorsWithoutInitializers() { var source = @"class C { C() { object o; } C(object x) { object y = x; } }"; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C..ctor", @" "); } [WorkItem(7244, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/7244")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void ConstructorsWithInitializers() { var source = @"class C { static object G = 1; object F = G; C() { object o; } C(object x) { object y = x; } }"; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C..ctor", @" "); } /// /// Although the debugging info attached to DebuggerHidden method is not used by the debugger /// (the debugger doesn't ever stop in the method) Dev11 emits the info and so do we. /// /// StepThrough method needs the information if JustMyCode is disabled and a breakpoint is set within the method. /// NonUserCode method needs the information if JustMyCode is disabled. /// /// It's up to the tool that consumes the debugging information, not the compiler to decide whether to ignore the info or not. /// BTW, the information can actually be retrieved at runtime from the PDB file via Reflection StackTrace. /// [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void MethodsWithDebuggerAttributes() { var source = @" using System; using System.Diagnostics; class Program { [DebuggerHidden] static void Hidden() { int x = 1; Console.WriteLine(x); } [DebuggerStepThrough] static void StepThrough() { int y = 1; Console.WriteLine(y); } [DebuggerNonUserCode] static void NonUserCode() { int z = 1; Console.WriteLine(z); } } "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb(@" "); } /// /// If a synthesized method contains any user code, /// the method must have a sequence point at /// offset 0 for correct stepping behavior. /// [WorkItem(804681, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/804681")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SequencePointAtOffset0() { string source = @"using System; class C { static Func F = x => { Func f = o => 1; Func, Func> g = h => y => h(y); return g(f)(null); }; }"; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb(@" 2 "); } /// /// Leading trivia is not included in the syntax offset. /// [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SyntaxOffsetInPresenceOfTrivia_Methods() { string source = @" class C { public static void Main1() /*Comment1*/{/*Comment2*/int a = 1;/*Comment3*/}/*Comment4*/ public static void Main2() {/*Comment2*/int a = 2;/*Comment3*/}/*Comment4*/ }"; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); // verify that both syntax offsets are the same c.VerifyPdb(@" "); } /// /// Leading and trailing trivia are not included in the syntax offset. /// [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void SyntaxOffsetInPresenceOfTrivia_Initializers() { string source = @" using System; class C1 { public static Func e=() => 0; public static Func f/*Comment0*/=/*Comment1*/() => 1;/*Comment2*/ public static Func g=() => 2; } class C2 { public static Func e=() => 0; public static Func f=/*Comment1*/() => 1; public static Func g=() => 2; } "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); // verify that syntax offsets of both .cctor's are the same c.VerifyPdb("C1..cctor", @" 4 "); c.VerifyPdb("C2..cctor", @" 4 "); } #endregion #region ReturnStatement [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void Return_Method1() { var source = @" class Program { static int Main() { return 1; } } "; var v = CompileAndVerify(source, options: TestOptions.DebugDll); // In order to place a breakpoint on the closing brace we need to save the return expression value to // a local and then load it again (since sequence point needs an empty stack). This variable has to be marked as long-lived. v.VerifyIL("Program.Main", @" { // Code size 7 (0x7) .maxstack 1 .locals init (int V_0) -IL_0000: nop -IL_0001: ldc.i4.1 IL_0002: stloc.0 IL_0003: br.s IL_0005 -IL_0005: ldloc.0 IL_0006: ret }", sequencePoints: "Program.Main"); v.VerifyPdb("Program.Main", @" "); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void Return_Property1() { var source = @" class C { static int P { get { return 1; } } } "; var v = CompileAndVerify(source, options: TestOptions.DebugDll); // In order to place a breakpoint on the closing brace we need to save the return expression value to // a local and then load it again (since sequence point needs an empty stack). This variable has to be marked as long-lived. v.VerifyIL("C.P.get", @" { // Code size 7 (0x7) .maxstack 1 .locals init (int V_0) -IL_0000: nop -IL_0001: ldc.i4.1 IL_0002: stloc.0 IL_0003: br.s IL_0005 -IL_0005: ldloc.0 IL_0006: ret }", sequencePoints: "C.get_P"); v.VerifyPdb("C.get_P", @" "); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void Return_Void1() { var source = @" class Program { static void Main() { return; } } "; var v = CompileAndVerify(source, options: TestOptions.DebugDll); v.VerifyIL("Program.Main", @" { // Code size 4 (0x4) .maxstack 0 -IL_0000: nop -IL_0001: br.s IL_0003 -IL_0003: ret }", sequencePoints: "Program.Main"); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void Return_ExpressionBodied1() { var source = @" class Program { static int Main() => 1; } "; var v = CompileAndVerify(source, options: TestOptions.DebugDll); v.VerifyIL("Program.Main", @" { // Code size 2 (0x2) .maxstack 1 -IL_0000: ldc.i4.1 IL_0001: ret }", sequencePoints: "Program.Main"); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void Return_FromExceptionHandler1() { var source = @" using System; class Program { static int Main() { try { Console.WriteLine(); return 1; } catch (Exception) { return 2; } } } "; var v = CompileAndVerify(source, options: TestOptions.DebugDll); v.VerifyIL("Program.Main", @" { // Code size 20 (0x14) .maxstack 1 .locals init (int V_0) -IL_0000: nop .try { -IL_0001: nop -IL_0002: call ""void System.Console.WriteLine()"" IL_0007: nop -IL_0008: ldc.i4.1 IL_0009: stloc.0 IL_000a: leave.s IL_0012 } catch System.Exception { -IL_000c: pop -IL_000d: nop -IL_000e: ldc.i4.2 IL_000f: stloc.0 IL_0010: leave.s IL_0012 } -IL_0012: ldloc.0 IL_0013: ret }", sequencePoints: "Program.Main"); v.VerifyPdb("Program.Main", @" "); } #endregion #region IfStatement [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void IfStatement() { var source = @" class C { void Method() { bool b = true; if (b) { string s = ""true""; System.Console.WriteLine(s); } else { string s = ""false""; int i = 1; while (i < 100) { int j = i, k = 1; System.Console.WriteLine(j); i = j + k; } i = i + 1; } } } "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); c.VerifyPdb("C.Method", @" "); } #endregion #region WhileStatement [WorkItem(538299, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538299")] [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] public void WhileStatement() { var source = @"using System; public class SeqPointForWhile { public static void Main() { SeqPointForWhile obj = new SeqPointForWhile(); obj.While(234); } int field; public void While(int p) { while (p > 0) // SeqPt should be generated at the end of loop { p = (int)(p / 2); if (p > 100) { continue; } else if (p > 10) { int x = p; field = x; } else { int x = p; Console.WriteLine(x); break; } } field = -1; } } "; var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.ReleaseExe); // Offset 0x01 should be: //