diff --git a/src/tools/illink/src/linker/Linker/MessageOrigin.cs b/src/tools/illink/src/linker/Linker/MessageOrigin.cs index df7f28d288ecef..7d9b3d51eaa9b1 100644 --- a/src/tools/illink/src/linker/Linker/MessageOrigin.cs +++ b/src/tools/illink/src/linker/Linker/MessageOrigin.cs @@ -88,7 +88,7 @@ public MessageOrigin(MessageOrigin other, int ilOffset) { var offset = ILOffset == UnsetILOffset ? method.DebugInformation.SequencePoints[0].Offset : ILOffset; SequencePoint? correspondingSequencePoint = method.DebugInformation.SequencePoints - .Where(s => s.Offset <= offset)?.Last(); + .Where(s => s.Offset <= offset).LastOrDefault(); // If the warning comes from hidden line (compiler generated code typically) // search for any sequence point with non-hidden line number and report that as a best effort. diff --git a/src/tools/illink/test/Mono.Linker.Tests/Tests/MessageContainerTests.cs b/src/tools/illink/test/Mono.Linker.Tests/Tests/MessageContainerTests.cs index 208ffe38369255..99eca61a6bf513 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/Tests/MessageContainerTests.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/Tests/MessageContainerTests.cs @@ -1,7 +1,11 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.IO; +using System.Linq; using Xunit; +using Mono.Cecil; +using Mono.Cecil.Cil; namespace Mono.Linker.Tests { @@ -21,5 +25,61 @@ public void MSBuildFormat() msg = MessageContainer.CreateInfoMessage("log test"); Assert.Equal("ILLink: log test", msg.ToMSBuildString()); } + + [Fact] + public void OriginBeforeFirstSequencePointFallsBackToApplicationName() + { + using ModuleDefinition module = ModuleDefinition.CreateModule("test", ModuleKind.Dll); + var type = new TypeDefinition("Test", "Type", TypeAttributes.Public, module.TypeSystem.Object); + module.Types.Add(type); + + var method = new MethodDefinition("Method", MethodAttributes.Public | MethodAttributes.Static, module.TypeSystem.Void); + type.Methods.Add(method); + + var body = method.Body; + var firstInstruction = Instruction.Create(OpCodes.Nop); + var secondInstruction = Instruction.Create(OpCodes.Ret); + body.Instructions.Add(firstInstruction); + body.Instructions.Add(secondInstruction); + + method.DebugInformation.SequencePoints.Add(new SequencePoint(secondInstruction, new Document("test.cs")) + { + StartLine = 10, + StartColumn = 5, + EndLine = 10, + EndColumn = 6 + }); + + using var assemblyStream = new MemoryStream(); + using var symbolStream = new MemoryStream(); + + module.Write(assemblyStream, new WriterParameters + { + WriteSymbols = true, + SymbolStream = symbolStream, + SymbolWriterProvider = new PortablePdbWriterProvider() + }); + + assemblyStream.Position = 0; + symbolStream.Position = 0; + + using var assembly = AssemblyDefinition.ReadAssembly(assemblyStream, new ReaderParameters + { + ReadSymbols = true, + SymbolStream = symbolStream, + SymbolReaderProvider = new PortablePdbReaderProvider() + }); + + method = assembly.MainModule.GetType("Test.Type").Methods.Single(m => m.Name == "Method"); + firstInstruction = method.Body.Instructions[0]; + Assert.True(firstInstruction.Offset < method.DebugInformation.SequencePoints[0].Offset); + + var msg = MessageContainer.CreateCustomErrorMessage( + "message", + 6001, + origin: new MessageOrigin(method, firstInstruction.Offset)); + + Assert.Equal("ILLink: error IL6001: Test.Type.Method(): message", msg.ToMSBuildString()); + } } }