diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
index 075a00c5bfea622974bd92930c3ced812d0b5245..d7f9b63e09b9e9da92523f50454ea82ca4ccb3c5 100644
--- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
@@ -526,6 +526,130 @@ public void CustomDebugEntryPoint_Errors()
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
diff --git a/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs b/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs
index e3aaa789f7f03d8d701c9c9d84ee32e06663c9f1..9a34a653a47195b5017122edba951082f48395fd 100644
--- a/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs
+++ b/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs
@@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.CodeGen
/// Represents a sequence point before translation by #line/ExternalSource directives.
///
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
- internal struct RawSequencePoint
+ internal readonly struct RawSequencePoint
{
internal readonly SyntaxTree SyntaxTree;
internal readonly int ILMarker;
diff --git a/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs b/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs
index da5dc27fb631e0695e0c26bdcee421bcbd38b8b0..a0189f3b9aea8d16e117f902f1c2ec8c2db2aa4e 100644
--- a/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs
+++ b/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs
@@ -1,15 +1,9 @@
// 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.Collections.Generic;
-using System.Collections.Immutable;
using System.Diagnostics;
-using System.Linq;
-using System.Text;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
-using Roslyn.Utilities;
-using Cci = Microsoft.Cci;
namespace Microsoft.CodeAnalysis.CodeGen
{
@@ -22,8 +16,6 @@ namespace Microsoft.CodeAnalysis.CodeGen
///
internal class SequencePointList
{
- internal const int HiddenSequencePointLine = 0xFEEFEE;
-
private readonly SyntaxTree _tree;
private readonly OffsetAndSpan[] _points;
private SequencePointList _next; // Linked list of all points.
@@ -142,7 +134,7 @@ private static OffsetAndSpan[] GetSubArray(ArrayBuilder seqPoi
// a hidden sequence point.
bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan;
- FileLinePositionSpan fileLinePositionSpan = default(FileLinePositionSpan);
+ FileLinePositionSpan fileLinePositionSpan = default;
if (!isHidden)
{
fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility(span, out isHidden);
@@ -161,9 +153,9 @@ private static OffsetAndSpan[] GetSubArray(ArrayBuilder seqPoi
builder.Add(new Cci.SequencePoint(
lastDebugDocument,
offset: offsetAndSpan.Offset,
- startLine: HiddenSequencePointLine,
+ startLine: Cci.SequencePoint.HiddenLine,
startColumn: 0,
- endLine: HiddenSequencePointLine,
+ endLine: Cci.SequencePoint.HiddenLine,
endColumn: 0));
}
}
@@ -178,13 +170,34 @@ private static OffsetAndSpan[] GetSubArray(ArrayBuilder seqPoi
if (lastDebugDocument != null)
{
+ int startLine = (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1;
+ int endLine = (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1;
+ int startColumn = fileLinePositionSpan.StartLinePosition.Character + 1;
+ int endColumn = fileLinePositionSpan.EndLinePosition.Character + 1;
+
+ // Trim column number if necessary.
+ // Column must be in range [0, 0xffff) and end column must be greater than start column if on the same line.
+ // The Portable PDB specifies 0x10000, but System.Reflection.Metadata reader has an off-by-one error.
+ // Windows PDBs allow the same range.
+ const int MaxColumn = ushort.MaxValue - 1;
+
+ if (startColumn > MaxColumn)
+ {
+ startColumn = (startLine == endLine) ? MaxColumn - 1 : MaxColumn;
+ }
+
+ if (endColumn > MaxColumn)
+ {
+ endColumn = MaxColumn;
+ }
+
builder.Add(new Cci.SequencePoint(
lastDebugDocument,
offset: offsetAndSpan.Offset,
- startLine: (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1,
- startColumn: fileLinePositionSpan.StartLinePosition.Character + 1,
- endLine: (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1,
- endColumn: fileLinePositionSpan.EndLinePosition.Character + 1
+ startLine: startLine,
+ startColumn: (ushort)startColumn,
+ endLine: endLine,
+ endColumn: (ushort)endColumn
));
}
}
diff --git a/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs b/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs
index c6d566dd6dcc4eaca98f8c697db35b37916f3854..7b065b01bb35a86fa3998a8ac81a7609877cdc05 100644
--- a/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs
+++ b/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs
@@ -8,22 +8,24 @@ namespace Microsoft.Cci
{
[SuppressMessage("Performance", "CA1067", Justification = "Equality not actually implemented")]
[DebuggerDisplay("{" + nameof(GetDebuggerDisplay) + "(),nq}")]
- internal struct SequencePoint
+ internal readonly struct SequencePoint
{
+ public const int HiddenLine = 0xfeefee;
+
public readonly int Offset;
public readonly int StartLine;
- public readonly int StartColumn;
public readonly int EndLine;
- public readonly int EndColumn;
+ public readonly ushort StartColumn;
+ public readonly ushort EndColumn;
public readonly DebugSourceDocument Document;
public SequencePoint(
DebugSourceDocument document,
int offset,
int startLine,
- int startColumn,
+ ushort startColumn,
int endLine,
- int endColumn)
+ ushort endColumn)
{
Debug.Assert(document != null);
@@ -35,7 +37,7 @@ internal struct SequencePoint
Document = document;
}
- public bool IsHidden => StartLine == 0xfeefee;
+ public bool IsHidden => StartLine == HiddenLine;
public override int GetHashCode()
{
diff --git a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs
index 46c907486a1200eb5635e75727990f8c44b5f796..5499ed4ecf117ef52ffe31d778215355c8e00869 100644
--- a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs
+++ b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs
@@ -758,7 +758,7 @@ internal static uint GetOffset(int methodToken, ISymUnmanagedReader symReader, i
{
var sequencePoints = symMethod.GetSequencePoints();
ilOffset = atLineNumber < 0
- ? sequencePoints.Where(sp => sp.StartLine != SequencePointList.HiddenSequencePointLine).Select(sp => sp.Offset).FirstOrDefault()
+ ? sequencePoints.Where(sp => sp.StartLine != Cci.SequencePoint.HiddenLine).Select(sp => sp.Offset).FirstOrDefault()
: sequencePoints.First(sp => sp.StartLine == atLineNumber).Offset;
}
}