Skip to content

Commit 833338f

Browse files
authored
[Macros] Top-level freestanding macros (#63553)
Allow freestanding macros to be used at top-level. - Parse top-level `#…` as `MacroExpansionDecl` when we are not in scripting mode. - Add macro expansion decls to the source lookup cache with name-driven lazy expansion. Not supporting arbitrary name yet. - Experimental support for script mode and brace-level declaration macro expansions: When type-checking a `MacroExpansionExpr`, assign it a substitute `MacroExpansionDecl` if the macro reference resolves to a declaration macro. This doesn’t work quite fully yet and will be enabled in a future fix.
1 parent 19335a1 commit 833338f

37 files changed

+486
-188
lines changed

include/swift/AST/Decl.h

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8306,19 +8306,21 @@ class PostfixOperatorDecl : public OperatorDecl {
83068306
}
83078307
};
83088308

8309+
class MacroExpansionDecl;
8310+
83098311
/// Represents a missing declaration in the source code.
83108312
///
83118313
/// This is used for parser recovery, e.g. when parsing a floating
83128314
/// attribute list, and to represent placeholders for unexpanded
83138315
/// declarations generated by macros.
83148316
class MissingDecl : public Decl {
8315-
/// If this missing decl represents an unexpanded peer generated
8316-
/// by a macro, \c unexpandedPeer contains the macro custom attribute
8317-
/// and the declaration the macro is attached to.
8317+
/// If this missing decl represents an unexpanded peer generated by a macro,
8318+
/// \c unexpandedMacro contains the macro reference and the base declaration
8319+
/// where the macro expansion applies.
83188320
struct {
8319-
CustomAttr *macroAttr = nullptr;
8320-
ValueDecl *attachedTo = nullptr;
8321-
} unexpandedPeer;
8321+
llvm::PointerUnion<MacroExpansionDecl *, CustomAttr *> macroRef;
8322+
Decl *baseDecl;
8323+
} unexpandedMacro;
83228324

