Skip to content

Commit 413352b

Browse files
Merge pull request #34620 from AnthonyLatsis/parse-misc
Parse: Only diagnose dollar-prefixed identifiers that are Swift declarations
2 parents 41f74e4 + 47ce152 commit 413352b

File tree

10 files changed

+120
-86
lines changed

10 files changed

+120
-86
lines changed

include/swift/Parse/Parser.h

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,13 @@ class Parser {
553553
return Tok.getLoc().getAdvancedLoc(-LeadingTrivia.getLength());
554554
}
555555

556-
SourceLoc consumeIdentifier(Identifier *Result = nullptr,
557-
bool allowDollarIdentifier = false) {
556+
SourceLoc consumeIdentifier(Identifier &Result, bool diagnoseDollarPrefix) {
558557
assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));
559-
if (Result)
560-
*Result = Context.getIdentifier(Tok.getText());
558+
assert(Result.empty());
559+
Result = Context.getIdentifier(Tok.getText());
561560

562561
if (Tok.getText()[0] == '$')
563-
diagnoseDollarIdentifier(Tok, allowDollarIdentifier);
562+
diagnoseDollarIdentifier(Tok, diagnoseDollarPrefix);
564563

565564
return consumeToken();
566565
}
@@ -573,15 +572,17 @@ class Parser {
573572
Result = Context.getIdentifier(Tok.getText());
574573

575574
if (Tok.getText()[0] == '$')
576-
diagnoseDollarIdentifier(Tok);
575+
diagnoseDollarIdentifier(Tok, /*diagnoseDollarPrefix=*/true);
577576
}
578577
return consumeToken();
579578
}
580579

581580
/// When we have a token that is an identifier starting with '$',
582581
/// diagnose it if not permitted in this mode.
582+
/// \param diagnoseDollarPrefix Whether to diagnose dollar-prefixed
583+
/// identifiers in addition to a standalone '$'.
583584
void diagnoseDollarIdentifier(const Token &tok,
584-
bool allowDollarIdentifier = false) {
585+
bool diagnoseDollarPrefix) {
585586
assert(tok.getText()[0] == '$');
586587

587588
// If '$' is not guarded by backticks, offer
@@ -592,7 +593,7 @@ class Parser {
592593
return;
593594
}
594595

595-
if (allowDollarIdentifier)
596+
if (!diagnoseDollarPrefix)
596597
return;
597598

598599
if (tok.getText().size() == 1 || Context.LangOpts.EnableDollarIdentifiers ||
@@ -790,24 +791,20 @@ class Parser {
790791
/// its name in \p Result. Otherwise, emit an error.
791792
///
792793
/// \returns false on success, true on error.
793-
bool parseIdentifier(Identifier &Result, SourceLoc &Loc, const Diagnostic &D);
794-
794+
bool parseIdentifier(Identifier &Result, SourceLoc &Loc, const Diagnostic &D,
795+
bool diagnoseDollarPrefix);
796+
795797
/// Consume an identifier with a specific expected name. This is useful for
796798
/// contextually sensitive keywords that must always be present.
797799
bool parseSpecificIdentifier(StringRef expected, SourceLoc &Loc,
798800
const Diagnostic &D);
799801

800-
template<typename ...DiagArgTypes, typename ...ArgTypes>
801-
bool parseIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID,
802-
ArgTypes... Args) {
803-
SourceLoc L;
804-
return parseIdentifier(Result, L, Diagnostic(ID, Args...));
805-
}
806-
807802
template<typename ...DiagArgTypes, typename ...ArgTypes>
808803
bool parseIdentifier(Identifier &Result, SourceLoc &L,
809-
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
810-
return parseIdentifier(Result, L, Diagnostic(ID, Args...));
804+
bool diagnoseDollarPrefix, Diag<DiagArgTypes...> ID,
805+
ArgTypes... Args) {
806+
return parseIdentifier(Result, L, Diagnostic(ID, Args...),
807+
diagnoseDollarPrefix);
811808
}
812809

813810
template<typename ...DiagArgTypes, typename ...ArgTypes>
@@ -820,19 +817,14 @@ class Parser {
820817
/// Consume an identifier or operator if present and return its name
821818
/// in \p Result. Otherwise, emit an error and return true.
822819
bool parseAnyIdentifier(Identifier &Result, SourceLoc &Loc,
823-
const Diagnostic &D);
820+
const Diagnostic &D, bool diagnoseDollarPrefix);
824821

825822
template<typename ...DiagArgTypes, typename ...ArgTypes>
826-
bool parseAnyIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID,
827-
ArgTypes... Args) {
828-
SourceLoc L;
829-
return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...));
830-
}
831-
832-
template<typename ...DiagArgTypes, typename ...ArgTypes>
833-
bool parseAnyIdentifier(Identifier &Result, SourceLoc &L,
823+
bool parseAnyIdentifier(Identifier &Result, bool diagnoseDollarPrefix,
834824
Diag<DiagArgTypes...> ID, ArgTypes... Args) {
835-
return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...));
825+
SourceLoc L;
826+
return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...),
827+
diagnoseDollarPrefix);
836828
}
837829

