Skip to content

Commit 31d4f66

Browse files
committed
[Macros] Support function body macros on closures.
1 parent a02633a commit 31d4f66

File tree

16 files changed

+386
-39
lines changed

16 files changed

+386
-39
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,18 @@ class ASTMangler : public Mangler {
408408
std::string mangleMacroExpansion(const FreestandingMacroExpansion *expansion);
409409
std::string mangleAttachedMacroExpansion(
410410
const Decl *decl, CustomAttr *attr, MacroRole role);
411+
std::string mangleAttachedMacroExpansion(
412+
ClosureExpr *attachedTo, CustomAttr *attr, MacroDecl *macro);
411413

412414
void appendMacroExpansion(const FreestandingMacroExpansion *expansion);
413415
void appendMacroExpansionContext(SourceLoc loc, DeclContext *origDC,
414-
const FreestandingMacroExpansion *expansion);
416+
Identifier macroName,
417+
unsigned discriminator);
418+
419+
void appendMacroExpansion(ClosureExpr *attachedTo,
420+
CustomAttr *attr,
421+
MacroDecl *macro);
422+
415423
void appendMacroExpansionOperator(
416424
StringRef macroName, MacroRole role, unsigned discriminator);
417425

include/swift/AST/AnyFunctionRef.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,54 @@ class AnyFunctionRef {
243243
llvm_unreachable("unexpected AnyFunctionRef representation");
244244
}
245245

246+
DeclAttributes getDeclAttributes() const {
247+
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
248+
return afd->getExpandedAttrs();
249+
}
250+
251+
if (auto ace = TheFunction.dyn_cast<AbstractClosureExpr *>()) {
252+
if (auto *ce = dyn_cast<ClosureExpr>(ace)) {
253+
return ce->getAttrs();
254+
}
255+
}
256+
257+
return DeclAttributes();
258+
}
259+
260+
MacroDecl *getResolvedMacro(CustomAttr *attr) const {
261+
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
262+
return afd->getResolvedMacro(attr);
263+
}
264+
265+
if (auto ace = TheFunction.dyn_cast<AbstractClosureExpr *>()) {
266+
if (auto *ce = dyn_cast<ClosureExpr>(ace)) {
267+
return ce->getResolvedMacro(attr);
268+
}
269+
}
270+
271+
return nullptr;
272+
}
273+
274+
using MacroCallback = llvm::function_ref<void(CustomAttr *, MacroDecl *)>;
275+
276+
void
277+
forEachAttachedMacro(MacroRole role,
278+
MacroCallback macroCallback) const {
279+
auto attrs = getDeclAttributes();
280+
for (auto customAttrConst : attrs.getAttributes<CustomAttr>()) {
281+
auto customAttr = const_cast<CustomAttr *>(customAttrConst);
282+
auto *macroDecl = getResolvedMacro(customAttr);
283+
284+
if (!macroDecl)
285+
continue;
286+
287+
if (!macroDecl->getMacroRoles().contains(role))
288+
continue;
289+
290+
macroCallback(customAttr, macroDecl);
291+
}
292+
}
293+
246294
friend bool operator==(AnyFunctionRef lhs, AnyFunctionRef rhs) {
247295
return lhs.TheFunction == rhs.TheFunction;
248296
}

