Skip to content

Commit 1426980

Browse files
authored
Merge pull request #65737 from bnbarham/expand-infinite-loop
[Macros] Terminate parsing expanded members if no progress is made
2 parents 2c91c54 + cec1fa2 commit 1426980

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,10 +2085,10 @@ WARNING(macro_expression_attribute_removed,PointsToFirstBadToken,
20852085
"@expression has been removed in favor of @freestanding(expression)", ())
20862086

20872087
ERROR(unexpected_attribute_expansion,PointsToFirstBadToken,
2088-
"unexpected token '%0' in expanded attribute list'",
2088+
"unexpected token '%0' in expanded attribute list",
20892089
(StringRef))
20902090
ERROR(unexpected_member_expansion,PointsToFirstBadToken,
2091-
"unexpected token '%0' in expanded member list'",
2091+
"unexpected token '%0' in expanded member list",
20922092
(StringRef))
20932093

20942094
ERROR(parser_round_trip_error,none,

lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7325,10 +7325,14 @@ void Parser::parseExpandedMemberList(SmallVectorImpl<ASTNode> &items) {
73257325
auto *idc = dyn_cast<IterableDeclContext>(decl);
73267326
bool previousHadSemi = true;
73277327

7328+
SourceLoc startingLoc = Tok.getLoc();
73287329
while (!Tok.is(tok::eof)) {
73297330
parseDeclItem(previousHadSemi,
73307331
getMemberParseDeclOptions(idc),
73317332
[&](Decl *d) { items.push_back(d); });
7333+
7334+
if (Tok.getLoc() == startingLoc)
7335+
break;
73327336
}
73337337

73347338
// Consume remaining tokens.

test/Macros/macro_invalid.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file --leading-lines %s %t
5+
6+
// Create the plugin
7+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroPlugin) -module-name=MacroPlugin %t/MacroPlugin.swift -g -no-toolchain-stdlib-rpath
8+
9+
// RUN: not %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroPlugin) -module-name TestModule %t/TestModule.swift 2>&1 | %FileCheck %s
10+
// CHECK: unexpected token '}' in expanded member list
11+
12+
//--- MacroPlugin.swift
13+
import SwiftSyntax
14+
import SwiftSyntaxBuilder
15+
import SwiftSyntaxMacros
16+
17+
public struct InvalidMemberMacro: MemberMacro {
18+
public static func expansion(
19+
of node: AttributeSyntax,
20+
providingMembersOf decl: some DeclGroupSyntax,
21+
in context: some MacroExpansionContext
22+
) throws -> [DeclSyntax] {
23+
let invalidMember: DeclSyntax =
24+
"""
25+
// no member here
26+
}
27+
"""
28+
29+
return [
30+
invalidMember
31+
]
32+
}
33+
}
34+
35+
//--- TestModule.swift
36+
@attached(member)
37+
public macro InvalidMember() = #externalMacro(module: "MacroPlugin", type: "InvalidMemberMacro")
38+
39+
@InvalidMember
40+
struct TestStruct { }

0 commit comments

Comments
 (0)