83238325
/// The location that the decl would be if it wasn't missing.
83248326
SourceLoc Loc;
@@ -8339,19 +8341,21 @@ class MissingDecl : public Decl {
83398341
SourceRange getSourceRange() const { return SourceRange(Loc); }
83408342

83418343
static MissingDecl *
8342-
forUnexpandedPeer(CustomAttr *macro, ValueDecl *attachedTo) {
8343-
auto &ctx = attachedTo->getASTContext();
8344-
auto *dc = attachedTo->getDeclContext();
8344+
forUnexpandedMacro(
8345+
llvm::PointerUnion<MacroExpansionDecl *, CustomAttr *> macroRef,
8346+
Decl *baseDecl) {
8347+
auto &ctx = baseDecl->getASTContext();
8348+
auto *dc = baseDecl->getDeclContext();
83458349
auto *missing = new (ctx) MissingDecl(dc, SourceLoc());
83468350

8347-
missing->unexpandedPeer.macroAttr = macro;
8348-
missing->unexpandedPeer.attachedTo = attachedTo;
8351+
missing->unexpandedMacro.macroRef = macroRef;
8352+
missing->unexpandedMacro.baseDecl = baseDecl;
83498353

83508354
return missing;
83518355
}
83528356

8353-
using ExpandedPeerCallback = llvm::function_ref<void(ValueDecl *)>;
8354-
void forEachExpandedPeer(ExpandedPeerCallback callback);
8357+
using MacroExpandedDeclCallback = llvm::function_ref<void(ValueDecl *)>;
8358+
void forEachMacroExpandedDecl(MacroExpandedDeclCallback callback);
83558359

83568360
static bool classof(const Decl *D) {
83578361
return D->getKind() == DeclKind::Missing;
@@ -8512,13 +8516,7 @@ class MacroExpansionDecl : public Decl {
85128516
SourceLoc leftAngleLoc,
85138517
ArrayRef<TypeRepr *> genericArgs,
85148518
SourceLoc rightAngleLoc,
8515-
ArgumentList *args)
8516-
: Decl(DeclKind::MacroExpansion, dc), PoundLoc(poundLoc),
8517-
MacroName(macro), MacroNameLoc(macroLoc),
8518-
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
8519-
GenericArgs(genericArgs), ArgList(args) {
8520-
Bits.MacroExpansionDecl.Discriminator = InvalidDiscriminator;
8521-
}
8519+
ArgumentList *args);
85228520

85238521
ArrayRef<TypeRepr *> getGenericArgs() const { return GenericArgs; }
85248522

@@ -8532,6 +8530,9 @@ class MacroExpansionDecl : public Decl {
85328530
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
85338531
DeclNameRef getMacroName() const { return MacroName; }
85348532
ArgumentList *getArgs() const { return ArgList; }
8533+
void setArgs(ArgumentList *args) { ArgList = args; }
8534+
using ExprOrStmtExpansionCallback = llvm::function_ref<void(ASTNode)>;
8535+
void forEachExpandedExprOrStmt(ExprOrStmtExpansionCallback) const;
85358536
ConcreteDeclRef getMacroRef() const { return macroRef; }
85368537
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
85378538

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6928,6 +6928,9 @@ ERROR(literal_type_in_macro_expansion,none,
69286928
ERROR(invalid_macro_introduced_name,none,
69296929
"declaration name %0 is not covered by macro %1",
69306930
(DeclName, DeclName))
6931+
ERROR(global_freestanding_macro_script,none,
6932+
"global freestanding macros not yet supported in script mode",
6933+
())
69316934

69326935
//------------------------------------------------------------------------------
69336936
// MARK: Move Only Errors

include/swift/AST/Expr.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6197,6 +6197,7 @@ class MacroExpansionExpr final : public Expr {
61976197
ArgumentList *ArgList;
61986198
Expr *Rewritten;
61996199
MacroRoles Roles;
6200+
MacroExpansionDecl *SubstituteDecl;
62006201

62016202
/// The referenced macro.
62026203
ConcreteDeclRef macroRef;
@@ -6219,7 +6220,7 @@ class MacroExpansionExpr final : public Expr {
62196220
MacroName(macroName), MacroNameLoc(macroNameLoc),
62206221
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
62216222
GenericArgs(genericArgs),
6222-
Rewritten(nullptr), Roles(roles) {
6223+
Rewritten(nullptr), Roles(roles), SubstituteDecl(nullptr) {
62236224
Bits.MacroExpansionExpr.Discriminator = InvalidDiscriminator;
62246225

62256226
// Macro expansions always have an argument list. If one is not provided, create
@@ -6276,6 +6277,10 @@ class MacroExpansionExpr final : public Expr {
62766277

62776278
SourceRange getSourceRange() const;
62786279

6280+
MacroExpansionDecl *createSubstituteDecl() const;
6281+
MacroExpansionDecl *getSubstituteDecl() const;
6282+
void setSubstituteDecl(MacroExpansionDecl *decl);
6283+
62796284
static bool classof(const Expr *E) {
62806285
return E->getKind() == ExprKind::MacroExpansion;
62816286
}

include/swift/AST/FileUnit.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,14 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
210210
/// The order of the results is not guaranteed to be meaningful.
211211
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {}
212212

213+
/// Finds all top-level decls in this file with their auxiliary decls such as
214+
/// macro expansions.
215+
///
216+
/// This does a simple local lookup, not recursively looking through imports.
217+
/// The order of the results is not guaranteed to be meaningful.
218+
void getTopLevelDeclsWithAuxiliaryDecls(
219+
SmallVectorImpl<Decl*> &results) const;
220+
213221
virtual void
214222
getExportedPrespecializations(SmallVectorImpl<Decl *> &results) const {}
215223

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,12 +1311,9 @@ namespace {
13111311
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {
13121312
printCommon(MED, "macro_expansion_decl ");
13131313
OS << MED->getMacroName();
1314-
if (MED->getArgs()) {
1315-
OS << '\n';
1316-
OS.indent(Indent + 2);
1317-
printArgumentList(OS, MED->getArgs(), Indent,
1318-
[&](Expr *E) { printRec(E); });
1319-
}
1314+
OS << '\n';
1315+
printArgumentList(OS, MED->getArgs(), Indent,
1316+
[&](Expr *E) { printRec(E); });
13201317
PrintWithColorRAII(OS, ParenthesisColor) << ')';
13211318
}
13221319
};
@@ -3050,7 +3047,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
30503047
printArgumentList(E->getArgs());
30513048
}
30523049
if (auto rewritten = E->getRewritten()) {
3053-
OS << '\n';
3050+
OS << " rewritten=\n";
30543051
printRec(rewritten);
30553052
}
30563053
PrintWithColorRAII(OS, ParenthesisColor) << ')';

lib/AST/ASTPrinter.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4683,20 +4683,18 @@ void PrintAST::visitMacroDecl(MacroDecl *decl) {
46834683

46844684
void PrintAST::visitMacroExpansionDecl(MacroExpansionDecl *decl) {
46854685
Printer << '#' << decl->getMacroName();
4686-
if (decl->getArgs()) {
4687-
Printer << '(';
4688-
auto args = decl->getArgs()->getOriginalArgs();
4689-
bool isFirst = true;
4690-
// FIXME: handle trailing closures.
4691-
for (auto arg : *args) {
4692-
if (!isFirst) {
4693-
Printer << ", ";
4694-
}
4695-
printArgument(arg);
4696-
isFirst = false;
4686+
Printer << '(';
4687+
auto args = decl->getArgs()->getOriginalArgs();
4688+
bool isFirst = true;
4689+
// FIXME: handle trailing closures.
4690+
for (auto arg : *args) {
4691+
if (!isFirst) {
4692+
Printer << ", ";
46974693
}
4698-
Printer << ')';
4694+
printArgument(arg);
4695+
isFirst = false;
46994696
}
4697+
Printer << ')';
47004698
}
47014699

47024700
void PrintAST::visitIntegerLiteralExpr(IntegerLiteralExpr *expr) {

lib/AST/ASTWalker.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,15 +433,29 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
433433
bool shouldWalkArguments, shouldWalkExpansion;
434434
std::tie(shouldWalkArguments, shouldWalkExpansion) =
435435
Walker.shouldWalkMacroArgumentsAndExpansion();
436-
if (shouldWalkArguments && MED->getArgs() && !doIt(MED->getArgs()))
437-
return true;
436+
if (shouldWalkArguments && MED->getArgs()) {
437+
if (auto *argList = doIt(MED->getArgs()))
438+
MED->setArgs(argList);
439+
else
440+
return true;
441+
}
438442
// Visit auxiliary decls, which may be decls from macro expansions.
439443
bool alreadyFailed = false;
440444
if (shouldWalkExpansion) {
441445
MED->visitAuxiliaryDecls([&](Decl *decl) {
442446
if (alreadyFailed) return;
443447
alreadyFailed = inherited::visit(decl);
444448
});
449+
MED->forEachExpandedExprOrStmt([&](ASTNode expandedNode) {
450+
if (alreadyFailed) return;
451+
if (auto *expr = expandedNode.dyn_cast<Expr *>()) {
452+
if (!doIt(expr))
453+
alreadyFailed = true;
454+
} else if (auto *stmt = expandedNode.dyn_cast<Stmt *>()) {
455+
if (!doIt(stmt))
456+
alreadyFailed = true;
457+
}
458+
});
445459
}
446460
return alreadyFailed;
447461
}

lib/AST/Decl.cpp

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9986,26 +9986,28 @@ MacroRoles swift::getAttachedMacroRoles() {
99869986
return attachedMacroRoles;
99879987
}
99889988

9989-
void
9990-
MissingDecl::forEachExpandedPeer(ExpandedPeerCallback callback) {
9991-
auto *macro = unexpandedPeer.macroAttr;
9992-
auto *attachedTo = unexpandedPeer.attachedTo;
9993-
if (!macro || !attachedTo)
9989+
void MissingDecl::forEachMacroExpandedDecl(MacroExpandedDeclCallback callback) {
9990+
auto macroRef = unexpandedMacro.macroRef;
9991+
auto *baseDecl = unexpandedMacro.baseDecl;
9992+
if (!macroRef || !baseDecl)
99949993
return;
99959994

9996-
attachedTo->visitAuxiliaryDecls(
9997-
[&](Decl *auxiliaryDecl) {
9998-
auto *sf = auxiliaryDecl->getInnermostDeclContext()->getParentSourceFile();
9999-
auto *macroAttr = sf->getAttachedMacroAttribute();
10000-
if (macroAttr != unexpandedPeer.macroAttr)
10001-
return;
10002-
10003-
auto *value = dyn_cast<ValueDecl>(auxiliaryDecl);
10004-
if (!value)
10005-
return;
10006-
10007-
callback(value);
10008-
});
9995+
baseDecl->visitAuxiliaryDecls([&](Decl *auxiliaryDecl) {
9996+
auto *sf = auxiliaryDecl->getInnermostDeclContext()->getParentSourceFile();
9997+
// We only visit auxiliary decls that are macro expansions associated with
9998+
// this macro reference.
9999+
if (auto *med = macroRef.dyn_cast<MacroExpansionDecl *>()) {
10000+
if (med != sf->getMacroExpansion().dyn_cast<Decl *>())
10001+
return;
10002+
} else if (auto *attr = macroRef.dyn_cast<CustomAttr *>()) {
10003+
if (attr != sf->getAttachedMacroAttribute())
10004+
return;
10005+
} else {
10006+
return;
10007+
}
10008+
if (auto *vd = dyn_cast<ValueDecl>(auxiliaryDecl))
10009+
callback(vd);
10010+
});
1000910011
}
1001010012

1001110013
MacroDecl::MacroDecl(
@@ -10142,10 +10144,24 @@ Optional<BuiltinMacroKind> MacroDecl::getBuiltinKind() const {
1014210144
return def.getBuiltinKind();
1014310145
}
1014410146

10147+
MacroExpansionDecl::MacroExpansionDecl(
10148+
DeclContext *dc, SourceLoc poundLoc, DeclNameRef macro,
10149+
DeclNameLoc macroLoc, SourceLoc leftAngleLoc,
10150+
ArrayRef<TypeRepr *> genericArgs, SourceLoc rightAngleLoc,
10151+
ArgumentList *args)
10152+
: Decl(DeclKind::MacroExpansion, dc), PoundLoc(poundLoc),
10153+
MacroName(macro), MacroNameLoc(macroLoc),
10154+
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
10155+
GenericArgs(genericArgs),
10156+
ArgList(args ? args
10157+
: ArgumentList::createImplicit(dc->getASTContext(), {})) {
10158+
Bits.MacroExpansionDecl.Discriminator = InvalidDiscriminator;
10159+
}
10160+
1014510161
SourceRange MacroExpansionDecl::getSourceRange() const {
1014610162
SourceLoc endLoc;
10147-
if (ArgList)
10148-
endLoc = ArgList->getEndLoc();
10163+
if (auto argsEndList = ArgList->getEndLoc())
10164+
endLoc = argsEndList;
1014910165
else if (RightAngleLoc.isValid())
1015010166
endLoc = RightAngleLoc;
1015110167
else
@@ -10171,6 +10187,23 @@ unsigned MacroExpansionDecl::getDiscriminator() const {
1017110187
return getRawDiscriminator();
1017210188
}
1017310189

10190+
void MacroExpansionDecl::forEachExpandedExprOrStmt(
10191+
ExprOrStmtExpansionCallback callback) const {
10192+
auto mutableThis = const_cast<MacroExpansionDecl *>(this);
10193+
auto bufferID = evaluateOrDefault(
10194+
getASTContext().evaluator,
10195+
ExpandMacroExpansionDeclRequest{mutableThis}, {});
10196+
auto &sourceMgr = getASTContext().SourceMgr;
10197+
auto *moduleDecl = getModuleContext();
10198+
if (!bufferID)
10199+
return;
10200+
auto startLoc = sourceMgr.getLocForBufferStart(*bufferID);
10201+
auto *sourceFile = moduleDecl->getSourceFileContainingLocation(startLoc);
10202+
for (auto node : sourceFile->getTopLevelItems())
10203+
if (node.is<Expr *>() || node.is<Stmt *>())
10204+
callback(node);
10205+
}
10206+
1017410207
NominalTypeDecl *
1017510208
ValueDecl::getRuntimeDiscoverableAttrTypeDecl(CustomAttr *attr) const {
1017610209
auto &ctx = getASTContext();

lib/AST/Expr.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,6 +2745,23 @@ unsigned MacroExpansionExpr::getDiscriminator() const {
27452745
return getRawDiscriminator();
27462746
}
27472747

2748+
MacroExpansionDecl *MacroExpansionExpr::createSubstituteDecl() const {
2749+
auto dc = DC;
2750+
if (auto *tlcd = dyn_cast_or_null<TopLevelCodeDecl>(dc->getAsDecl()))
2751+
dc = tlcd->getDeclContext();
2752+
return new (DC->getASTContext()) MacroExpansionDecl(
2753+
dc, SigilLoc, MacroName, MacroNameLoc, LeftAngleLoc,
2754+
GenericArgs, RightAngleLoc, ArgList);
2755+
}
2756+
2757+
MacroExpansionDecl *MacroExpansionExpr::getSubstituteDecl() const {
2758+
return SubstituteDecl;
2759+
}
2760+
2761+
void MacroExpansionExpr::setSubstituteDecl(MacroExpansionDecl *decl) {
2762+
SubstituteDecl = decl;
2763+
}
2764+
27482765
void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) {
27492766
if (!CE) {
27502767
out << "(null)";

0 commit comments

Comments
 (0)