Skip to content

Commit fe6703b

Browse files
authored
Merge pull request #77224 from allevato/macro-objc
[PrintAsClang] Ensure that all macro-generated decls get printed.
2 parents bf30a19 + eeeb73a commit fe6703b

File tree

5 files changed

+270
-32
lines changed

5 files changed

+270
-32
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ class DeclAndTypePrinter::Implementation
188188
}
189189

190190
bool isEmptyExtensionDecl(const ExtensionDecl *ED) {
191-
auto members = ED->getMembers();
191+
auto members = ED->getAllMembers();
192192
auto hasMembers = std::any_of(members.begin(), members.end(),
193193
[this](const Decl *D) -> bool {
194194
if (auto VD = dyn_cast<ValueDecl>(D))
@@ -371,7 +371,7 @@ class DeclAndTypePrinter::Implementation
371371
if (outputLang == OutputLanguageMode::Cxx) {
372372
// FIXME: Non objc class.
373373
ClangClassTypePrinter(os).printClassTypeDecl(
374-
CD, [&]() { printMembers(CD->getMembers()); }, owningPrinter);
374+
CD, [&]() { printMembers(CD->getAllMembers()); }, owningPrinter);
375375
recordEmittedDeclInCurrentCxxLexicalScope(CD);
376376
return;
377377
}
@@ -411,7 +411,7 @@ class DeclAndTypePrinter::Implementation
411411
os << " : " << getNameForObjC(superDecl);
412412
printProtocols(CD->getLocalProtocols(ConformanceLookupKind::OnlyExplicit));
413413
os << "\n";
414-
printMembers(CD->getMembers());
414+
printMembers(CD->getAllMembers());
415415
os << "@end\n";
416416
}
417417

@@ -424,13 +424,13 @@ class DeclAndTypePrinter::Implementation
424424
printer.printValueTypeDecl(
425425
SD, /*bodyPrinter=*/
426426
[&]() {
427-
printMembers(SD->getMembers());
427+
printMembers(SD->getAllMembers());
428428
for (const auto *ed :
429429
owningPrinter.interopContext.getExtensionsForNominalType(SD)) {
430430
if (!cxx_translation::isExposableToCxx(ed->getGenericSignature()))
431431
continue;
432432

433-
printMembers(ed->getMembers());
433+
printMembers(ed->getAllMembers());
434434
}
435435
},
436436
owningPrinter);
@@ -450,7 +450,7 @@ class DeclAndTypePrinter::Implementation
450450
os << " (SWIFT_EXTENSION(" << ED->getModuleContext()->getName() << "))";
451451
printProtocols(ED->getLocalProtocols(ConformanceLookupKind::OnlyExplicit));
452452
os << "\n";
453-
printMembers(ED->getMembers());
453+
printMembers(ED->getAllMembers());
454454
os << "@end\n";
455455
}
456456

@@ -471,7 +471,7 @@ class DeclAndTypePrinter::Implementation
471471

472472
printProtocols(PD->getInheritedProtocols());
473473
os << "\n";
474-
printMembers(PD->getMembers());
474+
printMembers(PD->getAllMembers());
475475
os << "@end\n";
476476
}
477477

@@ -906,14 +906,14 @@ class DeclAndTypePrinter::Implementation
906906
os << " }\n"; // operator cases()'s closing bracket
907907
os << "\n";
908908

909-
printMembers(ED->getMembers());
909+
printMembers(ED->getAllMembers());
910910

911911
for (const auto *ext :
912912
owningPrinter.interopContext.getExtensionsForNominalType(ED)) {
913913
if (!cxx_translation::isExposableToCxx(ext->getGenericSignature()))
914914
continue;
915915

916-
printMembers(ext->getMembers());
916+
printMembers(ext->getAllMembers());
917917
}
918918
},
919919
owningPrinter);

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ class ModuleWriter {
350350
}
351351
}
352352

