Skip to content

Commit ca030da

Browse files
committed
[QoI] improve diagnostics for operator declarations; unify parsing code
1 parent da4d996 commit ca030da

File tree

5 files changed

+79
-89
lines changed

5 files changed

+79
-89
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ ERROR(operator_decl_no_fixity,none,
388388
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
389389

390390
// PrecedenceGroup
391+
ERROR(precedencegroup_not_infix,none,
392+
"only infix operators may declare a precedence", ())
391393
ERROR(expected_precedencegroup_name,none,
392394
"expected identifier after 'precedencegroup'", ())
393395
ERROR(expected_precedencegroup_lbrace,none,

include/swift/Parse/Parser.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -825,18 +825,10 @@ class Parser {
825825

826826
ParserResult<OperatorDecl> parseDeclOperator(ParseDeclOptions Flags,
827827
DeclAttributes &Attributes);
828-
ParserResult<OperatorDecl> parseDeclPrefixOperator(SourceLoc OperatorLoc,
829-
Identifier Name,
830-
SourceLoc NameLoc,
831-
DeclAttributes &Attrs);
832-
ParserResult<OperatorDecl> parseDeclPostfixOperator(SourceLoc OperatorLoc,
833-
Identifier Name,
834-
SourceLoc NameLoc,
835-
DeclAttributes &Attrs);
836-
ParserResult<OperatorDecl> parseDeclInfixOperator(SourceLoc OperatorLoc,
837-
Identifier Name,
838-
SourceLoc NameLoc,
839-
DeclAttributes &Attrs);
828+
ParserResult<OperatorDecl> parseDeclOperatorImpl(SourceLoc OperatorLoc,
829+
Identifier Name,
830+
SourceLoc NameLoc,
831+
DeclAttributes &Attrs);
840832

841833
ParserResult<PrecedenceGroupDecl>
842834
parseDeclPrecedenceGroup(ParseDeclOptions flags, DeclAttributes &attributes);

lib/Parse/ParseDecl.cpp

Lines changed: 45 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -5574,17 +5574,8 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
55745574

55755575
Identifier Name = Context.getIdentifier(Tok.getText());
55765576
SourceLoc NameLoc = consumeToken();
5577-
5578-
ParserResult<OperatorDecl> Result;
5579-
if (Attributes.hasAttribute<PrefixAttr>())
5580-
Result = parseDeclPrefixOperator(OperatorLoc, Name, NameLoc, Attributes);
5581-
else if (Attributes.hasAttribute<PostfixAttr>())
5582-
Result = parseDeclPostfixOperator(OperatorLoc, Name, NameLoc, Attributes);
5583-
else {
5584-
if (!Attributes.hasAttribute<InfixAttr>())
5585-
diagnose(OperatorLoc, diag::operator_decl_no_fixity);
5586-
Result = parseDeclInfixOperator(OperatorLoc, Name, NameLoc, Attributes);
5587-
}
5577+
5578+
auto Result = parseDeclOperatorImpl(OperatorLoc, Name, NameLoc, Attributes);
55885579

55895580
if (!DCC.movedToTopLevel() && !AllowTopLevel) {
55905581
diagnose(OperatorLoc, diag::operator_decl_inner_scope);
@@ -5595,89 +5586,68 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
55955586
}
55965587

55975588
ParserResult<OperatorDecl>
5598-
Parser::parseDeclPrefixOperator(SourceLoc OperatorLoc, Identifier Name,
5589+
Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
55995590
SourceLoc NameLoc, DeclAttributes &Attributes) {
5600-
SourceLoc lBraceLoc;
5601-
if (consumeIf(tok::l_brace, lBraceLoc)) {
5602-
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
5603-
if (Tok.is(tok::r_brace)) {
5604-
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5605-
NameLoc);
5606-
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5607-
Diag.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5608-
}
5609-
5610-
skipUntilDeclRBrace();
5611-
(void) consumeIf(tok::r_brace);
5612-
}
5591+
bool isPrefix = Attributes.hasAttribute<PrefixAttr>();
5592+
bool isInfix = Attributes.hasAttribute<InfixAttr>();
5593+
bool isPostfix = Attributes.hasAttribute<PostfixAttr>();
56135594

5614-
auto *Res = new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc,
5615-
Name, NameLoc);
5616-
Res->getAttrs() = Attributes;
5617-
return makeParserResult(Res);
5618-
}
5619-
5620-
ParserResult<OperatorDecl>
5621-
Parser::parseDeclPostfixOperator(SourceLoc OperatorLoc,
5622-
Identifier Name, SourceLoc NameLoc,
5623-
DeclAttributes &Attributes) {
5624-
SourceLoc lBraceLoc;
5625-
if (consumeIf(tok::l_brace, lBraceLoc)) {
5626-
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
5627-
if (Tok.is(tok::r_brace)) {
5628-
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5629-
NameLoc);
5630-
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5631-
Diag.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5632-
}
5633-
5634-
skipUntilDeclRBrace();
5635-
(void) consumeIf(tok::r_brace);
5636-
}
5637-
5638-
auto Res = new (Context) PostfixOperatorDecl(CurDeclContext, OperatorLoc,
5639-
Name, NameLoc);
5640-
Res->getAttrs() = Attributes;
5641-
return makeParserResult(Res);
5642-
}
5643-
5644-
ParserResult<OperatorDecl>
5645-
Parser::parseDeclInfixOperator(SourceLoc operatorLoc, Identifier name,
5646-
SourceLoc nameLoc, DeclAttributes &attributes) {
5595+
// Parse (or diagnose) a specified precedence group.
56475596
SourceLoc colonLoc;
56485597
Identifier precedenceGroupName;
56495598
SourceLoc precedenceGroupNameLoc;
56505599
if (consumeIf(tok::colon, colonLoc)) {
56515600
if (Tok.is(tok::identifier)) {
56525601
precedenceGroupName = Context.getIdentifier(Tok.getText());
56535602
precedenceGroupNameLoc = consumeToken(tok::identifier);
5603+
5604+
if (isPrefix || isPostfix)
5605+
diagnose(colonLoc, diag::precedencegroup_not_infix)
5606+
.fixItRemove({colonLoc, precedenceGroupNameLoc});
56545607
}
56555608
}
5656-
5609+
5610+
// Diagnose deprecated operator body syntax `operator + { ... }`.
56575611
SourceLoc lBraceLoc;
56585612
if (consumeIf(tok::l_brace, lBraceLoc)) {
5659-
if (Tok.is(tok::r_brace)) {
5660-
SourceLoc lastGoodLoc = precedenceGroupNameLoc;
5661-
if (lastGoodLoc.isInvalid())
5662-
lastGoodLoc = nameLoc;
5663-
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5664-
lastGoodLoc);
5665-
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5666-
diagnose(lBraceLoc, diag::deprecated_operator_body)
5667-
.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5668-
} else {
5613+
if (isInfix && !Tok.is(tok::r_brace)) {
56695614
diagnose(lBraceLoc, diag::deprecated_operator_body_use_group);
5615+
} else {
5616+
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
5617+
if (Tok.is(tok::r_brace)) {
5618+
SourceLoc lastGoodLoc = precedenceGroupNameLoc;
5619+
if (lastGoodLoc.isInvalid())
5620+
lastGoodLoc = NameLoc;
5621+
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5622+
lastGoodLoc);
5623+
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5624+
Diag.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5625+
}
56705626
}
56715627

56725628
skipUntilDeclRBrace();
56735629
(void) consumeIf(tok::r_brace);
56745630
}
5675-
5676-
auto res = new (Context) InfixOperatorDecl(CurDeclContext, operatorLoc,
5677-
name, nameLoc, colonLoc,
5678-
precedenceGroupName,
5679-
precedenceGroupNameLoc);
5680-
res->getAttrs() = attributes;
5631+
5632+
5633+
OperatorDecl *res;
5634+
if (Attributes.hasAttribute<PrefixAttr>())
5635+
res = new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc,
5636+
Name, NameLoc);
5637+
else if (Attributes.hasAttribute<PostfixAttr>())
5638+
res = new (Context) PostfixOperatorDecl(CurDeclContext, OperatorLoc,
5639+
Name, NameLoc);
5640+
else {
5641+
if (!Attributes.hasAttribute<InfixAttr>())
5642+
diagnose(OperatorLoc, diag::operator_decl_no_fixity);
5643+
5644+
res = new (Context) InfixOperatorDecl(CurDeclContext, OperatorLoc,
5645+
Name, NameLoc, colonLoc,
5646+
precedenceGroupName,
5647+
precedenceGroupNameLoc);
5648+
}
5649+
5650+
res->getAttrs() = Attributes;
56815651
return makeParserResult(res);
56825652
}
56835653

