diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 09c765ed416..0ff7e74cc1c 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -369,36 +369,63 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s builder.WriteCompressedInteger( 0 ) builder.WriteCompressedInteger( MetadataTokens.GetRowNumber(DocumentHandle.op_Implicit(getDocumentHandle (sps.[i].Document))) ) else + //============================================================================================================================================= // Sequence-point-record - let offsetDelta = - if i > 0 then sps.[i].Offset - sps.[i - 1].Offset // delta from previous offset - else sps.[i].Offset // delta IL offset - - if i < 1 || offsetDelta <> 0 then // ILOffset must not be 0 + // Validate these with magic numbers according to the portable pdb spec Sequence point dexcription: + // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#methoddebuginformation-table-0x31 + // + // So the spec is actually bit iffy!!!!! (More like guidelines really. ) + // It uses code similar to this to validate the values + // if (result < 0 || result >= ushort.MaxValue) // be errorfull + // Spec Says 0x10000 and value max = 0xFFFF but it can't even be = to maxvalue, and so the range is 0 .. 0xfffe inclusive + //============================================================================================================================================= + + let capValue v maxValue = + if v < 0 then 0 + elif v > maxValue then maxValue + else v + + let capOffset v = capValue v 0xfffe + let capLine v = capValue v 0x1ffffffe + let capColumn v = capValue v 0xfffe + + let offset = capOffset sps.[i].Offset + let startLine = capLine sps.[i].Line + let endLine = capLine sps.[i].EndLine + let startColumn = capColumn sps.[i].Column + let endColumn = capColumn sps.[i].EndColumn + + let offsetDelta = // delta from previous offset + if i > 0 then offset - capOffset sps.[i - 1].Offset + else offset + + if i < 1 || offsetDelta > 0 then builder.WriteCompressedInteger(offsetDelta) - if sps.[i].Line = 0xfeefee && sps.[i].EndLine = 0xfeefee then // Hidden-sequence-point-record + // Hidden-sequence-point-record + if startLine = 0xfeefee || endLine = 0xfeefee || (startColumn = 0 && endColumn = 0) + then builder.WriteCompressedInteger(0) builder.WriteCompressedInteger(0) else // Non-hidden-sequence-point-record - let deltaLines = sps.[i].EndLine - sps.[i].Line // lines + let deltaLines = endLine - startLine // lines builder.WriteCompressedInteger(deltaLines) - let deltaColumns = sps.[i].EndColumn - sps.[i].Column // Columns + let deltaColumns = endColumn - startColumn // Columns if deltaLines = 0 then builder.WriteCompressedInteger(deltaColumns) else builder.WriteCompressedSignedInteger(deltaColumns) if previousNonHiddenStartLine < 0 then // delta Start Line & Column: - builder.WriteCompressedInteger(sps.[i].Line) - builder.WriteCompressedInteger(sps.[i].Column) + builder.WriteCompressedInteger(startLine) + builder.WriteCompressedInteger(startColumn) else - builder.WriteCompressedSignedInteger(sps.[i].Line - previousNonHiddenStartLine) - builder.WriteCompressedSignedInteger(sps.[i].Column - previousNonHiddenStartColumn) + builder.WriteCompressedSignedInteger(startLine - previousNonHiddenStartLine) + builder.WriteCompressedSignedInteger(startColumn - previousNonHiddenStartColumn) - previousNonHiddenStartLine <- sps.[i].Line - previousNonHiddenStartColumn <- sps.[i].Column + previousNonHiddenStartLine <- startLine + previousNonHiddenStartColumn <- startColumn getDocumentHandle singleDocumentIndex, metadata.GetOrAddBlob(builder) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 2c5f4d1abc5..2aa2ffd100f 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -14,14 +14,6 @@ $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 true true - true - true - - - - - full - false diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index a5068dae2d6..561900cdb80 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -805,7 +805,10 @@ and /// Get the syntactic range of source code covered by this construct. member e.Range = match e with - | SynExpr.Paren (range=m) + | SynExpr.Paren (_, leftParenRange, rightParenRange, r) -> + match rightParenRange with + | Some rightParenRange when leftParenRange.FileIndex <> rightParenRange.FileIndex -> leftParenRange + | _ -> r | SynExpr.Quote (range=m) | SynExpr.Const (range=m) | SynExpr.Typed (range=m) diff --git a/src/utils/prim-parsing.fs b/src/utils/prim-parsing.fs index c9ff1bb595f..9ce01bff907 100644 --- a/src/utils/prim-parsing.fs +++ b/src/utils/prim-parsing.fs @@ -361,38 +361,49 @@ module internal Implementation = #if DEBUG if Flags.debug then Console.Write("reduce popping {0} values/states, lookahead {1}", n, report haveLookahead lookaheadToken) #endif - for i = 0 to n - 1 do + // For every range to reduce merge it + for i = 0 to n - 1 do if valueStack.IsEmpty then failwith "empty symbol stack" - let topVal = valueStack.Peep() + let topVal = valueStack.Peep() // Grab topVal valueStack.Pop() stateStack.Pop() - ruleValues.[(n-i)-1] <- topVal.value - ruleStartPoss.[(n-i)-1] <- topVal.startPos - ruleEndPoss.[(n-i)-1] <- topVal.endPos - if i = 0 then lhsPos.[1] <- topVal.endPos - if i = n - 1 then lhsPos.[0] <- topVal.startPos - - // Use the lookahead token to populate the locations if the rhs is empty - if n = 0 then + + let ruleIndex = (n-i)-1 + ruleValues.[ruleIndex] <- topVal.value + ruleStartPoss.[ruleIndex] <- topVal.startPos + ruleEndPoss.[ruleIndex] <- topVal.endPos + + if i = 0 then + // Initial range + lhsPos.[0] <- topVal.startPos + lhsPos.[1] <- topVal.endPos + elif topVal.startPos.FileIndex = lhsPos.[1].FileIndex && topVal.startPos.Line <= lhsPos.[1].Line then + // Reduce range if same file as the initial end point + lhsPos.[0] <- topVal.startPos + + // Use the lookahead token to populate the locations if the rhs is empty + if n = 0 then if haveLookahead then - lhsPos.[0] <- lookaheadStartPos - lhsPos.[1] <- lookaheadEndPos + lhsPos.[0] <- lookaheadStartPos + lhsPos.[1] <- lookaheadEndPos else lhsPos.[0] <- lexbuf.StartPos lhsPos.[1] <- lexbuf.EndPos - try - // printf "reduce %d\n" prod - let redResult = reduction parseState - valueStack.Push(ValueInfo(redResult, lhsPos.[0], lhsPos.[1])) + try + // printf "reduce %d\n" prod + let redResult = reduction parseState + let valueInfo = ValueInfo(redResult, lhsPos.[0], lhsPos.[1]) + valueStack.Push(valueInfo) let currState = stateStack.Peep() let newGotoState = gotoTable.Read(int tables.productionToNonTerminalTable.[prod], currState) stateStack.Push(newGotoState) + #if DEBUG if Flags.debug then Console.WriteLine(" goto state {0}", newGotoState) #endif - with - | Accept res -> - finished <- true + with + | Accept res -> + finished <- true valueStack.Push(ValueInfo(res, lhsPos.[0], lhsPos.[1])) | RecoverableParseError -> #if DEBUG