Skip to content

Commit 47ce152

Browse files
committed
Parse: Only diagnose dollar-prefixed identifiers that are Swift declarations
1 parent 6722d71 commit 47ce152

File tree

10 files changed

+120
-86
lines changed

10 files changed

+120
-86
lines changed

include/swift/Parse/Parser.h

+21-29
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

+14-13
Original file line numberDiff line numberDiff line change
@@ -930,9 +930,7 @@ bool Parser::parseDifferentiabilityParametersClause(
930930
return true;
931931
}
932932
Identifier paramName;
933-
if (parseIdentifier(paramName, paramLoc,
934-
diag::diff_params_clause_expected_parameter))
935-
return true;
933+
paramLoc = consumeIdentifier(paramName, /*diagnoseDollarPrefix=*/false);
936934
parameters.push_back(
937935
ParsedAutoDiffParameter::getNamedParameter(paramLoc, paramName));
938936
break;
@@ -1966,8 +1964,8 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
19661964
}
19671965

19681966
Identifier name;
1969-
consumeIdentifier(&name);
1970-
1967+
consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
1968+
19711969
auto range = SourceRange(Loc, Tok.getRange().getStart());
19721970

19731971
if (!consumeIf(tok::r_paren)) {
@@ -2545,7 +2543,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
25452543
}
25462544

25472545
Identifier name;
2548-
consumeIdentifier(&name, /*allowDollarIdentifier=*/true);
2546+
consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
25492547

25502548
auto range = SourceRange(Loc, Tok.getRange().getStart());
25512549

@@ -4418,6 +4416,7 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
44184416
}
44194417
importPath.push_back(Identifier(), Tok.getLoc());
44204418
if (parseAnyIdentifier(importPath.back().Item,
4419+
/*diagnoseDollarPrefix=*/false,
44214420
diag::expected_identifier_in_decl, "import"))
44224421
return nullptr;
44234422
HasNext = consumeIf(tok::period);
@@ -4543,7 +4542,7 @@ parseIdentifierDeclName(Parser &P, Identifier &Result, SourceLoc &Loc,
45434542
StringRef DeclKindName,
45444543
llvm::function_ref<bool(const Token &)> canRecover) {
45454544
if (P.Tok.is(tok::identifier)) {
4546-
Loc = P.consumeIdentifier(&Result);
4545+
Loc = P.consumeIdentifier(Result, /*diagnoseDollarPrefix=*/true);
45474546

45484547
// We parsed an identifier for the declaration. If we see another
45494548
// identifier, it might've been a single identifier that got broken by a
@@ -5457,7 +5456,7 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
54575456
EndLoc = StartLoc;
54585457
} else {
54595458
// We have a name.
5460-
NameLoc = P.consumeIdentifier(&Name);
5459+
NameLoc = P.consumeIdentifier(Name, /*diagnoseDollarPrefix=*/true);
54615460

54625461
auto DiagID =
54635462
Kind == AccessorKind::Set ? diag::expected_rparen_set_name :
@@ -7737,15 +7736,15 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
77377736
SyntaxKind::IdentifierList);
77387737

77397738
Identifier name;
7740-
auto loc = consumeIdentifier(&name);
7739+
auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
77417740
identifiers.emplace_back(name, loc);
77427741

77437742
while (Tok.is(tok::comma)) {
77447743
auto comma = consumeToken();
77457744

77467745
if (Tok.is(tok::identifier)) {
77477746
Identifier name;
7748-
auto loc = consumeIdentifier(&name);
7747+
auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
77497748
identifiers.emplace_back(name, loc);
77507749
} else {
77517750
if (Tok.isNot(tok::eof)) {
@@ -7762,7 +7761,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
77627761
SyntaxKind::IdentifierList);
77637762

77647763
Identifier name;
7765-
auto nameLoc = consumeIdentifier(&name);
7764+
auto nameLoc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
77667765
identifiers.emplace_back(name, nameLoc);
77677766

77687767
if (isPrefix || isPostfix) {
@@ -7833,7 +7832,8 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
78337832

78347833
Identifier name;
78357834
SourceLoc nameLoc;
7836-
if (parseIdentifier(name, nameLoc, diag::expected_precedencegroup_name)) {
7835+
if (parseIdentifier(name, nameLoc, /*diagnoseDollarPrefix=*/true,
7836+
diag::expected_precedencegroup_name)) {
78377837
// If the identifier is missing or a keyword or something, try to
78387838
// skip the entire body.
78397839
if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof) &&
@@ -8039,7 +8039,8 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
80398039
return abortBody();
80408040
}
80418041
Identifier name;
8042-
SourceLoc nameLoc = consumeIdentifier(&name);
8042+
SourceLoc nameLoc = consumeIdentifier(name,
8043+
/*diagnoseDollarPrefix=*/false);
80438044
relations.push_back({nameLoc, name, nullptr});
80448045

80458046
if (skipUnspacedCodeCompleteToken())

lib/Parse/ParseExpr.cpp

+6-6
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

+3-2
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

+2-2
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

+8-5
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

+5-4
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)