Skip to content

Commit 12fe866

Browse files
authored
Merge pull request #71238 from ahoppen/ahoppen/source-location-parser-changes
Disallow multi-line filenames and non-decimal line numbers in `#sourceLocation` directive in Swift 6 mode
2 parents 956d6d2 + 4a386d4 commit 12fe866

File tree

6 files changed

+52
-20
lines changed

6 files changed

+52
-20
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ WARNING(escaped_parameter_name,none,
8888

8989
ERROR(forbidden_interpolated_string,none,
9090
"%0 cannot be an interpolated string literal", (StringRef))
91+
ERROR(forbidden_multiline_string,none,
92+
"%0 cannot be a multi-line string literal", (StringRef))
9193
ERROR(forbidden_extended_escaping_string,none,
9294
"%0 cannot be an extended escaping string literal", (StringRef))
9395

include/swift/Parse/Parser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,8 +706,11 @@ class Parser {
706706
///
707707
/// \param Loc where to diagnose.
708708
/// \param DiagText name for the string literal in the diagnostic.
709+
/// \param AllowMultiline Whether the string literal can be a multiline string
710+
/// literal.
709711
llvm::Optional<StringRef>
710-
getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText);
712+
getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText,
713+
bool AllowMultiline);
711714

712715
/// Returns true to indicate that experimental concurrency syntax should be
713716
/// parsed if the parser is generating only a syntax tree or if the user has

lib/Parse/ParseDecl.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,8 @@ ParserResult<AvailableAttr> Parser::parseExtendedAvailabilitySpecList(
568568
}
569569

570570
auto Value = getStringLiteralIfNotInterpolated(
571-
AttrLoc, ("'" + ArgumentKindStr + "'").str());
571+
AttrLoc, ("'" + ArgumentKindStr + "'").str(),
572+
/*AllowMultiline=*/true);
572573
consumeToken();
573574
if (!Value) {
574575
AnyArgumentInvalid = true;
@@ -1453,7 +1454,8 @@ bool Parser::parseExternAttribute(DeclAttributes &Attributes,
14531454
return std::nullopt;
14541455
}
14551456
llvm::Optional<StringRef> importModuleName =
1456-
getStringLiteralIfNotInterpolated(Loc, ("'" + AttrName + "'").str());
1457+
getStringLiteralIfNotInterpolated(Loc, ("'" + AttrName + "'").str(),
1458+
/*AllowMultiline=*/false);
14571459
consumeToken(tok::string_literal);
14581460

14591461
if (!importModuleName.has_value()) {
@@ -3233,8 +3235,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
32333235
return makeParserSuccess();
32343236
}
32353237

3236-
AsmName =
3237-
getStringLiteralIfNotInterpolated(Loc, ("'" + AttrName + "'").str());
3238+
AsmName = getStringLiteralIfNotInterpolated(
3239+
Loc, ("'" + AttrName + "'").str(), /*AllowMultiline=*/false);
32383240

32393241
consumeToken(tok::string_literal);
32403242

@@ -3305,7 +3307,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
33053307
}
33063308

33073309
auto Name = getStringLiteralIfNotInterpolated(
3308-
Loc, ("'" + AttrName + "'").str());
3310+
Loc, ("'" + AttrName + "'").str(), /*AllowMultiline=*/false);
33093311

33103312
consumeToken(tok::string_literal);
33113313

@@ -3392,7 +3394,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
33923394
}
33933395

33943396
auto Value = getStringLiteralIfNotInterpolated(
3395-
Loc, ("'" + AttrName + "'").str());
3397+
Loc, ("'" + AttrName + "'").str(), /*AllowMultiline=*/false);
33963398

33973399
consumeToken(tok::string_literal);
33983400

@@ -3455,8 +3457,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
34553457
// Parse the next string literal as the original module name.
34563458
auto ModuleNameLoc = Tok.getLoc();
34573459
if (Tok.is(tok::string_literal)) {
3458-
auto NameOp = getStringLiteralIfNotInterpolated(Tok.getLoc(),
3459-
"original module name");
3460+
auto NameOp = getStringLiteralIfNotInterpolated(
3461+
Tok.getLoc(), "original module name", /*AllowMultiline=*/false);
34603462
if (NameOp.has_value())
34613463
OriginalModuleName = *NameOp;
34623464
consumeToken();
@@ -3545,7 +3547,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
35453547
diagnose(ColonLoc, diag::attr_private_import_expected_sourcefile_name);
35463548
return makeParserSuccess();
35473549
}
3548-
filename = getStringLiteralIfNotInterpolated(Loc, "_private");
3550+
filename = getStringLiteralIfNotInterpolated(Loc, "_private",
3551+
/*AllowMultiline=*/false);
35493552
if (!filename.has_value()) {
35503553
diagnose(ColonLoc, diag::attr_private_import_expected_sourcefile_name);
35513554
return makeParserSuccess();
@@ -3818,8 +3821,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
38183821
return makeParserSuccess();
38193822
}
38203823

