@@ -1379,14 +1379,27 @@ static bool delimiterMatches(unsigned CustomDelimiterLen, const char *&BytesPtr,
13791379
13801380// / advanceIfMultilineDelimiter - Centralized check for multiline delimiter.
13811381static bool advanceIfMultilineDelimiter (unsigned CustomDelimiterLen,
1382- const char *&CurPtr,
1382+ const char *&CurPtr, const char *EndPtr,
13831383 DiagnosticEngine *Diags,
13841384 bool IsOpening = false ) {
1385+ auto scanDelimiter = [&]() -> const char * {
1386+ // CurPtr here points to the character after `"`.
1387+ const char *TmpPtr = CurPtr;
1388+ if (*(TmpPtr - 1 ) == ' "' &&
1389+ diagnoseZeroWidthMatchAndAdvance (' "' , TmpPtr, Diags) &&
1390+ diagnoseZeroWidthMatchAndAdvance (' "' , TmpPtr, Diags)) {
1391+ return TmpPtr;
1392+ }
1393+ return nullptr ;
1394+ };
1395+ auto *DelimEnd = scanDelimiter ();
1396+ if (!DelimEnd)
1397+ return false ;
13851398
13861399 // Test for single-line string literals that resemble multiline delimiter.
1387- const char *TmpPtr = CurPtr + 1 ;
1400+ const char *TmpPtr = DelimEnd - 1 ;
13881401 if (IsOpening && CustomDelimiterLen) {
1389- while (*TmpPtr != ' \r ' && *TmpPtr != ' \n ' ) {
1402+ while (TmpPtr != EndPtr && *TmpPtr != ' \r ' && *TmpPtr != ' \n ' ) {
13901403 if (*TmpPtr == ' "' ) {
13911404 if (delimiterMatches (CustomDelimiterLen, ++TmpPtr, nullptr )) {
13921405 return false ;
@@ -1397,15 +1410,8 @@ static bool advanceIfMultilineDelimiter(unsigned CustomDelimiterLen,
13971410 }
13981411 }
13991412
1400- TmpPtr = CurPtr;
1401- if (*(TmpPtr - 1 ) == ' "' &&
1402- diagnoseZeroWidthMatchAndAdvance (' "' , TmpPtr, Diags) &&
1403- diagnoseZeroWidthMatchAndAdvance (' "' , TmpPtr, Diags)) {
1404- CurPtr = TmpPtr;
1405- return true ;
1406- }
1407-
1408- return false ;
1413+ CurPtr = DelimEnd;
1414+ return true ;
14091415}
14101416
14111417// / lexCharacter - Read a character and return its UTF32 code. If this is the
@@ -1450,8 +1456,8 @@ unsigned Lexer::lexCharacter(const char *&CurPtr, char StopQuote,
14501456
14511457 DiagnosticEngine *D = EmitDiagnostics ? getTokenDiags () : nullptr ;
14521458 auto TmpPtr = CurPtr;
1453- if (IsMultilineString &&
1454- ! advanceIfMultilineDelimiter ( CustomDelimiterLen, TmpPtr, D))
1459+ if (IsMultilineString && ! advanceIfMultilineDelimiter (
1460+ CustomDelimiterLen, TmpPtr, BufferEnd , D))
14551461 return ' "' ;
14561462 if (CustomDelimiterLen &&
14571463 !delimiterMatches (CustomDelimiterLen, TmpPtr, D, /* IsClosing=*/ true ))
@@ -1587,9 +1593,8 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr,
15871593 if (!inStringLiteral ()) {
15881594 // Open string literal.
15891595 OpenDelimiters.push_back (CurPtr[-1 ]);
1590- AllowNewline.push_back (advanceIfMultilineDelimiter (CustomDelimiterLen,
1591- CurPtr, nullptr ,
1592- true ));
1596+ AllowNewline.push_back (advanceIfMultilineDelimiter (
1597+ CustomDelimiterLen, CurPtr, EndPtr, nullptr , true ));
15931598 CustomDelimiter.push_back (CustomDelimiterLen);
15941599 continue ;
15951600 }
@@ -1602,7 +1607,8 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr,
16021607
16031608 // Multi-line string can only be closed by '"""'.
16041609 if (AllowNewline.back () &&
1605- !advanceIfMultilineDelimiter (CustomDelimiterLen, CurPtr, nullptr ))
1610+ !advanceIfMultilineDelimiter (CustomDelimiterLen, CurPtr, EndPtr,
1611+ nullptr ))
16061612 continue ;
16071613
16081614 // Check whether we have equivalent number of '#'s.
@@ -1947,7 +1953,7 @@ void Lexer::lexStringLiteral(unsigned CustomDelimiterLen) {
19471953 assert ((QuoteChar == ' "' || QuoteChar == ' \' ' ) && " Unexpected start" );
19481954
19491955 bool IsMultilineString = advanceIfMultilineDelimiter (
1950- CustomDelimiterLen, CurPtr, getTokenDiags (), true );
1956+ CustomDelimiterLen, CurPtr, BufferEnd, getTokenDiags (), true );
19511957 if (IsMultilineString && *CurPtr != ' \n ' && *CurPtr != ' \r ' )
19521958 diagnose (CurPtr, diag::lex_illegal_multiline_string_start)
19531959 .fixItInsert (Lexer::getSourceLoc (CurPtr), " \n " );
0 commit comments