Skip to content

Commit 213465e

Browse files
committed
[Macros] Allow keywords after # in freestanding macro expansions
Allow keywords after `#` in freestanding macro expansions There is no reason why we shouldn’t allow keywords here. I also thought about allowing keywords after `@` but things become tricky here for two reasons: - In the parser, we parse a type after the `@`, which could start with a keyword itself (e.g. `any`). If we want to keep the parser logic to parse a type after `@` (which I think we should), then it becomes unclear what `@any T` should parse as. - We allow a space between `@` and the type name. This makes it very hard for recovery to tell whether `@ struct` refers to an attribute with name `struct` or if the user forgot to write the attribute name after `@`. Since almost all keywords are lowercase and attached member macros are usually spelled with an uppercase name, there are a lot fewer chances for clashes here, so I don’t think it’s worth allowing keywords after `@`. #66444 rdar://110472060
1 parent c95d3e2 commit 213465e

File tree

6 files changed

+9
-18
lines changed

6 files changed

+9
-18
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,16 +2301,7 @@ ParserStatus Parser::parseFreestandingMacroExpansion(
23012301

23022302
bool hasWhitespaceBeforeName = poundEndLoc != Tok.getLoc();
23032303

2304-
// Diagnose and parse keyword right after `#`.
2305-
if (Tok.isKeyword() && !hasWhitespaceBeforeName) {
2306-
diagnose(Tok, diag::keyword_cant_be_identifier, Tok.getText());
2307-
diagnose(Tok, diag::backticks_to_escape)
2308-
.fixItReplace(Tok.getLoc(), "`" + Tok.getText().str() + "`");
2309-
2310-
// Let 'parseDeclNameRef' to parse this as an identifier.
2311-
Tok.setKind(tok::identifier);
2312-
}
2313-
macroNameRef = parseDeclNameRef(macroNameLoc, diag, DeclNameOptions());
2304+
macroNameRef = parseDeclNameRef(macroNameLoc, diag, DeclNameFlag::AllowKeywords);
23142305
if (!macroNameRef)
23152306
return makeParserError();
23162307

test/Macros/macro_keywordname.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import MacroLib
5353
@freestanding(expression) public macro `class`() -> Int = #externalMacro(module: "MacroDefinition", type: "OneMacro")
5454

5555
func test() {
56-
let _: Int = #public() // expected-error {{keyword 'public' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}}
56+
let _: Int = #public()
5757
let _: Int = #`public`()
5858
let _: Int = #escaped()
5959
let _: Int = #`class`()

test/Macros/macro_self.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ func sync() {}
99
macro Self() = #externalMacro(module: "MacroDefinition", type: "InvalidMacro")
1010

1111
func testSelfAsFreestandingMacro() {
12-
_ = #self // expected-error {{keyword 'self' cannot be used as an identifier here}} expected-note {{use backticks to escape it}}
12+
_ = #self
1313
}
1414

1515
func testCapitalSelfAsFreestandingMacro() {
16-
_ = #Self // expected-error {{keyword 'Self' cannot be used as an identifier here}} expected-note {{use backticks to escape it}}
16+
_ = #Self
1717
}
1818

1919
func testSelfAsAttachedMacro() {

test/Parse/macro_decl.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ public # someFunc // expected-error {{extraneous whitespace between '#' and macr
5151
5252
struct S {
5353
# someFunc // expected-error {{extraneous whitespace between '#' and macro name is not permitted}} {{4-5=}}
54-
#class // expected-error {{keyword 'class' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{4-9=`class`}}
54+
#class
5555
# struct Inner {} // expected-error {{expected a macro identifier for a pound literal declaration}} expected-error {{consecutive declarations on a line}}
5656
}

test/Parse/macro_expr.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ do {
4444
_ = # macro() // expected-error {{extraneous whitespace between '#' and macro name is not permitted}} {{8-9=}}
4545
}
4646
do {
47-
_ = #public() // expected-error {{keyword 'public' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{8-14=`public`}}
47+
_ = #public()
4848
}
4949
do {
5050
_ = # public() // expected-error {{expected a macro identifier for a pound literal expression}}

test/decl/import/import.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ import func Swift.print
3535

3636
// rdar://14418336
3737
#import something_nonexistent
38-
// expected-error@-1 {{keyword 'import' cannot be used as an identifier here}} expected-note@-1 {{use backticks to escape it}}
39-
// expected-error@-2 {{no macro named 'import'}}
40-
// expected-error@-3 {{consecutive statements on a line}} expected-error@-3 {{cannot find 'something_nonexistent' in scope}}
38+
// expected-error@-1 {{no macro named 'import'}}
39+
// expected-error@-2 {{consecutive statements on a line}}
40+
// expected-error@-3 {{cannot find 'something_nonexistent' in scope}}
4141

4242
// Import specific decls
4343
import typealias Swift.Int

0 commit comments

Comments
 (0)