From a76c91cabd3eb5f31af36a15a7f5e2533586bd52 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 11 Dec 2025 09:32:20 -0800 Subject: [PATCH] [Parser] Accept raw/multiline string literal in #sourceLocation etc. There's no reason to reject these string literals in `#sourceLocation` or `@available(..., message:, renamed:)` etc. We just want to reject string interpolation. Also previously escaped strings are literally used i.e. ```swift print(#file) ``` printed `foo\\bar` instead of `foo\bar` which is wrong. Correctly unescape the literal as regular string literals. --- include/swift/AST/DiagnosticsParse.def | 2 -- lib/Parse/Parser.cpp | 15 +++++++-------- test/Parse/diagnose_availability.swift | 4 ++-- test/Parse/line-directive-executable.swift | 13 +++++++++++++ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 95b9690a064af..4656c32c19e04 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -90,8 +90,6 @@ WARNING(escaped_parameter_name,none, ERROR(forbidden_interpolated_string,none, "%0 cannot be an interpolated string literal", (StringRef)) -ERROR(forbidden_extended_escaping_string,none, - "%0 cannot be an extended escaping string literal", (StringRef)) ERROR(expected_identifier_in_module_selector,none, "expected module name in module selector", ()) diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 92b392131b44d..d8463aa2fae28 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1170,12 +1170,6 @@ std::optional Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText) { assert(Tok.is(tok::string_literal)); - // FIXME: Support extended escaping string literal. - if (Tok.getCustomDelimiterLen()) { - diagnose(Loc, diag::forbidden_extended_escaping_string, DiagText); - return std::nullopt; - } - SmallVector Segments; L->getStringLiteralSegments(Tok, Segments); if (Segments.size() != 1 || @@ -1184,8 +1178,13 @@ Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText) { return std::nullopt; } - return SourceMgr.extractText(CharSourceRange(Segments.front().Loc, - Segments.front().Length)); + llvm::SmallString<256> Buf; + StringRef EncodedStr = L->getEncodedStringSegment(Segments.front(), Buf); + if (!Buf.empty()) { + EncodedStr = Context.AllocateCopy(EncodedStr); + } + + return EncodedStr; } struct ParserUnit::Implementation { diff --git a/test/Parse/diagnose_availability.swift b/test/Parse/diagnose_availability.swift index 9d43280792ee5..720dd081a1863 100644 --- a/test/Parse/diagnose_availability.swift +++ b/test/Parse/diagnose_availability.swift @@ -88,12 +88,12 @@ emptyMessage() // expected-error@-1{{'emptyMessage()' is unavailable: }} // expected-note@-3{{'emptyMessage()' has been explicitly marked unavailable here}} -// expected-error@+1{{'message' cannot be an extended escaping string literal}} +// OK. @available(*, unavailable, message: #""" foobar message. """#) func extendedEscapedMultilineMessage() {} -// expected-error@+1{{'renamed' cannot be an extended escaping string literal}} +// OK. @available(*, unavailable, renamed: #"available()"#) func extendedEscapedRenamed() {} diff --git a/test/Parse/line-directive-executable.swift b/test/Parse/line-directive-executable.swift index cc4e26824d21b..5a668fb41f857 100644 --- a/test/Parse/line-directive-executable.swift +++ b/test/Parse/line-directive-executable.swift @@ -62,3 +62,16 @@ check() // CHECK-NEXT: .swift:[[@LINE]] check() // CHECK-NEXT: {{^}}k.swift:1002 + +#sourceLocation(file: #"C:\l.swift"#, line: 1100) +check() // CHECK-NEXT: {{^}}C:\l.swift:1100 + +#sourceLocation(file: """ + m.swift + n.swift + """, + line: 1200 +) +check() +// CHECK-NEXT: {{^}}m.swift +// CHECK-NEXT: {{^}}n.swift:1200