353-
bool forwardDeclareMemberTypes(DeclRange members, const Decl *container) {
353+
bool forwardDeclareMemberTypes(ArrayRef<Decl *> members,
354+
const Decl *container) {
354355
PrettyStackTraceDecl
355356
entry("printing forward declarations needed by members of", container);
356357
switch (container->getKind()) {
@@ -480,7 +481,7 @@ class ModuleWriter {
480481
if (!allRequirementsSatisfied)
481482
return false;
482483

483-
(void)forwardDeclareMemberTypes(CD->getMembers(), CD);
484+
(void)forwardDeclareMemberTypes(CD->getAllMembers(), CD);
484485
auto [it, inserted] =
485486
seenTypes.try_emplace(CD, EmissionState::NotYetDefined, false);
486487
if (outputLangMode == OutputLanguageMode::Cxx &&
@@ -515,10 +516,10 @@ class ModuleWriter {
515516
if (addImport(SD))
516517
return true;
517518
if (outputLangMode == OutputLanguageMode::Cxx) {
518-
(void)forwardDeclareMemberTypes(SD->getMembers(), SD);
519+
(void)forwardDeclareMemberTypes(SD->getAllMembers(), SD);
519520
for (const auto *ed :
520521
printer.getInteropContext().getExtensionsForNominalType(SD)) {
521-
(void)forwardDeclareMemberTypes(ed->getMembers(), SD);
522+
(void)forwardDeclareMemberTypes(ed->getAllMembers(), SD);
522523
}
523524
forwardDeclareCxxValueTypeIfNeeded(SD);
524525
}
@@ -545,7 +546,7 @@ class ModuleWriter {
545546
if (!allRequirementsSatisfied)
546547
return false;
547548

548-
if (!forwardDeclareMemberTypes(PD->getMembers(), PD))
549+
if (!forwardDeclareMemberTypes(PD->getAllMembers(), PD))
549550
return false;
550551

551552
seenTypes[PD] = { EmissionState::Defined, true };
@@ -572,7 +573,7 @@ class ModuleWriter {
572573
// This isn't rolled up into the previous set of requirements because
573574
// it /also/ prints forward declarations, and the header is a little
574575
// prettier if those are as close as possible to the necessary extension.
575-
if (!forwardDeclareMemberTypes(ED->getMembers(), ED))
576+
if (!forwardDeclareMemberTypes(ED->getAllMembers(), ED))
576577
return false;
577578

578579
os << '\n';
@@ -585,7 +586,7 @@ class ModuleWriter {
585586
return true;
586587

587588
if (outputLangMode == OutputLanguageMode::Cxx) {
588-
forwardDeclareMemberTypes(ED->getMembers(), ED);
589+
forwardDeclareMemberTypes(ED->getAllMembers(), ED);
589590
forwardDeclareCxxValueTypeIfNeeded(ED);
590591
}
591592

@@ -617,7 +618,7 @@ class ModuleWriter {
617618

618619
void write() {
619620
SmallVector<Decl *, 64> decls;
620-
M.getTopLevelDecls(decls);
621+
M.getTopLevelDeclsWithAuxiliaryDecls(decls);
621622
llvm::DenseSet<const ValueDecl *> removedValueDecls;
622623

623624
auto newEnd =
@@ -649,7 +650,7 @@ class ModuleWriter {
649650
if (!ext ||
650651
ext->getExtendedNominal() != M.getASTContext().getStringDecl())
651652
continue;
652-
for (auto *m : ext->getMembers()) {
653+
for (auto *m : ext->getAllMembers()) {
653654
if (auto *sd = dyn_cast<StructDecl>(m)) {
654655
if (sd->getBaseIdentifier().str() == "UTF8View" ||
655656
sd->getBaseIdentifier().str() == "Index") {
@@ -761,8 +762,8 @@ class ModuleWriter {
761762
// Break ties in extensions by putting smaller extensions last (in reverse
762763
// order).
763764
// FIXME: This will end up taking linear time.
764-
auto lhsMembers = cast<ExtensionDecl>(*lhs)->getMembers();
765-
auto rhsMembers = cast<ExtensionDecl>(*rhs)->getMembers();
765+
auto lhsMembers = cast<ExtensionDecl>(*lhs)->getAllMembers();
766+
auto rhsMembers = cast<ExtensionDecl>(*rhs)->getAllMembers();
766767
unsigned numLHSMembers = std::distance(lhsMembers.begin(),
767768
lhsMembers.end());
768769
unsigned numRHSMembers = std::distance(rhsMembers.begin(),
@@ -794,18 +795,19 @@ class ModuleWriter {
794795
// Still nothing? Fine, we'll pick the one with the alphabetically first
795796
// member instead.
796797
{
797-
auto mismatch =
798-
std::mismatch(cast<ExtensionDecl>(*lhs)->getMembers().begin(),
799-
cast<ExtensionDecl>(*lhs)->getMembers().end(),
800-
cast<ExtensionDecl>(*rhs)->getMembers().begin(),
801-
[] (const Decl *nextLHSDecl, const Decl *nextRHSDecl) {
802-
if (isa<ValueDecl>(nextLHSDecl) && isa<ValueDecl>(nextRHSDecl)) {
803-
return cast<ValueDecl>(nextLHSDecl)->getName() !=
804-
cast<ValueDecl>(nextRHSDecl)->getName();
805-
}
806-
return isa<ValueDecl>(nextLHSDecl) != isa<ValueDecl>(nextRHSDecl);
807-
});
808-
if (mismatch.first != cast<ExtensionDecl>(*lhs)->getMembers().end()) {
798+
auto mismatch = std::mismatch(
799+
cast<ExtensionDecl>(*lhs)->getAllMembers().begin(),
800+
cast<ExtensionDecl>(*lhs)->getAllMembers().end(),
801+
cast<ExtensionDecl>(*rhs)->getAllMembers().begin(),
802+
[](const Decl *nextLHSDecl, const Decl *nextRHSDecl) {
803+
if (isa<ValueDecl>(nextLHSDecl) && isa<ValueDecl>(nextRHSDecl)) {
804+
return cast<ValueDecl>(nextLHSDecl)->getName() !=
805+
cast<ValueDecl>(nextRHSDecl)->getName();
806+
}
807+
return isa<ValueDecl>(nextLHSDecl) != isa<ValueDecl>(nextRHSDecl);
808+
});
809+
if (mismatch.first !=
810+
cast<ExtensionDecl>(*lhs)->getAllMembers().end()) {
809811
auto *lhsMember = dyn_cast<ValueDecl>(*mismatch.first),
810812
*rhsMember = dyn_cast<ValueDecl>(*mismatch.second);
811813
if (!rhsMember && lhsMember)
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import SwiftParser
2+
import SwiftSyntax
3+
import SwiftSyntaxBuilder
4+
import SwiftSyntaxMacros
5+
6+
struct ObjCMemberFuncMacro: MemberMacro {
7+
static func expansion(
8+
of node: AttributeSyntax,
9+
providingMembersOf declaration: some DeclGroupSyntax,
10+
conformingTo protocols: [TypeSyntax],
11+
in context: some MacroExpansionContext
12+
) throws -> [DeclSyntax] {
13+
guard let decl = declaration.asProtocol(NamedDeclSyntax.self) else {
14+
return []
15+
}
16+
return ["@objc public func member_\(raw: decl.name.text)() {}"]
17+
}
18+
}
19+
20+
struct ObjCPeerFuncMacro: PeerMacro {
21+
static func expansion(
22+
of node: AttributeSyntax,
23+
providingPeersOf declaration: some DeclSyntaxProtocol,
24+
in context: some MacroExpansionContext
25+
) throws -> [DeclSyntax] {
26+
guard let decl = declaration.asProtocol(NamedDeclSyntax.self) else {
27+
return []
28+
}
29+
return ["@objc public func peer_\(raw: decl.name.text)() {}"]
30+
}
31+
}
32+
33+
struct ObjCFreestandingFuncMacro: DeclarationMacro {
34+
static func expansion(
35+
of node: some FreestandingMacroExpansionSyntax,
36+
in context: some MacroExpansionContext
37+
) throws -> [DeclSyntax] {
38+
return ["@objc public func member_freestanding() {}"]
39+
}
40+
}
41+
42+
struct ObjCFreestandingClassMacro: DeclarationMacro {
43+
static func expansion(
44+
of node: some FreestandingMacroExpansionSyntax,
45+
in context: some MacroExpansionContext
46+
) throws -> [DeclSyntax] {
47+
return ["""
48+
@objc public class MacroExpandedObjCClass: NSObject {
49+
@objc public func member() {}
50+
}
51+
"""]
52+
}
53+
}
54+
55+
struct CDeclFreestandingFuncMacro: DeclarationMacro {
56+
static func expansion(
57+
of node: some FreestandingMacroExpansionSyntax,
58+
in context: some MacroExpansionContext
59+
) throws -> [DeclSyntax] {
60+
return [#"@_cdecl("c_freestanding") public func cFreestanding() {}"#]
61+
}
62+
}
63+
64+
struct ObjCExtensionMacro: ExtensionMacro {
65+
static func expansion(
66+
of node: AttributeSyntax,
67+
attachedTo declaration: some DeclGroupSyntax,
68+
providingExtensionsOf type: some TypeSyntaxProtocol,
69+
conformingTo protocols: [TypeSyntax],
70+
in context: some MacroExpansionContext
71+
) throws -> [ExtensionDeclSyntax] {
72+
let decl: DeclSyntax = """
73+
extension \(type): MyObjCProtocol {
74+
public func objcRequirement() {}
75+
}
76+
"""
77+
return [decl.as(ExtensionDeclSyntax.self)!]
78+
}
79+
}
80+
81+
struct MemberFuncMacro: MemberMacro {
82+
static func expansion(
83+
of node: AttributeSyntax,
84+
providingMembersOf declaration: some DeclGroupSyntax,
85+
conformingTo protocols: [TypeSyntax],
86+
in context: some MacroExpansionContext
87+
) throws -> [DeclSyntax] {
88+
guard let decl = declaration.asProtocol(NamedDeclSyntax.self) else {
89+
return []
90+
}
91+
return ["public func member_\(raw: decl.name.text)() {}"]
92+
}
93+
}
94+
95+
struct PeerFuncMacro: PeerMacro {
96+
static func expansion(
97+
of node: AttributeSyntax,
98+
providingPeersOf declaration: some DeclSyntaxProtocol,
99+
in context: some MacroExpansionContext
100+
) throws -> [DeclSyntax] {
101+
guard let decl = declaration.asProtocol(NamedDeclSyntax.self) else {
102+
return []
103+
}
104+
return ["public func peer_\(raw: decl.name.text)() {}"]
105+
}
106+
}
107+
108+
struct CxxFreestandingFuncMacro: DeclarationMacro {
109+
static func expansion(
110+
of node: some FreestandingMacroExpansionSyntax,
111+
in context: some MacroExpansionContext
112+
) throws -> [DeclSyntax] {
113+
return ["public func cxxFreestanding() {}"]
114+
}
115+
}
116+
117+
struct CxxFreestandingStructMacro: DeclarationMacro {
118+
static func expansion(
119+
of node: some FreestandingMacroExpansionSyntax,
120+
in context: some MacroExpansionContext
121+
) throws -> [DeclSyntax] {
122+
return ["""
123+
public struct MacroExpandedStruct {
124+
private let x: Int = 0
125+
public func member() {}
126+
}
127+
"""]
128+
}
129+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/objc_cxx_macro_definitions.swift -g -no-toolchain-stdlib-rpath
5+
// RUN: %target-build-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser -swift-version 5
6+
// RUN: %target-codesign %t/main
7+
8+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk) -typecheck -swift-version 5 -parse-as-library -clang-header-expose-decls=all-public -emit-clang-header-path %t/MacroUser.h -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser
9+
// RUN: %FileCheck --check-prefix CHECK %s < %t/MacroUser.h
10+
11+
@attached(member, names: prefixed(member_))
12+
public macro MemberFunc() = #externalMacro(module: "MacroDefinition", type: "MemberFuncMacro")
13+
14+
@attached(peer, names: prefixed(peer_))
15+
public macro PeerFunc() = #externalMacro(module: "MacroDefinition", type: "PeerFuncMacro")
16+
17+
@freestanding(declaration, names: named(cxxFreestanding))
18+
public macro CxxFreestandingFunc() = #externalMacro(module: "MacroDefinition", type: "CxxFreestandingFuncMacro")
19+
20+
@freestanding(declaration, names: named(MacroExpandedStruct))
21+
public macro CxxFreestandingStruct() = #externalMacro(module: "MacroDefinition", type: "CxxFreestandingStructMacro")
22+
23+
// ---
24+
25+
// CHECK: class SWIFT_SYMBOL("s:9MacroUser0A14ExpandedStructV") MacroExpandedStruct final {
26+
// CHECK-DAG: SWIFT_INLINE_THUNK void member() const SWIFT_SYMBOL("s:9MacroUser0A14ExpandedStructV6memberyyF");
27+
#CxxFreestandingStruct
28+
29+
// CHECK: class SWIFT_SYMBOL("s:9MacroUser10SomeStructV") SomeStruct final {
30+
@MemberFunc
31+
public struct SomeStruct {
32+
private var someProperty: Int = 0
33+
34+
@PeerFunc
35+
public func someMethod() {}
36+
37+
#CxxFreestandingFunc
38+
39+
// CHECK-DAG: SWIFT_INLINE_THUNK void peer_someMethod() const SWIFT_SYMBOL("s:9MacroUser10SomeStructV15peer_someMethodyyF");
40+
// CHECK-DAG: SWIFT_INLINE_THUNK void someMethod() const SWIFT_SYMBOL("s:9MacroUser10SomeStructV10someMethodyyF");
41+
// CHECK-DAG: SWIFT_INLINE_THUNK void cxxFreestanding() const SWIFT_SYMBOL("s:9MacroUser10SomeStructV15cxxFreestandingyyF");
42+
// CHECK-DAG: SWIFT_INLINE_THUNK void member_SomeStruct() const SWIFT_SYMBOL("s:9MacroUser10SomeStructV07member_cD0yyF");
43+
}

0 commit comments

Comments
 (0)