include/swift/AST/Expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4305,6 +4305,8 @@ class ClosureExpr : public AbstractClosureExpr {
43054305
BraceStmt *getBody() const { return Body; }
43064306
void setBody(BraceStmt *S) { Body = S; }
43074307

4308+
BraceStmt *getExpandedBody();
4309+
43084310
DeclAttributes &getAttrs() { return Attributes; }
43094311
const DeclAttributes &getAttrs() const { return Attributes; }
43104312

@@ -4422,6 +4424,10 @@ class ClosureExpr : public AbstractClosureExpr {
44224424
return ExplicitResultTypeAndBodyState.getPointer()->getTypeRepr();
44234425
}
44244426

4427+
/// Returns the resolved macro for the given custom attribute
4428+
/// attached to this closure expression.
4429+
MacroDecl *getResolvedMacro(CustomAttr *customAttr);
4430+
44254431
/// Determine whether the closure has a single expression for its
44264432
/// body.
44274433
///

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4708,7 +4708,7 @@ class ExpandPreambleMacroRequest
47084708

47094709
class ExpandBodyMacroRequest
47104710
: public SimpleRequest<ExpandBodyMacroRequest,
4711-
std::optional<unsigned>(AbstractFunctionDecl *),
4711+
std::optional<unsigned>(AnyFunctionRef),
47124712
RequestFlags::Cached> {
47134713
public:
47144714
using SimpleRequest::SimpleRequest;
@@ -4717,7 +4717,7 @@ class ExpandBodyMacroRequest
47174717
friend SimpleRequest;
47184718

47194719
std::optional<unsigned> evaluate(Evaluator &evaluator,
4720-
AbstractFunctionDecl *fn) const;
4720+
AnyFunctionRef fn) const;
47214721

47224722
public:
47234723
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ SWIFT_REQUEST(TypeChecker, ExpandPreambleMacroRequest,
531531
ArrayRef<unsigned>(AbstractFunctionDecl *),
532532
Cached, NoLocationInfo)
533533
SWIFT_REQUEST(TypeChecker, ExpandBodyMacroRequest,
534-
std::optional<unsigned>(AbstractFunctionDecl *),
534+
std::optional<unsigned>(AnyFunctionRef),
535535
Cached, NoLocationInfo)
536536
SWIFT_REQUEST(TypeChecker, LocalDiscriminatorsRequest,
537537
unsigned(DeclContext *),

lib/AST/ASTMangler.cpp

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4759,7 +4759,8 @@ static Identifier encodeLocalPrecheckedDiscriminator(
47594759

47604760
void ASTMangler::appendMacroExpansionContext(
47614761
SourceLoc loc, DeclContext *origDC,
4762-
const FreestandingMacroExpansion *expansion
4762+
Identifier macroName,
4763+
unsigned macroDiscriminator
47634764
) {
47644765
origDC = MacroDiscriminatorContext::getInnermostMacroContext(origDC);
47654766
BaseEntitySignature nullBase(nullptr);
@@ -4768,9 +4769,9 @@ void ASTMangler::appendMacroExpansionContext(
47684769
if (auto outermostLocalDC = getOutermostLocalContext(origDC)) {
47694770
auto innermostNonlocalDC = outermostLocalDC->getParent();
47704771
appendContext(innermostNonlocalDC, nullBase, StringRef());
4771-
Identifier name = expansion->getMacroName().getBaseIdentifier();
4772+
Identifier name = macroName;
47724773
ASTContext &ctx = origDC->getASTContext();
4773-
unsigned discriminator = expansion->getDiscriminator();
4774+
unsigned discriminator = macroDiscriminator;
47744775
name = encodeLocalPrecheckedDiscriminator(ctx, name, discriminator);
47754776
appendIdentifier(name.str());
47764777
} else {
@@ -4875,7 +4876,10 @@ void ASTMangler::appendMacroExpansionContext(
48754876
return appendMacroExpansionLoc();
48764877

48774878
// Append our own context and discriminator.
4878-
appendMacroExpansionContext(outerExpansionLoc, origDC, expansion);
4879+
appendMacroExpansionContext(
4880+
outerExpansionLoc, origDC,
4881+
macroName,
4882+
macroDiscriminator);
48794883
appendMacroExpansionOperator(
48804884
baseName.userFacingName(), role, discriminator);
48814885
}
@@ -4902,16 +4906,14 @@ void ASTMangler::appendMacroExpansionOperator(
49024906
}
49034907

49044908
static StringRef getPrivateDiscriminatorIfNecessary(
4905-
const MacroExpansionExpr *expansion) {
4906-
auto dc = MacroDiscriminatorContext::getInnermostMacroContext(
4907-
expansion->getDeclContext());
4908-
auto decl = dc->getAsDecl();
4909+
const DeclContext *macroDC) {
4910+
auto decl = macroDC->getAsDecl();
49094911
if (decl && !decl->isOutermostPrivateOrFilePrivateScope())
49104912
return StringRef();
49114913

49124914
// Mangle non-local private declarations with a textual discriminator
49134915
// based on their enclosing file.
4914-
auto topLevelSubcontext = dc->getModuleScopeContext();
4916+
auto topLevelSubcontext = macroDC->getModuleScopeContext();
49154917
SourceFile *sf = dyn_cast<SourceFile>(topLevelSubcontext);
49164918
if (!sf)
49174919
return StringRef();
@@ -4927,6 +4929,13 @@ static StringRef getPrivateDiscriminatorIfNecessary(
49274929
return discriminator.str();
49284930
}
49294931

4932+
static StringRef getPrivateDiscriminatorIfNecessary(
4933+
const MacroExpansionExpr *expansion) {
4934+
auto dc = MacroDiscriminatorContext::getInnermostMacroContext(
4935+
expansion->getDeclContext());
4936+
return getPrivateDiscriminatorIfNecessary(dc);
4937+
}
4938+
49304939
static StringRef getPrivateDiscriminatorIfNecessary(
49314940
const FreestandingMacroExpansion *expansion) {
49324941
switch (expansion->getFreestandingMacroKind()) {
@@ -4943,7 +4952,8 @@ void
49434952
ASTMangler::appendMacroExpansion(const FreestandingMacroExpansion *expansion) {
49444953
appendMacroExpansionContext(expansion->getPoundLoc(),
49454954
expansion->getDeclContext(),
4946-
expansion);
4955+
expansion->getMacroName().getBaseIdentifier(),
4956+
expansion->getDiscriminator());
49474957
auto privateDiscriminator = getPrivateDiscriminatorIfNecessary(expansion);
49484958
if (!privateDiscriminator.empty()) {
49494959
appendIdentifier(privateDiscriminator);
@@ -4955,6 +4965,42 @@ ASTMangler::appendMacroExpansion(const FreestandingMacroExpansion *expansion) {
49554965
expansion->getDiscriminator());
49564966
}
49574967

4968+
void ASTMangler::appendMacroExpansion(ClosureExpr *attachedTo,
4969+
CustomAttr *attr,
4970+
MacroDecl *macro) {
4971+
auto &ctx = attachedTo->getASTContext();
4972+
auto discriminator =
4973+
ctx.getNextMacroDiscriminator(attachedTo,
4974+
macro->getBaseName());
4975+
4976+
appendMacroExpansionContext(
4977+
attr->getLocation(),
4978+
attachedTo,
4979+
macro->getBaseName().getIdentifier(),
4980+
discriminator);
4981+
4982+
auto privateDiscriminator =
4983+
getPrivateDiscriminatorIfNecessary(attachedTo);
4984+
if (!privateDiscriminator.empty()) {
4985+
appendIdentifier(privateDiscriminator);
4986+
appendOperator("Ll");
4987+
}
4988+
4989+
appendMacroExpansionOperator(
4990+
macro->getBaseName().userFacingName(),
4991+
MacroRole::Body,
4992+
discriminator);
4993+
}
4994+
4995+
std::string
4996+
ASTMangler::mangleAttachedMacroExpansion(ClosureExpr *attachedTo,
4997+
CustomAttr *attr,
4998+
MacroDecl *macro) {
4999+
beginMangling();
5000+
appendMacroExpansion(attachedTo, attr, macro);
5001+
return finalize();
5002+
}
5003+
49585004
std::string
49595005
ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
49605006
beginMangling();

lib/AST/ASTScopeCreation.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,22 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
309309
break;
310310
}
311311
case MacroRole::Body: {
312-
// Use the end location of the function decl itself as the parentLoc
313-
// for the new function body scope. This is different from the end
314-
// location of the original source range, which is after the end of the
315-
// function decl.
316312
auto expansion = SF->getMacroExpansion();
317-
parentLoc = expansion.getEndLoc();
318-
bodyForDecl = cast<AbstractFunctionDecl>(expansion.get<Decl *>());
313+
if (expansion.is<Decl *>()) {
314+
// Use the end location of the function decl itself as the parentLoc
315+
// for the new function body scope. This is different from the end
316+
// location of the original source range, which is after the end of the
317+
// function decl.
318+
bodyForDecl = cast<AbstractFunctionDecl>(expansion.get<Decl *>());
319+
parentLoc = expansion.getEndLoc();
320+
break;
321+
}
322+
323+
// Otherwise, we have a closure body macro.
324+
auto insertionRange = SF->getMacroInsertionRange();
325+
parentLoc = insertionRange.End;
326+
if (insertionRange.Start != insertionRange.End)
327+
parentLoc = parentLoc.getAdvancedLoc(-1);
319328
break;
320329
}
321330
}

lib/AST/Expr.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/Basic/Assertions.h"
1919
#include "swift/Basic/Statistic.h"
2020
#include "swift/Basic/Unicode.h"
21+
#include "swift/Basic/SourceManager.h"
2122
#include "swift/AST/ASTContext.h"
2223
#include "swift/AST/ASTVisitor.h"
2324
#include "swift/AST/Decl.h" // FIXME: Bad dependency
@@ -2016,6 +2017,29 @@ BraceStmt * AbstractClosureExpr::getBody() const {
20162017
llvm_unreachable("Unknown closure expression");
20172018
}
20182019

2020+
BraceStmt *ClosureExpr::getExpandedBody() {
2021+
auto &ctx = getASTContext();
2022+
2023+
// Expand a body macro, if there is one.
2024+
BraceStmt *macroExpandedBody = nullptr;
2025+
if (auto bufferID = evaluateOrDefault(
2026+
ctx.evaluator,
2027+
ExpandBodyMacroRequest{this},
2028+
std::nullopt)) {
2029+
CharSourceRange bufferRange = ctx.SourceMgr.getRangeForBuffer(*bufferID);
2030+
auto bufferStart = bufferRange.getStart();
2031+
auto module = getParentModule();
2032+
auto macroSourceFile = module->getSourceFileContainingLocation(bufferStart);
2033+
2034+
if (macroSourceFile->getTopLevelItems().size() == 1) {
2035+
auto stmt = macroSourceFile->getTopLevelItems()[0].dyn_cast<Stmt *>();
2036+
macroExpandedBody = dyn_cast<BraceStmt>(stmt);
2037+
}
2038+
}
2039+
2040+
return macroExpandedBody;
2041+
}
2042+
20192043
bool AbstractClosureExpr::bodyHasExplicitReturnStmt() const {
20202044
return AnyFunctionRef(const_cast<AbstractClosureExpr *>(this))
20212045
.bodyHasExplicitReturnStmt();
@@ -2175,6 +2199,17 @@ void ClosureExpr::setExplicitResultType(Type ty) {
21752199
->setType(MetatypeType::get(ty));
21762200
}
21772201

2202+
MacroDecl *
2203+
ClosureExpr::getResolvedMacro(CustomAttr *customAttr) {
2204+
auto &ctx = getASTContext();
2205+
auto declRef = evaluateOrDefault(
2206+
ctx.evaluator,
2207+
ResolveMacroRequest{customAttr, this},
2208+
ConcreteDeclRef());
2209+
2210+
return dyn_cast_or_null<MacroDecl>(declRef.getDecl());
2211+
}
2212+
21782213
FORWARD_SOURCE_LOCS_TO(AutoClosureExpr, Body)
21792214

21802215
void AutoClosureExpr::setBody(Expr *E) {

lib/AST/TypeCheckRequests.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,19 +2681,17 @@ void ExpandPreambleMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
26812681
//----------------------------------------------------------------------------//
26822682

26832683
void ExpandBodyMacroRequest::diagnoseCycle(DiagnosticEngine &diags) const {
2684-
auto decl = std::get<0>(getStorage());
2685-
diags.diagnose(decl->getLoc(),
2686-
diag::macro_expand_circular_reference_entity,
2687-
"body",
2688-
decl->getName());
2684+
auto fn = std::get<0>(getStorage());
2685+
diags.diagnose(fn.getLoc(),
2686+
diag::macro_expand_circular_reference_unnamed,
2687+
"body");
26892688
}
26902689

26912690
void ExpandBodyMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
2692-
auto decl = std::get<0>(getStorage());
2693-
diags.diagnose(decl->getLoc(),
2694-
diag::macro_expand_circular_reference_entity_through,
2695-
"body",
2696-
decl->getName());
2691+
auto fn = std::get<0>(getStorage());
2692+
diags.diagnose(fn.getLoc(),
2693+
diag::macro_expand_circular_reference_unnamed_through,
2694+
"body");
26972695
}
26982696

26992697
//----------------------------------------------------------------------------//

lib/ASTGen/Sources/MacroEvaluation/Macros.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ func expandAttachedMacro(
589589
let declarationNode = findSyntaxNodeInSourceFile(
590590
sourceFilePtr: declarationSourceFilePtr,
591591
sourceLocationPtr: declarationSourceLocPointer,
592-
type: DeclSyntax.self
592+
type: Syntax.self
593593
)
594594
else {
595595
return 1
@@ -657,7 +657,7 @@ func expandAttachedMacroImpl(
657657
customAttrSourceFilePtr: UnsafePointer<ExportedSourceFile>,
658658
customAttrNode: AttributeSyntax,
659659
declarationSourceFilePtr: UnsafePointer<ExportedSourceFile>,
660-
attachedTo declarationNode: DeclSyntax,
660+
attachedTo declarationNode: Syntax,
661661
parentDeclSourceFilePtr: UnsafePointer<ExportedSourceFile>?,
662662
parentDeclNode: DeclSyntax?
663663
) -> String? {
@@ -689,7 +689,7 @@ func expandAttachedMacroImpl(
689689
)!
690690

691691
let declSyntax = PluginMessage.Syntax(
692-
syntax: Syntax(declarationNode),
692+
syntax: declarationNode,
693693
in: declarationSourceFilePtr
694694
)!
695695

0 commit comments

Comments
 (0)