Skip to content

Commit e959f84

Browse files
committed
[Macros] Support function body macros on closures.
1 parent 737b5ec commit e959f84

File tree

16 files changed

+385
-39
lines changed

16 files changed

+385
-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
@@ -4672,7 +4672,7 @@ class ExpandPreambleMacroRequest
46724672

46734673
class ExpandBodyMacroRequest
46744674
: public SimpleRequest<ExpandBodyMacroRequest,
4675-
std::optional<unsigned>(AbstractFunctionDecl *),
4675+
std::optional<unsigned>(AnyFunctionRef),
46764676
RequestFlags::Cached> {
46774677
public:
46784678
using SimpleRequest::SimpleRequest;
@@ -4681,7 +4681,7 @@ class ExpandBodyMacroRequest
46814681
friend SimpleRequest;
46824682

46834683
std::optional<unsigned> evaluate(Evaluator &evaluator,
4684-
AbstractFunctionDecl *fn) const;
4684+
AnyFunctionRef fn) const;
46854685

46864686
public:
46874687
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ SWIFT_REQUEST(TypeChecker, ExpandPreambleMacroRequest,
527527
ArrayRef<unsigned>(AbstractFunctionDecl *),
528528
Cached, NoLocationInfo)
529529
SWIFT_REQUEST(TypeChecker, ExpandBodyMacroRequest,
530-
std::optional<unsigned>(AbstractFunctionDecl *),
530+
std::optional<unsigned>(AnyFunctionRef),
531531
Cached, NoLocationInfo)
532532
SWIFT_REQUEST(TypeChecker, LocalDiscriminatorsRequest,
533533
unsigned(DeclContext *),

lib/AST/ASTMangler.cpp

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

47584758
void ASTMangler::appendMacroExpansionContext(
47594759
SourceLoc loc, DeclContext *origDC,
4760-
const FreestandingMacroExpansion *expansion
4760+
Identifier macroName,
4761+
unsigned macroDiscriminator
47614762
) {
47624763
origDC = MacroDiscriminatorContext::getInnermostMacroContext(origDC);
47634764
BaseEntitySignature nullBase(nullptr);
@@ -4766,9 +4767,9 @@ void ASTMangler::appendMacroExpansionContext(
47664767
if (auto outermostLocalDC = getOutermostLocalContext(origDC)) {
47674768
auto innermostNonlocalDC = outermostLocalDC->getParent();
47684769
appendContext(innermostNonlocalDC, nullBase, StringRef());
4769-
Identifier name = expansion->getMacroName().getBaseIdentifier();
4770+
Identifier name = macroName;
47704771
ASTContext &ctx = origDC->getASTContext();
4771-
unsigned discriminator = expansion->getDiscriminator();
4772+
unsigned discriminator = macroDiscriminator;
47724773
name = encodeLocalPrecheckedDiscriminator(ctx, name, discriminator);
47734774
appendIdentifier(name.str());
47744775
} else {
@@ -4873,7 +4874,10 @@ void ASTMangler::appendMacroExpansionContext(
48734874
return appendMacroExpansionLoc();
48744875

48754876
// Append our own context and discriminator.
4876-
appendMacroExpansionContext(outerExpansionLoc, origDC, expansion);
4877+
appendMacroExpansionContext(
4878+
outerExpansionLoc, origDC,
4879+
macroName,
4880+
macroDiscriminator);
48774881
appendMacroExpansionOperator(
48784882
baseName.userFacingName(), role, discriminator);
48794883
}
@@ -4900,16 +4904,14 @@ void ASTMangler::appendMacroExpansionOperator(
49004904
}
49014905

49024906
static StringRef getPrivateDiscriminatorIfNecessary(
4903-
const MacroExpansionExpr *expansion) {
4904-
auto dc = MacroDiscriminatorContext::getInnermostMacroContext(
4905-
expansion->getDeclContext());
4906-
auto decl = dc->getAsDecl();
4907+
const DeclContext *macroDC) {
4908+
auto decl = macroDC->getAsDecl();
49074909
if (decl && !decl->isOutermostPrivateOrFilePrivateScope())
49084910
return StringRef();
49094911

49104912
// Mangle non-local private declarations with a textual discriminator
49114913
// based on their enclosing file.
4912-
auto topLevelSubcontext = dc->getModuleScopeContext();
4914+
auto topLevelSubcontext = macroDC->getModuleScopeContext();
49134915
SourceFile *sf = dyn_cast<SourceFile>(topLevelSubcontext);
49144916
if (!sf)
49154917
return StringRef();
@@ -4925,6 +4927,13 @@ static StringRef getPrivateDiscriminatorIfNecessary(
49254927
return discriminator.str();
49264928
}
49274929

4930+
static StringRef getPrivateDiscriminatorIfNecessary(
4931+
const MacroExpansionExpr *expansion) {
4932+
auto dc = MacroDiscriminatorContext::getInnermostMacroContext(
4933+
expansion->getDeclContext());
4934+
return getPrivateDiscriminatorIfNecessary(dc);
4935+
}
4936+
49284937
static StringRef getPrivateDiscriminatorIfNecessary(
49294938
const FreestandingMacroExpansion *expansion) {
49304939
switch (expansion->getFreestandingMacroKind()) {
@@ -4941,7 +4950,8 @@ void
49414950
ASTMangler::appendMacroExpansion(const FreestandingMacroExpansion *expansion) {
49424951
appendMacroExpansionContext(expansion->getPoundLoc(),
49434952
expansion->getDeclContext(),
4944-
expansion);
4953+
expansion->getMacroName().getBaseIdentifier(),
4954+
expansion->getDiscriminator());
49454955
auto privateDiscriminator = getPrivateDiscriminatorIfNecessary(expansion);
49464956
if (!privateDiscriminator.empty()) {
49474957
appendIdentifier(privateDiscriminator);
@@ -4953,6 +4963,42 @@ ASTMangler::appendMacroExpansion(const FreestandingMacroExpansion *expansion) {
49534963
expansion->getDiscriminator());
49544964
}
49554965

4966+
void ASTMangler::appendMacroExpansion(ClosureExpr *attachedTo,
4967+
CustomAttr *attr,
4968+
MacroDecl *macro) {
4969+
auto &ctx = attachedTo->getASTContext();
4970+
auto discriminator =
4971+
ctx.getNextMacroDiscriminator(attachedTo,
4972+
macro->getBaseName());
4973+
4974+
appendMacroExpansionContext(
4975+
attr->getLocation(),
4976+
attachedTo,
4977+
macro->getBaseName().getIdentifier(),
4978+
discriminator);
4979+
4980+
auto privateDiscriminator =
4981+
getPrivateDiscriminatorIfNecessary(attachedTo);
4982+
if (!privateDiscriminator.empty()) {
4983+
appendIdentifier(privateDiscriminator);
4984+
appendOperator("Ll");
4985+
}
4986+
4987+
appendMacroExpansionOperator(
4988+
macro->getBaseName().userFacingName(),
4989+
MacroRole::Body,
4990+
discriminator);
4991+
}
4992+
4993+
std::string
4994+
ASTMangler::mangleAttachedMacroExpansion(ClosureExpr *attachedTo,
4995+
CustomAttr *attr,
4996+
MacroDecl *macro) {
4997+
beginMangling();
4998+
appendMacroExpansion(attachedTo, attr, macro);
4999+
return finalize();
5000+
}
5001+
49565002
std::string
49575003
ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
49585004
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
@@ -2644,19 +2644,17 @@ void ExpandPreambleMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
26442644
//----------------------------------------------------------------------------//
26452645

26462646
void ExpandBodyMacroRequest::diagnoseCycle(DiagnosticEngine &diags) const {
2647-
auto decl = std::get<0>(getStorage());
2648-
diags.diagnose(decl->getLoc(),
2649-
diag::macro_expand_circular_reference_entity,
2650-
"body",
2651-
decl->getName());
2647+
auto fn = std::get<0>(getStorage());
2648+
diags.diagnose(fn.getLoc(),
2649+
diag::macro_expand_circular_reference_unnamed,
2650+
"body");
26522651
}
26532652

26542653
void ExpandBodyMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
2655-
auto decl = std::get<0>(getStorage());
2656-
diags.diagnose(decl->getLoc(),
2657-
diag::macro_expand_circular_reference_entity_through,
2658-
"body",
2659-
decl->getName());
2654+
auto fn = std::get<0>(getStorage());
2655+
diags.diagnose(fn.getLoc(),
2656+
diag::macro_expand_circular_reference_unnamed_through,
2657+
"body");
26602658
}
26612659

26622660
//----------------------------------------------------------------------------//

lib/ASTGen/Sources/MacroEvaluation/Macros.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ func expandAttachedMacro(
586586
let declarationNode = findSyntaxNodeInSourceFile(
587587
sourceFilePtr: declarationSourceFilePtr,
588588
sourceLocationPtr: declarationSourceLocPointer,
589-
type: DeclSyntax.self
589+
type: Syntax.self
590590
)
591591
else {
592592
return 1
@@ -654,7 +654,7 @@ func expandAttachedMacroImpl(
654654
customAttrSourceFilePtr: UnsafePointer<ExportedSourceFile>,
655655
customAttrNode: AttributeSyntax,
656656
declarationSourceFilePtr: UnsafePointer<ExportedSourceFile>,
657-
attachedTo declarationNode: DeclSyntax,
657+
attachedTo declarationNode: Syntax,
658658
parentDeclSourceFilePtr: UnsafePointer<ExportedSourceFile>?,
659659
parentDeclNode: DeclSyntax?
660660
) -> String? {
@@ -686,7 +686,7 @@ func expandAttachedMacroImpl(
686686
)!
687687

688688
let declSyntax = PluginMessage.Syntax(
689-
syntax: Syntax(declarationNode),
689+
syntax: declarationNode,
690690
in: declarationSourceFilePtr
691691
)!
692692

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4481,7 +4481,7 @@ NodePointer Demangler::demangleMacroExpansion() {
44814481
context = popContext();
44824482
NodePointer discriminator = demangleIndexAsNode();
44834483
NodePointer result;
4484-
if (isAttached) {
4484+
if (isAttached && attachedName) {
44854485
result = createWithChildren(
44864486
kind, context, attachedName, macroName, discriminator);
44874487
} else {

0 commit comments

Comments
 (0)