@@ -1240,7 +1240,8 @@ unsigned Lexer::lexCharacter(const char *&CurPtr, char StopQuote,
1240
1240
// / outstanding delimiters as it scans the string.
1241
1241
static const char *skipToEndOfInterpolatedExpression (const char *CurPtr,
1242
1242
const char *EndPtr,
1243
- DiagnosticEngine *Diags) {
1243
+ DiagnosticEngine *Diags,
1244
+ bool MultilineString) {
1244
1245
llvm::SmallVector<char , 4 > OpenDelimiters;
1245
1246
auto inStringLiteral = [&]() {
1246
1247
return !OpenDelimiters.empty () &&
@@ -1257,9 +1258,11 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr,
1257
1258
// issues with malformed tokens or other problems.
1258
1259
switch (*CurPtr++) {
1259
1260
// String literals in general cannot be split across multiple lines;
1260
- // interpolated ones are no exception.
1261
+ // interpolated ones are no exception - unless multiline literals .
1261
1262
case ' \n ' :
1262
1263
case ' \r ' :
1264
+ if (MultilineString)
1265
+ continue ;
1263
1266
// Will be diagnosed as an unterminated string literal.
1264
1267
return CurPtr-1 ;
1265
1268
@@ -1272,12 +1275,12 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr,
1272
1275
}
1273
1276
// Otherwise it's an ordinary character; treat it normally.
1274
1277
} else {
1275
- if (*CurPtr == ' "' && *(CurPtr + 1 ) == ' "' ) {
1276
- Diags->diagnose (Lexer::getSourceLoc (CurPtr-1 ),
1277
- diag::lex_multiline_inside_interpolation);
1278
- }
1279
1278
OpenDelimiters.push_back (CurPtr[-1 ]);
1280
1279
}
1280
+ if (*CurPtr == ' "' && *(CurPtr + 1 ) == ' "' && *(CurPtr - 1 ) == ' "' ) {
1281
+ MultilineString = true ;
1282
+ CurPtr += 2 ;
1283
+ }
1281
1284
continue ;
1282
1285
case ' \\ ' :
1283
1286
if (inStringLiteral ()) {
@@ -1373,7 +1376,8 @@ static StringRef getMultilineTrailingIndent(const Token &Str,
1373
1376
1374
1377
// / validateMultilineIndents:
1375
1378
// / Diagnose contents of string literal that have inconsistent indentation.
1376
- void Lexer::validateMultilineIndents (const Token &Str) {
1379
+ static void validateMultilineIndents (const Token &Str,
1380
+ DiagnosticEngine *Diags) {
1377
1381
StringRef Indent = getMultilineTrailingIndent (Str, Diags);
1378
1382
if (Indent.empty ())
1379
1383
return ;
@@ -1385,7 +1389,8 @@ void Lexer::validateMultilineIndents(const Token &Str) {
1385
1389
size_t nextpos = pos + 1 ;
1386
1390
if (BytesPtr[nextpos] != ' \n ' && BytesPtr[nextpos] != ' \r ' ) {
1387
1391
if (Bytes.substr (nextpos, Indent.size ()) != Indent)
1388
- diagnose (BytesPtr + nextpos, diag::lex_ambiguous_string_indent);
1392
+ Diags->diagnose (Lexer::getSourceLoc (BytesPtr + nextpos),
1393
+ diag::lex_ambiguous_string_indent);
1389
1394
}
1390
1395
pos = nextpos;
1391
1396
}
@@ -1415,7 +1420,8 @@ void Lexer::lexStringLiteral() {
1415
1420
// Consume tokens until we hit the corresponding ')'.
1416
1421
CurPtr += 2 ;
1417
1422
const char *EndPtr =
1418
- skipToEndOfInterpolatedExpression (CurPtr, BufferEnd, Diags);
1423
+ skipToEndOfInterpolatedExpression (CurPtr, BufferEnd,
1424
+ Diags, MultilineString);
1419
1425
1420
1426
if (*EndPtr == ' )' ) {
1421
1427
// Successfully scanned the body of the expression literal.
@@ -1483,7 +1489,8 @@ void Lexer::lexStringLiteral() {
1483
1489
if (*CurPtr == ' "' && *(CurPtr + 1 ) == ' "' && *(CurPtr + 2 ) != ' "' ) {
1484
1490
CurPtr += 2 ;
1485
1491
formToken (tok::string_literal, TokStart, MultilineString);
1486
- validateMultilineIndents (NextToken);
1492
+ if (Diags)
1493
+ validateMultilineIndents (NextToken, Diags);
1487
1494
return ;
1488
1495
}
1489
1496
else
@@ -1778,7 +1785,7 @@ void Lexer::getStringLiteralSegments(
1778
1785
// Find the closing ')'.
1779
1786
const char *End = skipToEndOfInterpolatedExpression (BytesPtr,
1780
1787
Str.getText ().end (),
1781
- Diags);
1788
+ Diags, MultilineString );
1782
1789
assert (*End == ' )' && " invalid string literal interpolations should"
1783
1790
" not be returned as string literals" );
1784
1791
++End;
0 commit comments