Skip to content

Commit 565634c

Browse files
committed
Handle decl modifier keywords in isStartOfSwiftDecl
Previously we would always return true if we encountered a decl modifier keyword, however this could cause us to incorrectly consider SIL's usage of such keywords, e.g 'private', to be the start of a Swift decl. Adjust the logic to check the next token for the start of a Swift decl.
1 parent dfeb482 commit 565634c

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3350,6 +3350,35 @@ bool Parser::isStartOfSwiftDecl() {
33503350
return isStartOfSwiftDecl();
33513351
}
33523352

3353+
// If we have a decl modifying keyword, check if the next token is a valid
3354+
// decl start. This is necessary to correctly handle Swift keywords that are
3355+
// shared by SIL, e.g 'private' in 'sil private @foo :'. We need to make sure
3356+
// this isn't considered a valid Swift decl start.
3357+
if (Tok.isKeyword()) {
3358+
auto DAK = DeclAttribute::getAttrKindFromString(Tok.getText());
3359+
if (DAK != DAK_Count && DeclAttribute::isDeclModifier(DAK)) {
3360+
BacktrackingScope backtrack(*this);
3361+
consumeToken();
3362+
3363+
// Eat paren after modifier name; e.g. private(set)
3364+
if (consumeIf(tok::l_paren)) {
3365+
while (Tok.isNot(tok::r_brace, tok::eof, tok::pound_endif)) {
3366+
if (consumeIf(tok::r_paren))
3367+
break;
3368+
3369+
// If we found the start of a decl while trying to skip over the
3370+
// paren, then we have something incomplete like 'private('. Return
3371+
// true for better recovery.
3372+
if (isStartOfSwiftDecl())
3373+
return true;
3374+
3375+
skipSingle();
3376+
}
3377+
}
3378+
return isStartOfSwiftDecl();
3379+
}
3380+
}
3381+
33533382
// Otherwise, the only hard case left is the identifier case.
33543383
if (Tok.isNot(tok::identifier)) return true;
33553384

test/Parse/identifiers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ func <#some name#>() {} // expected-error {{editor placeholder in source file}}
3232
class switch {} // expected-error {{keyword 'switch' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{7-13=`switch`}}
3333
struct Self {} // expected-error {{keyword 'Self' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{8-12=`Self`}}
3434
protocol enum {} // expected-error {{keyword 'enum' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{10-14=`enum`}}
35-
protocol test { // expected-note{{in declaration of 'test'}}
36-
associatedtype public // expected-error {{keyword 'public' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{18-24=`public`}} expected-error {{consecutive declarations on a line must be separated by ';'}}
37-
} // expected-error{{expected declaration}}
35+
protocol test {
36+
associatedtype public // expected-error {{keyword 'public' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{18-24=`public`}}
37+
}
3838
func _(_ x: Int) {} // expected-error {{keyword '_' cannot be used as an identifier here}} // expected-note {{if this name is unavoidable, use backticks to escape it}} {{6-7=`_`}}
3939

4040
// SIL keywords are tokenized as normal identifiers in non-SIL mode.

0 commit comments

Comments
 (0)