lib/Parse/ParseStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ namespace {
860860
Expr *Guard = nullptr;
861861
};
862862

863-
/// Contexts in which a guarded pattern can appears.
863+
/// Contexts in which a guarded pattern can appear.
864864
enum class GuardedPatternContext {
865865
Case,
866866
Catch,

test/Parse/operator_decl.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,33 @@ infix operator +++ {} // expected-warning {{operator should no longer be declare
66
infix operator +++* { // expected-warning {{operator should no longer be declared with body; use a precedence group instead}} {{none}}
77
associativity right
88
}
9-
infix operator +++** : A { } // expected-warning {{operator should no longer be declared with body}} {{25-29=}}
9+
infix operator +++*+ : A { } // expected-warning {{operator should no longer be declared with body}} {{25-29=}}
10+
11+
12+
prefix operator +++** : A { }
13+
// expected-error@-1 {{only infix operators may declare a precedence}} {{23-27=}}
14+
// expected-warning@-2 {{operator should no longer be declared with body}} {{26-30=}}
15+
16+
prefix operator ++*++ : A
17+
// expected-error@-1 {{only infix operators may declare a precedence}} {{23-26=}}
18+
19+
postfix operator ++*+* : A { }
20+
// expected-error@-1 {{only infix operators may declare a precedence}} {{24-28=}}
21+
// expected-warning@-2 {{operator should no longer be declared with body}} {{27-31=}}
22+
23+
postfix operator ++**+ : A
24+
// expected-error@-1 {{only infix operators may declare a precedence}} {{24-27=}}
25+
26+
operator ++*** : A
27+
// expected-error@-1 {{operator must be declared as 'prefix', 'postfix', or 'infix'}}
28+
29+
operator +*+++ { }
30+
// expected-error@-1 {{operator must be declared as 'prefix', 'postfix', or 'infix'}}
31+
// expected-warning@-2 {{operator should no longer be declared with body}} {{15-19=}}
32+
33+
operator +*++* : A { }
34+
// expected-error@-1 {{operator must be declared as 'prefix', 'postfix', or 'infix'}}
35+
// expected-warning@-2 {{operator should no longer be declared with body}} {{19-23=}}
1036

1137
prefix operator // expected-error {{expected operator name in operator declaration}}
1238

0 commit comments

Comments
 (0)