diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 1caa40abc68b4..9ef984d848057 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -1843,9 +1843,29 @@ void Lexer::lexStringLiteral(unsigned CustomDelimiterLen) { assert((QuoteChar == '"' || QuoteChar == '\'') && "Unexpected start"); bool IsMultilineString = advanceIfMultilineDelimiter(CurPtr, Diags); - if (IsMultilineString && *CurPtr != '\n' && *CurPtr != '\r') - diagnose(CurPtr, diag::lex_illegal_multiline_string_start) - .fixItInsert(Lexer::getSourceLoc(CurPtr), "\n"); + if (IsMultilineString && *CurPtr != '\n' && *CurPtr != '\r') { + // Test for single-line string literals that may resemble multiline delimiter. + if (CustomDelimiterLen > 0) { + for (const char *Ptr = CurPtr-1; Ptr <= BufferEnd-CustomDelimiterLen; Ptr++) { + if (*Ptr == '\r' || *Ptr == '\n') { + break; + } + if (*Ptr == '"') { + const char *TmpPtr = Ptr + 1; + if (delimiterMatches(CustomDelimiterLen, TmpPtr, nullptr)) { + // Undo effects from falsely detecting multiline delimiter. + CurPtr = CurPtr - 2; + IsMultilineString = false; + break; + } + } + } + } + if (IsMultilineString) { + diagnose(CurPtr, diag::lex_illegal_multiline_string_start) + .fixItInsert(Lexer::getSourceLoc(CurPtr), "\n"); + } + } bool wasErroneous = false; while (true) { diff --git a/test/Parse/raw_string.swift b/test/Parse/raw_string.swift index d07bbd24fa54f..b84ebef7f94f7 100644 --- a/test/Parse/raw_string.swift +++ b/test/Parse/raw_string.swift @@ -68,6 +68,18 @@ _ = ##""" """## // CHECK: "a raw string with \"\"\" in it" +_ = #"""# +// CHECK: "\"" + +_ = ##""" foo # "# "## +// CHECK: "\"\" foo # \"# " + +_ = #"""""# +// CHECK: "\"\"\"" + +_ = ###"""##"### +// CHECK: "\"\"##" + let foo = "Interpolation" _ = #"\b\b \#(foo)\#(foo) Kappa"# // CHECK: "\\b\\b " diff --git a/test/Parse/raw_string_errors.swift b/test/Parse/raw_string_errors.swift index 0ba693fc79f30..145e082bfa109 100644 --- a/test/Parse/raw_string_errors.swift +++ b/test/Parse/raw_string_errors.swift @@ -12,13 +12,23 @@ let _ = #"\##("invalid")"# let _ = ####"invalid"### // expected-error@-1{{unterminated string literal}} +let _ = ###"""invalid"###### +// expected-error@-1{{too many '#' characters in closing delimiter}}{{26-29=}} +// expected-error@-2{{consecutive statements on a line must be separated by ';'}} +// expected-error@-3{{expected expression}} + let _ = ###"invalid"###### // expected-error@-1{{too many '#' characters in closing delimiter}}{{24-27=}} // expected-error@-2{{consecutive statements on a line must be separated by ';'}} // expected-error@-3{{expected expression}} -let _ = ##"""## +let _ = ##"""a foobar - ##"""## -// expected-error@-3{{multi-line string literal content must begin on a new line}}{{14-14=\n}} + a"""## +// expected-error@-1{{multi-line string literal content must begin on a new line}}{{14-14=\n}} // expected-error@-2{{multi-line string literal closing delimiter must begin on a new line}}{{5-5=\n}} + +let _ = #""" foo "bar" #baz +"""# +// expected-error@-1{{multi-line string literal content must begin on a new line}}{{14-14=\n}} +