Skip to content

Commit e5ba389

Browse files
committed
[Macros] Allow one attached macro declaration to fulfill multiple roles.
1 parent f1742fd commit e5ba389

File tree

6 files changed

+88
-35
lines changed

6 files changed

+88
-35
lines changed

include/swift/AST/SourceFile.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,13 @@ class SourceFile final : public FileUnit {
511511
/// macro.
512512
CustomAttr *getAttachedMacroAttribute() const;
513513

514+
/// For source files created to hold the source code created by expanding
515+
/// an attached macro, this is the macro role that the expansion fulfills.
516+
///
517+
/// \Returns the fulfilled macro role, or \c None if this source file is not
518+
/// for a macro expansion.
519+
Optional<MacroRole> getFulfilledMacroRole() const;
520+
514521
/// When this source file is enclosed within another source file, for example
515522
/// because it describes a macro expansion, return the source file it was
516523
/// enclosed in.

lib/AST/Module.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,34 @@ CustomAttr *SourceFile::getAttachedMacroAttribute() const {
896896
return genInfo.attachedMacroCustomAttr;
897897
}
898898

899+
Optional<MacroRole> SourceFile::getFulfilledMacroRole() const {
900+
if (Kind != SourceFileKind::MacroExpansion)
901+
return None;
902+
903+
auto genInfo =
904+
*getASTContext().SourceMgr.getGeneratedSourceInfo(*getBufferID());
905+
switch (genInfo.kind) {
906+
case GeneratedSourceInfo::ExpressionMacroExpansion:
907+
return MacroRole::Expression;
908+
909+
case GeneratedSourceInfo::FreestandingDeclMacroExpansion:
910+
return MacroRole::FreestandingDeclaration;
911+
912+
case GeneratedSourceInfo::AccessorMacroExpansion:
913+
return MacroRole::Accessor;
914+
915+
case GeneratedSourceInfo::MemberAttributeMacroExpansion:
916+
return MacroRole::MemberAttribute;
917+
918+
case GeneratedSourceInfo::SynthesizedMemberMacroExpansion:
919+
return MacroRole::SynthesizedMembers;
920+
921+
case GeneratedSourceInfo::ReplacedFunctionBody:
922+
case GeneratedSourceInfo::PrettyPrinted:
923+
return None;
924+
}
925+
}
926+
899927
SourceFile *SourceFile::getEnclosingSourceFile() const {
900928
auto macroExpansion = getMacroExpansion();
901929
if (!macroExpansion)

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ struct ExportedMacro {
3131
var macro: Macro.Type
3232
}
3333

34+
enum MacroRole: UInt8 {
35+
case Expression = 0x01
36+
case FreestandingDeclaration = 0x02
37+
case Accessor = 0x04
38+
case MemberAttribute = 0x08
39+
case SynthesizedMembers = 0x10
40+
}
41+
3442
/// Resolve a reference to type metadata into a macro, if posible.
3543
///
3644
/// Returns an unmanaged pointer to an ExportedMacro instance that describes
@@ -262,6 +270,7 @@ private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
262270
func expandAttachedMacro(
263271
diagEnginePtr: UnsafeMutablePointer<UInt8>,
264272
macroPtr: UnsafeRawPointer,
273+
rawMacroRole: UInt8,
265274
customAttrSourceFilePtr: UnsafeRawPointer,
266275
customAttrSourceLocPointer: UnsafePointer<UInt8>?,
267276
declarationSourceFilePtr: UnsafeRawPointer,
@@ -297,6 +306,7 @@ func expandAttachedMacro(
297306
// Get the macro.
298307
let macroPtr = macroPtr.bindMemory(to: ExportedMacro.self, capacity: 1)
299308
let macro = macroPtr.pointee.macro
309+
let macroRole = MacroRole(rawValue: rawMacroRole)
300310

301311
// FIXME: Which source file? I don't know! This should go.
302312
let declarationSourceFilePtr = declarationSourceFilePtr.bindMemory(
@@ -310,8 +320,8 @@ func expandAttachedMacro(
310320

311321
var evaluatedSyntaxStr: String
312322
do {
313-
switch macro {
314-
case let attachedMacro as AccessorDeclarationMacro.Type:
323+
switch (macro, macroRole) {
324+
case (let attachedMacro as AccessorDeclarationMacro.Type, .Accessor):
315325
let accessors = try attachedMacro.expansion(
316326
of: customAttrNode, attachedTo: declarationNode, in: &context
317327
)
@@ -321,7 +331,7 @@ func expandAttachedMacro(
321331
$0.withoutTrivia().description
322332
}.joined(separator: "\n\n")
323333

324-
case let attachedMacro as MemberAttributeMacro.Type:
334+
case (let attachedMacro as MemberAttributeMacro.Type, .MemberAttribute):
325335
// Dig out the node for the parent declaration of the to-expand
326336
// declaration. Only member attribute macros need this.
327337
guard let parentDeclNode = findSyntaxNodeInSourceFile(
@@ -344,7 +354,7 @@ func expandAttachedMacro(
344354
$0.withoutTrivia().description
345355
}.joined(separator: " ")
346356

347-
case let attachedMacro as MemberDeclarationMacro.Type:
357+
case (let attachedMacro as MemberDeclarationMacro.Type, .SynthesizedMembers):
348358
let members = try attachedMacro.expansion(
349359
of: customAttrNode,
350360
attachedTo: declarationNode,

lib/Sema/TypeCheckMacros.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern "C" ptrdiff_t swift_ASTGen_evaluateMacro(
4444

4545
extern "C" ptrdiff_t swift_ASTGen_expandAttachedMacro(
4646
void *diagEngine, void *macro,
47+
uint32_t rawMacroRole,
4748
void *customAttrSourceFile,
4849
const void *customAttrSourceLocation,
4950
void *declarationSourceFile,
@@ -366,7 +367,8 @@ bool ExpandSynthesizedMemberMacroRequest::evaluate(Evaluator &evaluator,
366367

367368
/// Determine whether the given source file is from an expansion of the given
368369
/// macro.
369-
static bool isFromExpansionOfMacro(SourceFile *sourceFile, MacroDecl *macro) {
370+
static bool isFromExpansionOfMacro(SourceFile *sourceFile, MacroDecl *macro,
371+
MacroRole role) {
370372
while (sourceFile) {
371373
auto expansion = sourceFile->getMacroExpansion();
372374
if (!expansion)
@@ -391,7 +393,8 @@ static bool isFromExpansionOfMacro(SourceFile *sourceFile, MacroDecl *macro) {
391393
if (!macroDecl)
392394
return false;
393395

394-
return macroDecl == macro;
396+
return macroDecl == macro &&
397+
sourceFile->getFulfilledMacroRole() == role;
395398
} else {
396399
llvm_unreachable("Unknown macro expansion node kind");
397400
}
@@ -418,7 +421,7 @@ Expr *swift::expandMacroExpr(
418421

419422
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
420423

421-
if (isFromExpansionOfMacro(sourceFile, macro)) {
424+
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
422425
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
423426
return nullptr;
424427
}
@@ -599,7 +602,7 @@ bool swift::expandFreestandingDeclarationMacro(
599602
assert(macro->getMacroRoles()
600603
.contains(MacroRole::FreestandingDeclaration));
601604

602-
if (isFromExpansionOfMacro(sourceFile, macro)) {
605+
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::FreestandingDeclaration)) {
603606
med->diagnose(diag::macro_recursive, macro->getName());
604607
return false;
605608
}
@@ -765,8 +768,8 @@ void swift::expandAccessors(
765768
// Evaluate the macro.
766769
NullTerminatedStringRef evaluatedSource;
767770

768-
if (isFromExpansionOfMacro(attrSourceFile, macro) ||
769-
isFromExpansionOfMacro(declSourceFile, macro)) {
771+
if (isFromExpansionOfMacro(attrSourceFile, macro, MacroRole::Accessor) ||
772+
isFromExpansionOfMacro(declSourceFile, macro, MacroRole::Accessor)) {
770773
storage->diagnose(diag::macro_recursive, macro->getName());
771774
return;
772775
}
@@ -831,6 +834,7 @@ void swift::expandAccessors(
831834
swift_ASTGen_expandAttachedMacro(
832835
&ctx.Diags,
833836
externalDef.opaqueHandle,
837+
static_cast<uint32_t>(MacroRole::Accessor),
834838
astGenAttrSourceFile, attr->AtLoc.getOpaquePointerValue(),
835839
astGenDeclSourceFile, searchDecl->getStartLoc().getOpaquePointerValue(),
836840
/*parentDeclSourceFile*/nullptr, /*parentDeclLoc*/nullptr,
@@ -943,8 +947,8 @@ bool swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member) {
943947
// Evaluate the macro.
944948
NullTerminatedStringRef evaluatedSource;
945949

946-
if (isFromExpansionOfMacro(attrSourceFile, macro) ||
947-
isFromExpansionOfMacro(declSourceFile, macro)) {
950+
if (isFromExpansionOfMacro(attrSourceFile, macro, MacroRole::MemberAttribute) ||
951+
isFromExpansionOfMacro(declSourceFile, macro, MacroRole::MemberAttribute)) {
948952
member->diagnose(diag::macro_recursive, macro->getName());
949953
return false;
950954
}
@@ -1013,6 +1017,7 @@ bool swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member) {
10131017
swift_ASTGen_expandAttachedMacro(
10141018
&ctx.Diags,
10151019
externalDef.opaqueHandle,
1020+
static_cast<uint32_t>(MacroRole::MemberAttribute),
10161021
astGenAttrSourceFile, attr->AtLoc.getOpaquePointerValue(),
10171022
astGenDeclSourceFile, searchDecl->getStartLoc().getOpaquePointerValue(),
10181023
astGenParentDeclSourceFile, parentDecl->getStartLoc().getOpaquePointerValue(),
@@ -1127,8 +1132,8 @@ bool swift::expandSynthesizedMembers(CustomAttr *attr, MacroDecl *macro,
11271132
// Evaluate the macro.
11281133
NullTerminatedStringRef evaluatedSource;
11291134

1130-
if (isFromExpansionOfMacro(attrSourceFile, macro) ||
1131-
isFromExpansionOfMacro(declSourceFile, macro)) {
1135+
if (isFromExpansionOfMacro(attrSourceFile, macro, MacroRole::SynthesizedMembers) ||
1136+
isFromExpansionOfMacro(declSourceFile, macro, MacroRole::SynthesizedMembers)) {
11321137
decl->diagnose(diag::macro_recursive, macro->getName());
11331138
return false;
11341139
}
@@ -1189,6 +1194,7 @@ bool swift::expandSynthesizedMembers(CustomAttr *attr, MacroDecl *macro,
11891194
swift_ASTGen_expandAttachedMacro(
11901195
&ctx.Diags,
11911196
externalDef.opaqueHandle,
1197+
static_cast<uint32_t>(MacroRole::SynthesizedMembers),
11921198
astGenAttrSourceFile, attr->AtLoc.getOpaquePointerValue(),
11931199
astGenDeclSourceFile, decl->getStartLoc().getOpaquePointerValue(),
11941200
/*parentDeclSourceFile*/nullptr, /*parentDeclLoc*/nullptr,

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,9 @@ public struct WrapAllProperties: MemberAttributeMacro {
274274
}
275275
}
276276

277-
public struct TypeWrapperMacro: MemberAttributeMacro {
277+
public struct TypeWrapperMacro {}
278+
279+
extension TypeWrapperMacro: MemberAttributeMacro {
278280
public static func expansion(
279281
of node: AttributeSyntax,
280282
attachedTo decl: DeclSyntax,
@@ -303,6 +305,23 @@ public struct TypeWrapperMacro: MemberAttributeMacro {
303305
}
304306
}
305307

308+
extension TypeWrapperMacro: MemberDeclarationMacro {
309+
public static func expansion(
310+
of node: AttributeSyntax,
311+
attachedTo decl: DeclSyntax,
312+
in context: inout MacroExpansionContext
313+
) throws -> [DeclSyntax] {
314+
let storageVariable: VariableDeclSyntax =
315+
"""
316+
private var _storage = _Storage()
317+
"""
318+
319+
return [
320+
DeclSyntax(storageVariable),
321+
]
322+
}
323+
}
324+
306325
public struct AccessViaStorageMacro: AccessorDeclarationMacro {
307326
public static func expansion(
308327
of node: AttributeSyntax,
@@ -327,20 +346,3 @@ public struct AccessViaStorageMacro: AccessorDeclarationMacro {
327346
]
328347
}
329348
}
330-
331-
public struct TypeWrapperStorageMacro: MemberDeclarationMacro {
332-
public static func expansion(
333-
of node: AttributeSyntax,
334-
attachedTo decl: DeclSyntax,
335-
in context: inout MacroExpansionContext
336-
) throws -> [DeclSyntax] {
337-
let storageVariable: VariableDeclSyntax =
338-
"""
339-
private var _storage = _Storage()
340-
"""
341-
342-
return [
343-
DeclSyntax(storageVariable),
344-
]
345-
}
346-
}

test/Macros/composed_macro.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
// FIXME: Swift parser is not enabled on Linux CI yet.
1010
// REQUIRES: OS=macosx
1111

12-
@attached(memberAttributes) macro myTypeWrapper() = #externalMacro(module: "MacroDefinition", type: "TypeWrapperMacro")
13-
@attached(synthesizedMembers) macro typeWrapperStorage() = #externalMacro(module: "MacroDefinition", type: "TypeWrapperStorageMacro")
12+
@attached(memberAttributes)
13+
@attached(synthesizedMembers)
14+
macro myTypeWrapper() = #externalMacro(module: "MacroDefinition", type: "TypeWrapperMacro")
1415
@attached(accessor) macro accessViaStorage() = #externalMacro(module: "MacroDefinition", type: "AccessViaStorageMacro")
1516

1617
struct _Storage {
@@ -22,7 +23,6 @@ struct _Storage {
2223
}
2324
}
2425

25-
@typeWrapperStorage
2626
@myTypeWrapper
2727
struct S {
2828
var x: Int

0 commit comments

Comments
 (0)