Skip to content

Commit 8492161

Browse files
committed
Disallow non-decimal line numbers as argument to #sourceLocation
rdar://121668395
1 parent c23360f commit 8492161

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

Sources/SwiftParser/Directives.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,14 @@ extension Parser {
201201

202202
let (unexpectedBeforeLine, line) = self.expect(.keyword(.line))
203203
let (unexpectedBeforeLineColon, lineColon) = self.expect(.colon)
204-
let lineNumber = self.expectWithoutRecovery(.integerLiteral)
204+
var lineNumber = self.expectWithoutRecovery(.integerLiteral)
205+
if !lineNumber.tokenText.allSatisfy({ Unicode.Scalar($0).isDigit }) {
206+
let diagnostic = TokenDiagnostic(
207+
swiftVersion < .v6 ? .unexpectedNonDecimalIntegerLiteralWarning : .unexpectedNonDecimalIntegerLiteralError,
208+
byteOffset: 0
209+
)
210+
lineNumber = lineNumber.tokenView.withTokenDiagnostic(tokenDiagnostic: diagnostic, arena: self.arena)
211+
}
205212

206213
arguments = RawPoundSourceLocationArgumentsSyntax(
207214
unexpectedBeforeFile,

Sources/SwiftParserDiagnostics/LexerDiagnosticMessages.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public enum StaticTokenError: String, DiagnosticMessage {
7878
case spaceAtStartOfRegexLiteral = "bare slash regex literal may not start with space"
7979
case spaceAtEndOfRegexLiteral = "bare slash regex literal may not end with space"
8080
case multilineRegexClosingNotOnNewline = "multi-line regex closing delimiter must appear on new line"
81+
case unexpectedNonDecimalIntegerLiteral = "unexpected non-decimal integer literal"
8182
case unprintableAsciiCharacter = "unprintable ASCII character found in source file"
8283
case unterminatedBlockComment = "unterminated '/*' comment"
8384

@@ -166,7 +167,7 @@ public struct InvalidDigitInIntegerLiteral: TokenError {
166167

167168
/// Downgrades a ``TokenError`` to a ``TokenWarning`` until Swift 6.
168169
public struct ErrorToWarningDowngrade: TokenWarning {
169-
public let error: TokenError
170+
public let error: DiagnosticMessage
170171

171172
public var message: String {
172173
return "\(error.message); this is an error in Swift 6"
@@ -223,6 +224,8 @@ public extension SwiftSyntax.TokenDiagnostic {
223224
case .spaceAtStartOfRegexLiteral: return StaticTokenError.spaceAtStartOfRegexLiteral
224225
case .tokenDiagnosticOffsetOverflow: return StaticTokenError.tokenDiagnosticOffsetOverflow
225226
case .unexpectedBlockCommentEnd: return StaticTokenError.unexpectedBlockCommentEnd
227+
case .unexpectedNonDecimalIntegerLiteralWarning: return ErrorToWarningDowngrade(error: StaticTokenError.unexpectedNonDecimalIntegerLiteral)
228+
case .unexpectedNonDecimalIntegerLiteralError: return StaticTokenError.unexpectedNonDecimalIntegerLiteral
226229
case .unicodeCurlyQuote: return StaticTokenError.unicodeCurlyQuote
227230
case .unprintableAsciiCharacter: return StaticTokenError.unprintableAsciiCharacter
228231
case .unterminatedBlockComment: return StaticTokenError.unterminatedBlockComment

Sources/SwiftSyntax/TokenDiagnostic.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public struct TokenDiagnostic: Hashable, Sendable {
5656
/// The lexer discovered an error but was not able to represent the offset of the error because it would overflow `LexerErrorOffset`.
5757
case tokenDiagnosticOffsetOverflow
5858
case unexpectedBlockCommentEnd
59+
case unexpectedNonDecimalIntegerLiteralWarning
60+
case unexpectedNonDecimalIntegerLiteralError
5961
case unicodeCurlyQuote
6062
case unprintableAsciiCharacter
6163
case unterminatedBlockComment
@@ -95,6 +97,8 @@ public struct TokenDiagnostic: Hashable, Sendable {
9597
case .spaceAtStartOfRegexLiteral: return .error
9698
case .tokenDiagnosticOffsetOverflow: return .error
9799
case .unexpectedBlockCommentEnd: return .error
100+
case .unexpectedNonDecimalIntegerLiteralWarning: return .warning
101+
case .unexpectedNonDecimalIntegerLiteralError: return .error
98102
case .unicodeCurlyQuote: return .error
99103
case .unprintableAsciiCharacter: return .error
100104
case .unterminatedBlockComment: return .error

Tests/SwiftParserTest/DirectiveTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,27 @@ final class DirectiveTests: ParserTestCase {
153153
)
154154
}
155155

156+
func testNonDecimalLineNumberInSourceLocation() {
157+
assertParse(
158+
#"""
159+
#sourceLocation(file: "f.swift", line: 1️⃣0xff)
160+
"""#,
161+
diagnostics: [
162+
DiagnosticSpec(message: "unexpected non-decimal integer literal")
163+
]
164+
)
165+
166+
assertParse(
167+
#"""
168+
#sourceLocation(file: "f.swift", line: 1️⃣0xff)
169+
"""#,
170+
diagnostics: [
171+
DiagnosticSpec(message: "unexpected non-decimal integer literal; this is an error in Swift 6", severity: .warning)
172+
],
173+
swiftVersion: .v5
174+
)
175+
}
176+
156177
public func testUnterminatedPoundIf() {
157178
assertParse(
158179
"#if test1️⃣",

0 commit comments

Comments
 (0)