838830
/// \brief Parse an unsigned integer and returns it in \p Result. On failure

lib/Parse/ParseDecl.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -938,9 +938,7 @@ bool Parser::parseDifferentiabilityParametersClause(
938938
return true;
939939
}
940940
Identifier paramName;
941-
if (parseIdentifier(paramName, paramLoc,
942-
diag::diff_params_clause_expected_parameter))
943-
return true;
941+
paramLoc = consumeIdentifier(paramName, /*diagnoseDollarPrefix=*/false);
944942
parameters.push_back(
945943
ParsedAutoDiffParameter::getNamedParameter(paramLoc, paramName));
946944
break;
@@ -1974,8 +1972,8 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
19741972
}
19751973

19761974
Identifier name;
1977-
consumeIdentifier(&name);
1978-
1975+
consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
1976+
19791977
auto range = SourceRange(Loc, Tok.getRange().getStart());
19801978

19811979
if (!consumeIf(tok::r_paren)) {
@@ -2553,7 +2551,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
25532551
}
25542552

25552553
Identifier name;
2556-
consumeIdentifier(&name, /*allowDollarIdentifier=*/true);
2554+
consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
25572555

25582556
auto range = SourceRange(Loc, Tok.getRange().getStart());
25592557

@@ -4426,6 +4424,7 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
44264424
}
44274425
importPath.push_back(Identifier(), Tok.getLoc());
44284426
if (parseAnyIdentifier(importPath.back().Item,
4427+
/*diagnoseDollarPrefix=*/false,
44294428
diag::expected_identifier_in_decl, "import"))
44304429
return nullptr;
44314430
HasNext = consumeIf(tok::period);
@@ -4551,7 +4550,7 @@ parseIdentifierDeclName(Parser &P, Identifier &Result, SourceLoc &Loc,
45514550
StringRef DeclKindName,
45524551
llvm::function_ref<bool(const Token &)> canRecover) {
45534552
if (P.Tok.is(tok::identifier)) {
4554-
Loc = P.consumeIdentifier(&Result);
4553+
Loc = P.consumeIdentifier(Result, /*diagnoseDollarPrefix=*/true);
45554554

45564555
// We parsed an identifier for the declaration. If we see another
45574556
// identifier, it might've been a single identifier that got broken by a
@@ -5465,7 +5464,7 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
54655464
EndLoc = StartLoc;
54665465
} else {
54675466
// We have a name.
5468-
NameLoc = P.consumeIdentifier(&Name);
5467+
NameLoc = P.consumeIdentifier(Name, /*diagnoseDollarPrefix=*/true);
54695468

54705469
auto DiagID =
54715470
Kind == AccessorKind::Set ? diag::expected_rparen_set_name :
@@ -7745,15 +7744,15 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
77457744
SyntaxKind::IdentifierList);
77467745

77477746
Identifier name;
7748-
auto loc = consumeIdentifier(&name);
7747+
auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
77497748
identifiers.emplace_back(name, loc);
77507749

77517750
while (Tok.is(tok::comma)) {
77527751
auto comma = consumeToken();
77537752

77547753
if (Tok.is(tok::identifier)) {
77557754
Identifier name;
7756-
auto loc = consumeIdentifier(&name);
7755+
auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
77577756
identifiers.emplace_back(name, loc);
77587757
} else {
77597758
if (Tok.isNot(tok::eof)) {
@@ -7770,7 +7769,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
77707769
SyntaxKind::IdentifierList);
77717770

77727771
Identifier name;
7773-
auto nameLoc = consumeIdentifier(&name);
7772+
auto nameLoc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
77747773
identifiers.emplace_back(name, nameLoc);
77757774

77767775
if (isPrefix || isPostfix) {
@@ -7841,7 +7840,8 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
78417840

78427841
Identifier name;
78437842
SourceLoc nameLoc;
7844-
if (parseIdentifier(name, nameLoc, diag::expected_precedencegroup_name)) {
7843+
if (parseIdentifier(name, nameLoc, /*diagnoseDollarPrefix=*/true,
7844+
diag::expected_precedencegroup_name)) {
78457845
// If the identifier is missing or a keyword or something, try to
78467846
// skip the entire body.
78477847
if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof) &&
@@ -8047,7 +8047,8 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
80478047
return abortBody();
80488048
}
80498049
Identifier name;
8050-
SourceLoc nameLoc = consumeIdentifier(&name);
8050+
SourceLoc nameLoc = consumeIdentifier(name,
8051+
/*diagnoseDollarPrefix=*/false);
80518052
relations.push_back({nameLoc, name, nullptr});
80528053

80538054
if (skipUnspacedCodeCompleteToken())

lib/Parse/ParseExpr.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,7 +1500,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15001500
peekToken().isNot(tok::period, tok::period_prefix, tok::l_paren)) {
15011501
DeferringContextRAII Deferring(*SyntaxContext);
15021502
Identifier name;
1503-
SourceLoc loc = consumeIdentifier(&name, /*allowDollarIdentifier=*/true);
1503+
SourceLoc loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
15041504
auto introducer = (InVarOrLetPattern != IVOLP_InVar
15051505
? VarDecl::Introducer::Let
15061506
: VarDecl::Introducer::Var);
@@ -2114,8 +2114,7 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc,
21142114
SourceLoc baseNameLoc;
21152115
if (Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_self)) {
21162116
Identifier baseNameId;
2117-
baseNameLoc = consumeIdentifier(
2118-
&baseNameId, /*allowDollarIdentifier=*/true);
2117+
baseNameLoc = consumeIdentifier(baseNameId, /*diagnoseDollarPrefix=*/false);
21192118
baseName = baseNameId;
21202119
} else if (flags.contains(DeclNameFlag::AllowOperators) &&
21212120
Tok.isAnyOperator()) {
@@ -2490,7 +2489,7 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange,
24902489

24912490
} else {
24922491
// Otherwise, the name is a new declaration.
2493-
consumeIdentifier(&name);
2492+
consumeIdentifier(name, /*diagnoseDollarPrefix=*/true);
24942493
equalLoc = consumeToken(tok::equal);
24952494

24962495
auto ExprResult = parseExpr(diag::expected_init_capture_specifier);
@@ -2569,7 +2568,7 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange,
25692568
Identifier name;
25702569
SourceLoc nameLoc;
25712570
if (Tok.is(tok::identifier)) {
2572-
nameLoc = consumeIdentifier(&name);
2571+
nameLoc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/true);
25732572
} else {
25742573
nameLoc = consumeToken(tok::kw__);
25752574
}
@@ -3233,7 +3232,7 @@ ParserResult<Expr> Parser::parseExprPoundUnknown(SourceLoc LSquareLoc) {
32333232
PoundLoc.getAdvancedLoc(1) == Tok.getLoc());
32343233

32353234
Identifier Name;
3236-
SourceLoc NameLoc = consumeIdentifier(&Name);
3235+
SourceLoc NameLoc = consumeIdentifier(Name, /*diagnoseDollarPrefix=*/false);
32373236

32383237
// Parse arguments if exist.
32393238
SourceLoc LParenLoc, RParenLoc;
@@ -3670,6 +3669,7 @@ Parser::parsePlatformVersionConstraintSpec() {
36703669
}
36713670

36723671
if (parseIdentifier(PlatformIdentifier, PlatformLoc,
3672+
/*diagnoseDollarPrefix=*/false,
36733673
diag::avail_query_expected_platform_name)) {
36743674
return nullptr;
36753675
}

lib/Parse/ParseGeneric.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
7171
// Parse the name of the parameter.
7272
Identifier Name;
7373
SourceLoc NameLoc;
74-
if (parseIdentifier(Name, NameLoc,
74+
if (parseIdentifier(Name, NameLoc, /*diagnoseDollarPrefix=*/true,
7575
diag::expected_generics_parameter_name)) {
7676
Result.setIsParseError();
7777
break;
@@ -307,7 +307,8 @@ ParserStatus Parser::parseGenericWhereClause(
307307
->isKnownLayout()) {
308308
// Parse a layout constraint.
309309
Identifier LayoutName;
310-
auto LayoutLoc = consumeIdentifier(&LayoutName);
310+
auto LayoutLoc = consumeIdentifier(LayoutName,
311+
/*diagnoseDollarPrefix=*/false);
311312
auto LayoutInfo = parseLayoutConstraint(LayoutName);
312313
if (!LayoutInfo->isKnownLayout()) {
313314
// There was a bug in the layout constraint.

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ ParserResult<Pattern> Parser::parsePattern() {
975975
case tok::identifier: {
976976
PatternCtx.setCreateSyntax(SyntaxKind::IdentifierPattern);
977977
Identifier name;
978-
SourceLoc loc = consumeIdentifier(&name);
978+
SourceLoc loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/true);
979979
if (Tok.isIdentifierOrUnderscore() && !Tok.isContextualDeclKeyword())
980980
diagnoseConsecutiveIDs(name.str(), loc,
981981
introducer == VarDecl::Introducer::Let
@@ -1054,7 +1054,7 @@ Parser::parsePatternTupleElement() {
10541054

10551055
// If the tuple element has a label, parse it.
10561056
if (Tok.is(tok::identifier) && peekToken().is(tok::colon)) {
1057-
LabelLoc = consumeIdentifier(&Label);
1057+
LabelLoc = consumeIdentifier(Label, /*diagnoseDollarPrefix=*/true);
10581058
consumeToken(tok::colon);
10591059
}
10601060

lib/Parse/ParseStmt.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ static bool isAtStartOfSwitchCase(Parser &parser,
192192
backtrack.emplace(parser);
193193

194194
parser.consumeToken(tok::at_sign);
195-
parser.consumeIdentifier();
195+
parser.consumeToken(tok::identifier);
196196
if (parser.Tok.is(tok::l_paren))
197197
parser.skipSingle();
198198
}
@@ -536,7 +536,8 @@ ParserResult<Stmt> Parser::parseStmt() {
536536
// If this is a label on a loop/switch statement, consume it and pass it into
537537
// parsing logic below.
538538
if (Tok.is(tok::identifier) && peekToken().is(tok::colon)) {
539-
LabelInfo.Loc = consumeIdentifier(&LabelInfo.Name);
539+
LabelInfo.Loc = consumeIdentifier(LabelInfo.Name,
540+
/*diagnoseDollarPrefix=*/true);
540541
consumeToken(tok::colon);
541542
}
542543

@@ -687,7 +688,7 @@ static ParserStatus parseOptionalControlTransferTarget(Parser &P,
687688
if (!P.Tok.isAtStartOfLine()) {
688689
if (P.Tok.is(tok::identifier) && !P.isStartOfStmt() &&
689690
!P.isStartOfSwiftDecl()) {
690-
TargetLoc = P.consumeIdentifier(&Target);
691+
TargetLoc = P.consumeIdentifier(Target, /*diagnoseDollarPrefix=*/false);
691692
return makeParserSuccess();
692693
} else if (P.Tok.is(tok::code_complete)) {
693694
if (P.CodeCompletion)
@@ -2486,17 +2487,19 @@ ParserResult<CaseStmt> Parser::parseStmtCase(bool IsActive) {
24862487
diagnose(UnknownAttrLoc, diag::previous_attribute, false);
24872488
consumeToken(tok::at_sign);
24882489
}
2489-
consumeIdentifier();
2490+
consumeToken(tok::identifier);
24902491

24912492
SyntaxParsingContext Args(SyntaxContext, SyntaxKind::TokenList);
24922493
if (Tok.is(tok::l_paren)) {
24932494
diagnose(Tok, diag::unexpected_lparen_in_attribute, "unknown");
24942495
skipSingle();
24952496
}
24962497
} else {
2498+
assert(peekToken().is(tok::identifier) && "isAtStartOfSwitchCase() lied");
2499+
24972500
consumeToken(tok::at_sign);
24982501
diagnose(Tok, diag::unknown_attribute, Tok.getText());
2499-
consumeIdentifier();
2502+
consumeToken(tok::identifier);
25002503

25012504
SyntaxParsingContext Args(SyntaxContext, SyntaxKind::TokenList);
25022505
if (Tok.is(tok::l_paren))

lib/Parse/Parser.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -903,12 +903,12 @@ bool Parser::StructureMarkerRAII::pushStructureMarker(
903903
//===----------------------------------------------------------------------===//
904904

905905
bool Parser::parseIdentifier(Identifier &Result, SourceLoc &Loc,
906-
const Diagnostic &D) {
906+
const Diagnostic &D, bool diagnoseDollarPrefix) {
907907
switch (Tok.getKind()) {
908908
case tok::kw_self:
909909
case tok::kw_Self:
910910
case tok::identifier:
911-
Loc = consumeIdentifier(&Result);
911+
Loc = consumeIdentifier(Result, diagnoseDollarPrefix);
912912
return false;
913913
default:
914914
checkForInputIncomplete();
@@ -930,9 +930,10 @@ bool Parser::parseSpecificIdentifier(StringRef expected, SourceLoc &loc,
930930
/// parseAnyIdentifier - Consume an identifier or operator if present and return
931931
/// its name in Result. Otherwise, emit an error and return true.
932932
bool Parser::parseAnyIdentifier(Identifier &Result, SourceLoc &Loc,
933-
const Diagnostic &D) {
933+
const Diagnostic &D,
934+
bool diagnoseDollarPrefix) {
934935
if (Tok.is(tok::identifier)) {
935-
Loc = consumeIdentifier(&Result);
936+
Loc = consumeIdentifier(Result, diagnoseDollarPrefix);
936937
return false;
937938
}
938939

0 commit comments

Comments
 (0)