Skip to content

Commit 2cd25c8

Browse files
authored
Merge pull request #5194 from rintaro/parselist-earlybailout
[Parse] Improve error handling in parseList
2 parents be55ede + fba1ed2 commit 2cd25c8

File tree

16 files changed

+96
-131
lines changed

16 files changed

+96
-131
lines changed

lib/Parse/ParsePattern.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
324324
diagnose(Tok, diag::expected_parameter_name);
325325
param.isInvalid = true;
326326
param.FirstNameLoc = Tok.getLoc();
327+
status.setIsParseError();
327328
}
328329
}
329330

lib/Parse/Parser.cpp

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -679,52 +679,46 @@ Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
679679
RightLoc = Tok.getLoc();
680680
return Status;
681681
}
682-
SourceLoc SepLoc = Tok.getLoc();
683-
if (consumeIf(SeparatorK)) {
684-
if (Tok.is(RightK)) {
685-
if (!AllowSepAfterLast) {
686-
diagnose(Tok, diag::unexpected_separator,
687-
SeparatorK == tok::comma ? "," : ";")
688-
.fixItRemove(SourceRange(SepLoc));
689-
}
682+
// If we haven't made progress, or seeing any error, skip ahead.
683+
if (Tok.getLoc() == StartLoc || Status.isError()) {
684+
assert(Status.isError() && "no progress without error");
685+
skipUntilDeclRBrace(RightK, SeparatorK);
686+
if (Tok.is(RightK) || (!OptionalSep && Tok.isNot(SeparatorK)))
690687
break;
688+
}
689+
if (consumeIf(SeparatorK)) {
690+
if (Tok.isNot(RightK))
691+
continue;
692+
if (!AllowSepAfterLast) {
693+
diagnose(Tok, diag::unexpected_separator,
694+
SeparatorK == tok::comma ? "," : ";")
695+
.fixItRemove(SourceRange(PreviousLoc));
691696
}
692-
continue;
697+
break;
698+
}
699+
// If we're in a comma-separated list, the next token is at the
700+
// beginning of a new line and can never start a element, break.
701+
if (SeparatorK == tok::comma && Tok.isAtStartOfLine() &&
702+
(Tok.is(tok::r_brace) || isStartOfDecl() || isStartOfStmt())) {
703+
break;
704+
}
705+
// If we found EOF or such, bailout.
706+
if (Tok.isAny(tok::eof, tok::pound_endif)) {
707+
IsInputIncomplete = true;
708+
break;
693709
}
694710
if (!OptionalSep) {
695-
// If we're in a comma-separated list and the next token starts a new
696-
// declaration at the beginning of a new line, skip until the end.
697-
if (SeparatorK == tok::comma && Tok.isAtStartOfLine() &&
698-
isStartOfDecl() && Tok.getLoc() != StartLoc) {
699-
skipUntilDeclRBrace(RightK, SeparatorK);
700-
break;
701-
}
702-
703711
StringRef Separator = (SeparatorK == tok::comma ? "," : ";");
704712
diagnose(Tok, diag::expected_separator, Separator)
705713
.fixItInsertAfter(PreviousLoc, Separator);
706714
Status.setIsParseError();
707715
}
708-
709-
710-
// If we haven't made progress, skip ahead
711-
if (Tok.getLoc() == StartLoc) {
712-
skipUntilDeclRBrace(RightK, SeparatorK);
713-
if (Tok.is(RightK))
714-
break;
715-
if (Tok.is(tok::eof) || Tok.is(tok::pound_endif)) {
716-
RightLoc = PreviousLoc.isValid()? PreviousLoc : Tok.getLoc();
717-
IsInputIncomplete = true;
718-
Status.setIsParseError();
719-
return Status;
720-
}
721-
if (consumeIf(SeparatorK) || OptionalSep)
722-
continue;
723-
break;
724-
}
725716
}
726717

727-
if (parseMatchingToken(RightK, RightLoc, ErrorDiag, LeftLoc)) {
718+
if (Status.isError()) {
719+
// If we've already got errors, don't emit missing RightK diagnostics.
720+
RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
721+
} else if (parseMatchingToken(RightK, RightLoc, ErrorDiag, LeftLoc)) {
728722
Status.setIsParseError();
729723
}
730724

test/IDE/complete_unresolved_members.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ var Container = OptionTakerContainer1()
208208
Container.OptionSetTaker1(.#^UNRESOLVED_19^#
209209
Container.EnumTaker1(.#^UNRESOLVED_20^#
210210

211+
func parserSync() {}
212+
211213
// UNRESOLVED_4: Begin completions
212214
// UNRESOLVED_4-DAG: Decl[StaticVar]/CurrNominal: Option1[#SomeOptions1#]; name=Option1
213215
// UNRESOLVED_4-DAG: Decl[StaticVar]/CurrNominal: Option2[#SomeOptions1#]; name=Option2

test/Parse/ConditionalCompilation/decl_parse_errors.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ lazy
2727
var val3: Int = 0;
2828
#line
2929

30-
class C { // expected-note 3 {{in declaration of 'C'}}
30+
class C { // expected-note 2 {{in declaration of 'C'}} expected-note {{to match this opening '{'}}
3131

3232
#if os(iOS)
3333
func foo() {}
3434
} // expected-error{{expected declaration}} expected-error{{expected #else or #endif at end of conditional compilation block}}
3535
#else
3636
func bar() {}
3737
func baz() {}
38-
} // expected-error{{expected #else or #endif at end of conditional compilation block}} expected-error {{expected declaration}}
38+
} // expected-error{{expected declaration}} expected-error{{expected #else or #endif at end of conditional compilation block}}
3939
#endif
40-
// expected-error@+1{{expected declaration}}
40+
// expected-error@+1{{expected '}' in class}}

test/Parse/invalid.swift

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,18 @@ func test2(inout let x : Int) {} // expected-error {{parameter may not have mul
1515
func test3(f : (inout _ x : Int) -> Void) {} // expected-error {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}
1616

1717
func test3() {
18-
undeclared_func( // expected-error {{use of unresolved identifier 'undeclared_func'}} expected-note {{to match this opening '('}} expected-error {{expected ',' separator}} {{19-19=,}}
19-
} // expected-error {{expected expression in list of expressions}} expected-error {{expected ')' in expression list}}
18+
undeclared_func( // expected-error {{use of unresolved identifier 'undeclared_func'}}
19+
} // expected-error {{expected expression in list of expressions}}
2020

2121
func runAction() {} // expected-note {{did you mean 'runAction'?}}
2222

2323
// rdar://16601779
2424
func foo() {
25-
runAction(SKAction.sequence() // expected-error {{use of unresolved identifier 'SKAction'}} expected-note {{to match this opening '('}} expected-error {{expected ',' separator}} {{32-32=,}}
25+
runAction(SKAction.sequence() // expected-error {{use of unresolved identifier 'SKAction'}} expected-error {{expected ',' separator}} {{32-32=,}}
2626

27-
// expected-error @+2 {{expected ',' separator}} {{12-12=,}}
28-
// expected-error @+1 {{expected ',' separator}} {{12-12=,}}
2927
skview!
3028
// expected-error @-1 {{use of unresolved identifier 'skview'}}
31-
} // expected-error {{expected expression in list of expressions}} expected-error {{expected ')' in expression list}}
29+
}
3230

3331
super.init() // expected-error {{'super' cannot be used outside of class members}}
3432

@@ -40,15 +38,12 @@ switch state { // expected-error {{use of unresolved identifier 'state'}}
4038
// rdar://18926814
4139
func test4() {
4240
let abc = 123
43-
_ = " >> \( abc } ) << " // expected-note {{to match this opening '('}} expected-error {{expected ')' in expression list}} expected-error {{expected ',' separator}} {{18-18=,}} expected-error {{expected ',' separator}} {{18-18=,}} expected-error {{expected expression in list of expressions}} expected-error {{extra tokens after interpolated string expression}}
41+
_ = " >> \( abc } ) << " // expected-error {{expected ',' separator}} {{18-18=,}} expected-error {{expected expression in list of expressions}} expected-error {{extra tokens after interpolated string expression}}
4442

4543
}
4644

4745
// rdar://problem/18507467
4846
func d(_ b: String -> <T>() -> T) {} // expected-error {{expected type for function result}}
49-
// expected-error @-1 {{expected ',' separator}} {{22-22=,}}
50-
// expected-error @-2 {{expected parameter name followed by ':'}}
51-
// expected-error @-3 {{expected ',' separator}}
5247

5348

5449
// <rdar://problem/22143680> QoI: terrible diagnostic when trying to form a generic protocol

test/Parse/matching_patterns.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ case (_?)?: break
308308

309309
// <rdar://problem/20365753> Bogus diagnostic "refutable pattern match can fail"
310310
let (responseObject: Int?) = op1
311-
// expected-error @-1 2 {{expected ',' separator}} {{25-25=,}} {{25-25=,}}
311+
// expected-error @-1 {{expected ',' separator}} {{25-25=,}}
312312
// expected-error @-2 {{expected pattern}}
313313

314314

test/Parse/object_literals.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
let _ = [##] // expected-error{{expected identifier after '#' in object literal expression}} expected-error{{object literal syntax no longer uses '[# ... #]'}} {{9-10=}} {{11-13=}}
44
let _ = [#what#] // expected-error{{object literal syntax no longer uses '[# ... #]'}} {{9-10=}} {{15-17=}}
55
let _ = [#what()#] // expected-error{{object literal syntax no longer uses '[# ... #]'}} {{9-10=}} {{17-19=}}
6-
let _ = [#colorLiteral( // expected-error{{expected ',' separator}} expected-error{{expected expression in list of expressions}}
6+
let _ = [#colorLiteral( // expected-error@+1 {{expected expression in list of expressions}}

test/Parse/recovery.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,19 +481,15 @@ Base=1 as Base=1 // expected-error {{cannot assign to immutable expression of t
481481

482482
// <rdar://problem/18634543> Parser hangs at swift::Parser::parseType
483483
public enum TestA {
484-
// expected-error @+2 {{expected ',' separator}}
485484
// expected-error @+1{{expected '{' in body of function declaration}}
486485
public static func convertFromExtenndition( // expected-error {{expected parameter name followed by ':'}}
487-
// expected-error@+2 {{expected ',' separator}}
488486
// expected-error@+1{{expected parameter name followed by ':'}}
489487
s._core.count != 0, "Can't form a Character from an empty String")
490488
}
491489

492490
public enum TestB {
493-
// expected-error@+2 {{expected ',' separator}}
494491
// expected-error@+1{{expected '{' in body of function declaration}}
495492
public static func convertFromExtenndition( // expected-error {{expected parameter name followed by ':'}}
496-
// expected-error@+2 {{expected ',' separator}}
497493
// expected-error@+1 {{expected parameter name followed by ':'}}
498494
s._core.count ?= 0, "Can't form a Character from an empty String")
499495
}
@@ -527,10 +523,9 @@ case let (jeb):
527523
// rdar://19605164
528524
// expected-error@+2{{use of undeclared type 'S'}}
529525
struct Foo19605164 {
530-
func a(s: S[{{g) -> Int {} // expected-note {{to match this opening '('}}
531-
// expected-error@+3 {{expected parameter name followed by ':'}}
532-
// expected-error@+2 2 {{expected ',' separator}}
533-
// expected-error@+1 {{expected ')' in parameter}}
526+
func a(s: S[{{g) -> Int {}
527+
// expected-error@+2 {{expected parameter name followed by ':'}}
528+
// expected-error@+1 {{expected ',' separator}}
534529
}}}
535530
#endif
536531

@@ -659,7 +654,7 @@ func r21712891(s : String) -> String {
659654
let a = s.startIndex..<s.startIndex
660655
_ = a
661656
// The specific errors produced don't actually matter, but we need to reject this.
662-
return "\(s[a)" // expected-error 3 {{}}
657+
return "\(s[a)" // expected-error {{expected ']' in expression list}} expected-note {{to match this opening '['}}
663658
}
664659

665660

test/Parse/subscripting.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ _ = y2[0] // expected-error{{cannot use mutating getter on immutable value: 'y2'
8181

8282
// Parsing errors
8383
// FIXME: Recovery here is horrible
84-
struct A0 { // expected-note{{in declaration of 'A0'}}
84+
struct A0 {
8585
subscript // expected-error{{expected '(' for subscript parameters}}
86-
i : Int // expected-error{{expected declaration}}
86+
i : Int
8787
-> Int {
8888
get {
8989
return stored
@@ -94,9 +94,9 @@ struct A0 { // expected-note{{in declaration of 'A0'}}
9494
}
9595
}
9696

97-
struct A1 { // expected-note{{in declaration of 'A1'}}
97+
struct A1 {
9898
subscript (i : Int) // expected-error{{expected '->' for subscript element type}}
99-
Int { // expected-error{{expected declaration}}
99+
Int {
100100
get {
101101
return stored
102102
}
@@ -106,9 +106,9 @@ struct A1 { // expected-note{{in declaration of 'A1'}}
106106
}
107107
}
108108

109-
struct A2 { // expected-note{{in declaration of 'A2'}}
109+
struct A2 {
110110
subscript (i : Int) -> // expected-error{{expected subscripting element type}}
111-
{ // expected-error{{expected declaration}}
111+
{
112112
get {
113113
return stored
114114
}
@@ -118,17 +118,17 @@ struct A2 { // expected-note{{in declaration of 'A2'}}
118118
}
119119
}
120120

121-
struct A3 { // expected-note{{in declaration of 'A3'}}
121+
struct A3 {
122122
subscript(i : Int) // expected-error {{expected '->' for subscript element type}}
123-
{ // expected-error {{expected declaration}}
123+
{
124124
get {
125125
return i
126126
}
127127
}
128128
}
129129

130-
struct A4 { // expected-note{{in declaration of 'A4'}}
131-
subscript(i : Int) { // expected-error {{expected '->' for subscript element type}} expected-error {{consecutive declarations on a line must be separated by ';'}} {{21-21=;}} expected-error {{expected declaration}}
130+
struct A4 {
131+
subscript(i : Int) { // expected-error {{expected '->' for subscript element type}}
132132
get {
133133
return i
134134
}
@@ -139,8 +139,8 @@ struct A5 {
139139
subscript(i : Int) -> Int // expected-error {{expected '{' in subscript to specify getter and setter implementation}}
140140
}
141141

142-
struct A6 { // expected-note{{in declaration of 'A6'}}
143-
subscript(i: Int)(j: Int) -> Int { // expected-error {{expected '->' for subscript element type}} expected-error {{consecutive declarations on a line must be separated by ';'}} {{20-20=;}} expected-error {{expected declaration}}
142+
struct A6 {
143+
subscript(i: Int)(j: Int) -> Int { // expected-error {{expected '->' for subscript element type}}
144144
get {
145145
return i + j
146146
}
@@ -163,9 +163,9 @@ struct A7b {
163163
}
164164
}
165165

166-
struct A8 { // expected-note{{in declaration of 'A8'}}
166+
struct A8 {
167167
subscript(i : Int) -> Int // expected-error{{expected '{' in subscript to specify getter and setter implementation}}
168-
get { // expected-error{{expected declaration}}
168+
get {
169169
return stored
170170
}
171171
set {

test/Sema/immutability.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,11 +452,11 @@ struct StructWithDelegatingInit {
452452
}
453453

454454
func test_recovery_missing_name_2(let: Int) {} // expected-error {{'let' as a parameter attribute is not allowed}}{{35-38=}}
455-
// expected-error @-1 2{{expected ',' separator}} {{38-38=,}} expected-error @-1 2 {{expected parameter name followed by ':'}}
455+
// expected-error @-1 {{expected parameter name followed by ':'}}
456456

457457
// <rdar://problem/16792027> compiler infinite loops on a really really mutating function
458-
struct F { // expected-note 2 {{in declaration of 'F'}}
459-
mutating mutating mutating f() { // expected-error 2 {{duplicate modifier}} expected-note 2 {{modifier already specified here}} expected-error {{consecutive declarations on a line must be separated by ';'}} {{29-29=;}} expected-error 2 {{expected declaration}}
458+
struct F { // expected-note 1 {{in declaration of 'F'}}
459+
mutating mutating mutating f() { // expected-error 2 {{duplicate modifier}} expected-note 2 {{modifier already specified here}} expected-error {{expected declaration}}
460460
}
461461

462462
mutating nonmutating func g() { // expected-error {{method may not be declared both mutating and nonmutating}} {{12-24=}}

test/SourceKit/CursorInfo/rdar_18677108-2.swift.response

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,21 @@
11
[
22
{
3-
key.line: 6,
4-
key.column: 2,
5-
key.filepath: rdar_18677108-2-a.swift,
6-
key.severity: source.diagnostic.severity.error,
7-
key.description: "expected ',' separator",
8-
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
9-
key.fixits: [
10-
{
11-
key.offset: 184,
12-
key.length: 0,
13-
key.sourcetext: ","
14-
}
15-
]
16-
},
17-
{
18-
key.line: 6,
19-
key.column: 2,
3+
key.line: 7,
4+
key.column: 1,
205
key.filepath: rdar_18677108-2-a.swift,
216
key.severity: source.diagnostic.severity.error,
22-
key.description: "expected ',' separator",
7+
key.description: "expected ')' in expression list",
238
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
24-
key.fixits: [
9+
key.diagnostics: [
2510
{
26-
key.offset: 184,
27-
key.length: 0,
28-
key.sourcetext: ","
11+
key.line: 5,
12+
key.column: 46,
13+
key.filepath: rdar_18677108-2-a.swift,
14+
key.severity: source.diagnostic.severity.note,
15+
key.description: "to match this opening '('"
2916
}
3017
]
3118
},
32-
{
33-
key.line: 7,
34-
key.column: 1,
35-
key.filepath: rdar_18677108-2-a.swift,
36-
key.severity: source.diagnostic.severity.error,
37-
key.description: "expected expression in list of expressions",
38-
key.diagnostic_stage: source.diagnostic.stage.swift.parse
39-
},
4019
{
4120
key.line: 7,
4221
key.column: 1,
@@ -59,15 +38,15 @@
5938
key.column: 1,
6039
key.filepath: rdar_18677108-2-a.swift,
6140
key.severity: source.diagnostic.severity.error,
62-
key.description: "expected declaration",
41+
key.description: "expected '}' in class",
6342
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
6443
key.diagnostics: [
6544
{
66-
key.line: 1,
67-
key.column: 7,
45+
key.line: 2,
46+
key.column: 1,
6847
key.filepath: rdar_18677108-2-a.swift,
6948
key.severity: source.diagnostic.severity.note,
70-
key.description: "in declaration of 'CameraController'"
49+
key.description: "to match this opening '{'"
7150
}
7251
]
7352
}

0 commit comments

Comments
 (0)