Skip to content

Commit d6590cd

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

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
@@ -5466,17 +5466,8 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
54665466

54675467
Identifier Name = Context.getIdentifier(Tok.getText());
54685468
SourceLoc NameLoc = consumeToken();
5469-
5470-
ParserResult<OperatorDecl> Result;
5471-
if (Attributes.hasAttribute<PrefixAttr>())
5472-
Result = parseDeclPrefixOperator(OperatorLoc, Name, NameLoc, Attributes);
5473-
else if (Attributes.hasAttribute<PostfixAttr>())
5474-
Result = parseDeclPostfixOperator(OperatorLoc, Name, NameLoc, Attributes);
5475-
else {
5476-
if (!Attributes.hasAttribute<InfixAttr>())
5477-
diagnose(OperatorLoc, diag::operator_decl_no_fixity);
5478-
Result = parseDeclInfixOperator(OperatorLoc, Name, NameLoc, Attributes);
5479-
}
5469+
5470+
auto Result = parseDeclOperatorImpl(OperatorLoc, Name, NameLoc, Attributes);
54805471

54815472
if (!DCC.movedToTopLevel() && !AllowTopLevel) {
54825473
diagnose(OperatorLoc, diag::operator_decl_inner_scope);
@@ -5487,89 +5478,68 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
54875478
}
54885479

54895480
ParserResult<OperatorDecl>
5490-
Parser::parseDeclPrefixOperator(SourceLoc OperatorLoc, Identifier Name,
5481+
Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
54915482
SourceLoc NameLoc, DeclAttributes &Attributes) {
5492-
SourceLoc lBraceLoc;
5493-
if (consumeIf(tok::l_brace, lBraceLoc)) {
5494-
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
5495-
if (Tok.is(tok::r_brace)) {
5496-
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5497-
NameLoc);
5498-
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5499-
Diag.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5500-
}
5501-
5502-
skipUntilDeclRBrace();
5503-
(void) consumeIf(tok::r_brace);
5504-
}
5483+
bool isPrefix = Attributes.hasAttribute<PrefixAttr>();
5484+
bool isInfix = Attributes.hasAttribute<InfixAttr>();
5485+
bool isPostfix = Attributes.hasAttribute<PostfixAttr>();
55055486

5506-
auto *Res = new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc,
5507-
Name, NameLoc);
5508-
Res->getAttrs() = Attributes;
5509-
return makeParserResult(Res);
5510-
}
5511-
5512-
ParserResult<OperatorDecl>
5513-
Parser::parseDeclPostfixOperator(SourceLoc OperatorLoc,
5514-
Identifier Name, SourceLoc NameLoc,
5515-
DeclAttributes &Attributes) {
5516-
SourceLoc lBraceLoc;
5517-
if (consumeIf(tok::l_brace, lBraceLoc)) {
5518-
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
5519-
if (Tok.is(tok::r_brace)) {
5520-
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5521-
NameLoc);
5522-
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5523-
Diag.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5524-
}
5525-
5526-
skipUntilDeclRBrace();
5527-
(void) consumeIf(tok::r_brace);
5528-
}
5529-
5530-
auto Res = new (Context) PostfixOperatorDecl(CurDeclContext, OperatorLoc,
5531-
Name, NameLoc);
5532-
Res->getAttrs() = Attributes;
5533-
return makeParserResult(Res);
5534-
}
5535-
5536-
ParserResult<OperatorDecl>
5537-
Parser::parseDeclInfixOperator(SourceLoc operatorLoc, Identifier name,
5538-
SourceLoc nameLoc, DeclAttributes &attributes) {
5487+
// Parse (or diagnose) a specified precedence group.
55395488
SourceLoc colonLoc;
55405489
Identifier precedenceGroupName;
55415490
SourceLoc precedenceGroupNameLoc;
55425491
if (consumeIf(tok::colon, colonLoc)) {
55435492
if (Tok.is(tok::identifier)) {
55445493
precedenceGroupName = Context.getIdentifier(Tok.getText());
55455494
precedenceGroupNameLoc = consumeToken(tok::identifier);
5495+
5496+
if (isPrefix || isPostfix)
5497+
diagnose(colonLoc, diag::precedencegroup_not_infix)
5498+
.fixItRemove({colonLoc, precedenceGroupNameLoc});
55465499
}
55475500
}
5548-
5501+
5502+
// Diagnose deprecated operator body syntax `operator + { ... }`.
55495503
SourceLoc lBraceLoc;
55505504
if (consumeIf(tok::l_brace, lBraceLoc)) {
5551-
if (Tok.is(tok::r_brace)) {
5552-
SourceLoc lastGoodLoc = precedenceGroupNameLoc;
5553-
if (lastGoodLoc.isInvalid())
5554-
lastGoodLoc = nameLoc;
5555-
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5556-
lastGoodLoc);
5557-
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5558-
diagnose(lBraceLoc, diag::deprecated_operator_body)
5559-
.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5560-
} else {
5505+
if (isInfix && !Tok.is(tok::r_brace)) {
55615506
diagnose(lBraceLoc, diag::deprecated_operator_body_use_group);
5507+
} else {
5508+
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
5509+
if (Tok.is(tok::r_brace)) {
5510+
SourceLoc lastGoodLoc = precedenceGroupNameLoc;
5511+
if (lastGoodLoc.isInvalid())
5512+
lastGoodLoc = NameLoc;
5513+
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
5514+
lastGoodLoc);
5515+
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
5516+
Diag.fixItRemoveChars(lastGoodLocEnd, rBraceEnd);
5517+
}
55625518
}
55635519

55645520
skipUntilDeclRBrace();
55655521
(void) consumeIf(tok::r_brace);
55665522
}
5567-
5568-
auto res = new (Context) InfixOperatorDecl(CurDeclContext, operatorLoc,
5569-
name, nameLoc, colonLoc,
5570-
precedenceGroupName,
5571-
precedenceGroupNameLoc);
5572-
res->getAttrs() = attributes;
5523+
5524+
5525+
OperatorDecl *res;
5526+
if (Attributes.hasAttribute<PrefixAttr>())
5527+
res = new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc,
5528+
Name, NameLoc);
5529+
else if (Attributes.hasAttribute<PostfixAttr>())
5530+
res = new (Context) PostfixOperatorDecl(CurDeclContext, OperatorLoc,
5531+
Name, NameLoc);
5532+
else {
5533+
if (!Attributes.hasAttribute<InfixAttr>())
5534+
diagnose(OperatorLoc, diag::operator_decl_no_fixity);
5535+
5536+
res = new (Context) InfixOperatorDecl(CurDeclContext, OperatorLoc,
5537+
Name, NameLoc, colonLoc,
5538+
precedenceGroupName,
5539+
precedenceGroupNameLoc);
5540+
}
5541+
5542+
res->getAttrs() = Attributes;
55735543
return makeParserResult(res);
55745544
}
55755545

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)