Skip to content

Commit b04b4ef

Browse files
committed
[Macros] Diagnose when an accessor macro produces an accessor that already exists
We used to crash; now we diagnose and... don't crash. Fixes rdar://111588129.
1 parent 6f1cf76 commit b04b4ef

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

lib/AST/Decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6478,7 +6478,8 @@ void AbstractStorageDecl::setAccessors(SourceLoc lbraceLoc,
64786478
auto record = Accessors.getPointer();
64796479
if (record) {
64806480
for (auto accessor : accessors) {
6481-
(void) record->addOpaqueAccessor(accessor);
6481+
if (!record->getAccessor(accessor->getAccessorKind()))
6482+
(void) record->addOpaqueAccessor(accessor);
64826483
}
64836484
} else {
64846485
record = AccessorRecord::create(getASTContext(),

lib/Parse/ParseDecl.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7448,8 +7448,14 @@ void Parser::parseTopLevelAccessors(
74487448

74497449
bool hadLBrace = consumeIf(tok::l_brace);
74507450

7451-
ParserStatus status;
7451+
// Prepopulate the field for any accessors that were already parsed parsed accessors
74527452
ParsedAccessors accessors;
7453+
#define ACCESSOR(ID) \
7454+
if (auto accessor = storage->getAccessor(AccessorKind::ID)) \
7455+
accessors.ID = accessor;
7456+
#include "swift/AST/AccessorKinds.def"
7457+
7458+
ParserStatus status;
74537459
bool hasEffectfulGet = false;
74547460
bool parsingLimitedSyntax = false;
74557461
while (!Tok.isAny(tok::r_brace, tok::eof)) {

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,7 @@ extension PropertyWrapperMacro: AccessorMacro, Macro {
422422
) throws -> [AccessorDeclSyntax] {
423423
guard let varDecl = declaration.as(VariableDeclSyntax.self),
424424
let binding = varDecl.bindings.first,
425-
let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier,
426-
binding.accessor == nil
425+
let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier
427426
else {
428427
return []
429428
}

test/Macros/accessor_macros.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
// First check for no errors.
77
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition)
88

9+
// Check for expected errors.
10+
// RUN: not %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -DTEST_DIAGNOSTICS %s > %t/diags.txt 2>&1
11+
// RUN: %FileCheck -check-prefix=CHECK-DIAGS %s < %t/diags.txt
12+
913
// Check that the expansion buffer are as expected.
1014
// RUN: %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) %s -dump-macro-expansions > %t/expansions-dump.txt 2>&1
1115
// RUN: %FileCheck -check-prefix=CHECK-DUMP %s < %t/expansions-dump.txt
@@ -72,3 +76,23 @@ _ = ms.name
7276
// CHECK-NEXT: Setting value World
7377
ms.name = "World"
7478

79+
80+
#if TEST_DIAGNOSTICS
81+
struct MyBrokenStruct {
82+
var _birthDate: MyWrapperThingy<Date?> = .init(storage: nil)
83+
84+
@myPropertyWrapper
85+
var birthDate: Date? {
86+
// CHECK-DIAGS: variable already has a getter
87+
// CHECK-DIAGS: in expansion of macro
88+
// CHECK-DIAGS: previous definition of getter here
89+
get { fatalError("Boom") }
90+
91+
// CHECK-DIAGS: variable already has a setter
92+
// CHECK-DIAGS: in expansion of macro
93+
// CHECK-DIAGS: previous definition of setter here
94+
set { fatalError("Boom") }
95+
}
96+
}
97+
98+
#endif

0 commit comments

Comments
 (0)