3821-
llvm::Optional<StringRef> value =
3822-
getStringLiteralIfNotInterpolated(Tok.getLoc(), flag);
3824+
llvm::Optional<StringRef> value = getStringLiteralIfNotInterpolated(
3825+
Tok.getLoc(), flag, /*AllowMultiline=*/false);
38233826
if (!value)
38243827
return makeParserSuccess();
38253828
Token stringTok = Tok;
@@ -4533,7 +4536,8 @@ bool Parser::parseConventionAttributeInternal(SourceLoc atLoc, SourceLoc attrLoc
45334536
diagnose(Tok, diag::convention_attribute_ctype_expected_string);
45344537
return true;
45354538
}
4536-
if (auto ty = getStringLiteralIfNotInterpolated(Tok.getLoc(), "(C type)")) {
4539+
if (auto ty = getStringLiteralIfNotInterpolated(Tok.getLoc(), "(C type)",
4540+
/*AllowMultiline=*/false)) {
45374541
cType = Located<StringRef>(ty.value(), Tok.getLoc());
45384542
}
45394543
consumeToken(tok::string_literal);
@@ -7167,8 +7171,8 @@ ParserStatus Parser::parseLineDirective(bool isLine) {
71677171
return makeParserError();
71687172
}
71697173

7170-
Filename =
7171-
getStringLiteralIfNotInterpolated(Loc, "'#sourceLocation'");
7174+
Filename = getStringLiteralIfNotInterpolated(Loc, "'#sourceLocation'",
7175+
/*AllowMultiline=*/false);
71727176
if (!Filename.has_value())
71737177
return makeParserError();
71747178
SourceLoc filenameLoc = consumeToken(tok::string_literal);
@@ -7186,6 +7190,11 @@ ParserStatus Parser::parseLineDirective(bool isLine) {
71867190
}
71877191
SmallString<16> buffer;
71887192
auto text = stripUnderscoresIfNeeded(Tok.getText(), buffer);
7193+
if (text.find_first_not_of("0123456789") != StringRef::npos) {
7194+
// Disallow non-decimal line numbers in Swift 6.
7195+
diagnose(Tok, diag::expected_line_directive_number)
7196+
.warnUntilSwiftVersion(6);
7197+
}
71897198
if (text.getAsInteger(0, StartLine)) {
71907199
diagnose(Tok, diag::expected_line_directive_number);
71917200
return makeParserError();
@@ -7233,8 +7242,9 @@ ParserStatus Parser::parseLineDirective(bool isLine) {
72337242
diagnose(Tok, diag::expected_line_directive_name);
72347243
return makeParserError();
72357244
}
7236-
7237-
Filename = getStringLiteralIfNotInterpolated(Loc, "'#line'");
7245+
7246+
Filename = getStringLiteralIfNotInterpolated(Loc, "'#line'",
7247+
/*AllowMultiline=*/false);
72387248
if (!Filename.has_value())
72397249
return makeParserError();
72407250
}

lib/Parse/ParseStmt.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,8 +2773,9 @@ ParserResult<Stmt> Parser::parseStmtPoundAssert() {
27732773
return makeParserError();
27742774
}
27752775

2776-
auto messageOpt = getStringLiteralIfNotInterpolated(Tok.getLoc(),
2777-
"'#assert' message");
2776+
auto messageOpt =
2777+
getStringLiteralIfNotInterpolated(Tok.getLoc(), "'#assert' message",
2778+
/*AllowMultiline=*/true);
27782779
consumeToken();
27792780
if (!messageOpt)
27802781
return makeParserError();

lib/Parse/Parser.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,14 +1080,19 @@ Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
10801080
}
10811081

10821082
llvm::Optional<StringRef>
1083-
Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText) {
1083+
Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText,
1084+
bool AllowMultiline) {
10841085
assert(Tok.is(tok::string_literal));
10851086

10861087
// FIXME: Support extended escaping string literal.
10871088
if (Tok.getCustomDelimiterLen()) {
10881089
diagnose(Loc, diag::forbidden_extended_escaping_string, DiagText);
10891090
return llvm::None;
10901091
}
1092+
if (!AllowMultiline && Tok.isMultilineString()) {
1093+
diagnose(Loc, diag::forbidden_multiline_string, DiagText)
1094+
.warnUntilSwiftVersion(6);
1095+
}
10911096

10921097
SmallVector<Lexer::StringSegment, 1> Segments;
10931098
L->getStringLiteralSegments(Tok, Segments);

test/Parse/line-directive.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ x // expected-error {{parameterless closing #sourceLocation() directive without
1414

1515
#sourceLocation(file: x.swift, line: 1) // expected-error{{expected filename string literal}}
1616

17+
// expected-warning@+1 {{expected starting line number for #sourceLocation directive; this is an error in Swift 6}}
18+
#sourceLocation(file: "x.swift", line: 0xff)
19+
20+
#sourceLocation()
21+
22+
// expected-warning@+1 {{'#sourceLocation' cannot be a multi-line string literal; this is an error in Swift 6}}
23+
#sourceLocation(file: """
24+
x.swift
25+
y.swift
26+
""", line: 42)
27+
1728
#sourceLocation(file: "x.swift", line: 42)
1829
x x ; // should be ignored by expected_error because it is in a different file
1930
x

0 commit comments

Comments
 (0)