Skip to content

Commit 22158be

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 939376b commit 22158be

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
@@ -6488,7 +6488,8 @@ void AbstractStorageDecl::setAccessors(SourceLoc lbraceLoc,
64886488
auto record = Accessors.getPointer();
64896489
if (record) {
64906490
for (auto accessor : accessors) {
6491-
(void) record->addOpaqueAccessor(accessor);
6491+
if (!record->getAccessor(accessor->getAccessorKind()))
6492+
(void) record->addOpaqueAccessor(accessor);
64926493
}
64936494
} else {
64946495
record = AccessorRecord::create(getASTContext(),

lib/Parse/ParseDecl.cpp

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

75227522
bool hadLBrace = consumeIf(tok::l_brace);
75237523

7524-
ParserStatus status;
7524+
// Prepopulate the field for any accessors that were already parsed parsed accessors
75257525
ParsedAccessors accessors;
7526+
#define ACCESSOR(ID) \
7527+
if (auto accessor = storage->getAccessor(AccessorKind::ID)) \
7528+
accessors.ID = accessor;
7529+
#include "swift/AST/AccessorKinds.def"
7530+
7531+
ParserStatus status;
75267532
bool hasEffectfulGet = false;
75277533
bool parsingLimitedSyntax = false;
75287534
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)