Skip to content

Commit be8a6ad

Browse files
committed
[Macros] Top-level freestanding macros
Allow freestanding macros to be used at top-level. - Parse top-level `#...` as `MacroExpansionDecl`. When it resolves to an expression macro, expand the decl to a `MacroExpansionExpr`, and then type-check that as a normal expression. - Add macro expansions to the source lookup cache. - Add name lookup flags `MacroLookup` and `DisableMacroExpansion` to break dependency cycles between name lookup and macro expansion. - `MacroLookup` is used to prevent unqualified macro lookup from looking into local AST scopes that may contain other macro expansions. - `DisableMacroExpansion` is used to prevent the top-level lookup cache from eagerly expanding macros. This requires `NLOptions` to be plumbed through `lookupValue`. - Generate AST scopes for macro expansion decls and use them to break dependency cycles, specifically to determine whether a location is within a macro declaration or top-level expansion. This work hand in hand with `DisableMacroExpansion` to prevent macro expansions within macro definitions (e.g. `#externalMacro`) from circularly depending on macro expansions to produce macro declarations for lookup. TODOs: - Nested expansions and name-guided expansions are not yet handled in top-level name lookup. - Support local scope declaration macro expansions.
1 parent 8e0e51a commit be8a6ad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+718
-276
lines changed

include/swift/AST/ASTScope.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,12 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
278278
static const ASTScopeImpl *findStartingScopeForLookup(SourceFile *,
279279
const SourceLoc where);
280280

281-
protected:
281+
public:
282282
/// Not const because may reexpand some scopes.
283283
ASTScopeImpl *findInnermostEnclosingScope(SourceLoc,
284284
NullablePtr<raw_ostream>);
285+
286+
protected:
285287
ASTScopeImpl *findInnermostEnclosingScopeImpl(SourceLoc,
286288
NullablePtr<raw_ostream>,
287289
SourceManager &,
@@ -1217,6 +1219,29 @@ class MacroDeclScope final : public ASTScopeImpl {
12171219
NullablePtr<const GenericParamList> genericParams() const override;
12181220
};
12191221

1222+
class MacroExpansionDeclScope final : public ASTScopeImpl {
1223+
public:
1224+
MacroExpansionDecl *const decl;
1225+
1226+
MacroExpansionDeclScope(MacroExpansionDecl *d) : decl(d) {}
1227+
virtual ~MacroExpansionDeclScope() {}
1228+
1229+
protected:
1230+
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
1231+
1232+
private:
1233+
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
1234+
1235+
public:
1236+
std::string getClassName() const override;
1237+
SourceRange
1238+
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
1239+
1240+
public:
1241+
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
1242+
Decl *getDecl() const { return decl; }
1243+
};
1244+
12201245
class AbstractStmtScope : public ASTScopeImpl {
12211246
public:
12221247
SourceRange

include/swift/AST/Decl.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ namespace swift {
109109
class VarDecl;
110110
class OpaqueReturnTypeRepr;
111111
class Witness;
112+
class MacroExpansionExpr;
112113

113114
namespace ast_scope {
114115
class AbstractPatternEntryScope;
@@ -8456,13 +8457,7 @@ class MacroExpansionDecl : public Decl {
84568457
SourceLoc leftAngleLoc,
84578458
ArrayRef<TypeRepr *> genericArgs,
84588459
SourceLoc rightAngleLoc,
8459-
ArgumentList *args)
8460-
: Decl(DeclKind::MacroExpansion, dc), PoundLoc(poundLoc),
8461-
MacroName(macro), MacroNameLoc(macroLoc),
8462-
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
8463-
GenericArgs(genericArgs), ArgList(args) {
8464-
Bits.MacroExpansionDecl.Discriminator = InvalidDiscriminator;
8465-
}
8460+
ArgumentList *args);
84668461

84678462
ArrayRef<TypeRepr *> getGenericArgs() const { return GenericArgs; }
84688463

@@ -8476,9 +8471,11 @@ class MacroExpansionDecl : public Decl {
84768471
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
84778472
DeclNameRef getMacroName() const { return MacroName; }
84788473
ArgumentList *getArgs() const { return ArgList; }
8479-
ArrayRef<Decl *> getRewritten() const;
8474+
void setArgs(ArgumentList *args) { ArgList = args; }
8475+
ArrayRef<ASTNode> getRewritten() const;
84808476
ConcreteDeclRef getMacroRef() const { return macroRef; }
84818477
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
8478+
MacroExpansionExpr *createExpr() const;
84828479

84838480
/// Returns a discriminator which determines this macro expansion's index
84848481
/// in the sequence of macro expansions within the current function.

include/swift/AST/DeclContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,13 @@ class IterableDeclContext {
832832
/// The resulting list of members will be stable across translation units.
833833
ArrayRef<Decl *> getAllMembers() const;
834834

835+
/// Get all of the members within this context, including any
836+
/// implicitly-synthesized members and macro expansions. All macro expansions
837+
/// will be recursively flattened.
838+
///
839+
/// The resulting list of members will be stable across translation units.
840+
ArrayRef<Decl *> getExpandedAllMembers() const;
841+
835842
/// Retrieve the set of members in this context without loading any from the
836843
/// associated lazy loader; this should only be used as part of implementing
837844
/// abstractions on top of member loading, such as a name lookup table.

include/swift/AST/FileUnit.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,14 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
6464
/// within this file.
6565
///
6666
/// This does a simple local lookup, not recursively looking through imports.
67-
virtual void lookupValue(DeclName name, NLKind lookupKind,
67+
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
6868
SmallVectorImpl<ValueDecl*> &result) const = 0;
6969

70+
void lookupValue(DeclName name, NLKind lookupKind,
71+
SmallVectorImpl<ValueDecl*> &result) const {
72+
lookupValue(name, lookupKind, getDefaultNLOptions(lookupKind), result);
73+
}
74+
7075
/// Look up a local type declaration by its mangled name.
7176
///
7277
/// This does a simple local lookup, not recursively looking through imports.
@@ -210,6 +215,13 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
210215
/// The order of the results is not guaranteed to be meaningful.
211216
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {}
212217

218+
/// Finds all top-level decls in this file with all macros recursively
219+
/// expanded.
220+
///
221+
/// This does a simple local lookup, not recursively looking through imports.
222+
/// The order of the results is not guaranteed to be meaningful.
223+
void getExpandedTopLevelDecls(SmallVectorImpl<Decl*> &results) const;
224+
213225
virtual void
214226
getExportedPrespecializations(SmallVectorImpl<Decl *> &results) const {}
215227

@@ -369,7 +381,7 @@ class BuiltinUnit final : public FileUnit {
369381
public:
370382
explicit BuiltinUnit(ModuleDecl &M);
371383

372-
virtual void lookupValue(DeclName name, NLKind lookupKind,
384+
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
373385
SmallVectorImpl<ValueDecl*> &result) const override;
374386

375387
/// Find all Objective-C methods with the given selector.

include/swift/AST/LookupKinds.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ enum NLOptions : unsigned {
5353
// Include @usableFromInline and @inlinable
5454
NL_IncludeUsableFromInline = 1 << 6,
5555

56+
/// Don't expand macros.
57+
NL_DisableMacroExpansions = 1 << 7,
58+
5659
/// The default set of options used for qualified name lookup.
5760
///
5861
/// FIXME: Eventually, add NL_ProtocolMembers to this, once all of the
@@ -79,6 +82,13 @@ static inline NLOptions operator~(NLOptions value) {
7982
return NLOptions(~(unsigned)value);
8083
}
8184

85+
static inline NLOptions getDefaultNLOptions(NLKind kind) {
86+
switch (kind) {
87+
case NLKind::QualifiedLookup: return NL_QualifiedDefault;
88+
case NLKind::UnqualifiedLookup: return NL_UnqualifiedDefault;
89+
}
90+
}
91+
8292
void simple_display(llvm::raw_ostream &out, NLOptions options);
8393

8494
} // end namespace swift

include/swift/AST/Module.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,9 +651,19 @@ class ModuleDecl
651651
/// within the current module.
652652
///
653653
/// This does a simple local lookup, not recursively looking through imports.
654-
void lookupValue(DeclName Name, NLKind LookupKind,
654+
void lookupValue(DeclName Name, NLKind LookupKind, NLOptions Options,
655655
SmallVectorImpl<ValueDecl*> &Result) const;
656656

657+
/// Look up a (possibly overloaded) value set at top-level scope
658+
/// (but with the specified access path, which may come from an import decl)
659+
/// within the current module.
660+
///
661+
/// This does a simple local lookup, not recursively looking through imports.
662+
void lookupValue(DeclName Name, NLKind LookupKind,
663+
SmallVectorImpl<ValueDecl*> &Result) const {
664+
lookupValue(Name, LookupKind, getDefaultNLOptions(LookupKind), Result);
665+
}
666+
657667
/// Look up a local type declaration by its mangled name.
658668
///
659669
/// This does a simple local lookup, not recursively looking through imports.

include/swift/AST/NameLookup.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ enum class UnqualifiedLookupFlags {
239239
// This lookup should include results that are @inlinable or
240240
// @usableFromInline.
241241
IncludeUsableFromInline = 1 << 5,
242+
// This lookup should not expand macros.
243+
DisableMacroExpansions = 1 << 6,
244+
// This lookup should only return macros.
245+
MacroLookup = 1 << 7,
242246
};
243247

244248
using UnqualifiedLookupOptions = OptionSet<UnqualifiedLookupFlags>;
@@ -794,6 +798,11 @@ class ASTScope : public ASTAllocated<ASTScope> {
794798
static std::pair<CaseStmt *, CaseStmt *>
795799
lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc);
796800

801+
/// Returns true if the given location is within a \c MacroDecl or a top-level
802+
/// \c MacroExpansionDecl.
803+
static bool isLocWithinMacroDeclOrTopLevelMacroExpansionDeclScope(
804+
SourceFile *sf, SourceLoc loc);
805+
797806
SWIFT_DEBUG_DUMP;
798807
void print(llvm::raw_ostream &) const;
799808
void dumpOneScopeMapLocation(std::pair<unsigned, unsigned>);

include/swift/AST/SourceFile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class SourceFile final : public FileUnit {
427427
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
428428
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;
429429

430-
virtual void lookupValue(DeclName name, NLKind lookupKind,
430+
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
431431
SmallVectorImpl<ValueDecl*> &result) const override;
432432

433433
virtual void lookupVisibleDecls(ImportPath::Access accessPath,

include/swift/AST/SynthesizedFileUnit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class SynthesizedFileUnit final : public FileUnit {
4343
/// Add a synthesized top-level declaration.
4444
void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); }
4545

46-
virtual void lookupValue(DeclName name, NLKind lookupKind,
46+
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
4747
SmallVectorImpl<ValueDecl *> &result) const override;
4848

4949
void lookupObjCMethods(

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,24 @@ class AllMembersRequest :
18131813
bool isCached() const { return true; }
18141814
};
18151815

1816+
class ExpandedAllMembersRequest :
1817+
public SimpleRequest<ExpandedAllMembersRequest,
1818+
ArrayRef<Decl *>(IterableDeclContext *),
1819+
RequestFlags::Cached> {
1820+
public:
1821+
using SimpleRequest::SimpleRequest;
1822+
1823+
private:
1824+
friend SimpleRequest;
1825+
1826+
// Evaluation.
1827+
ArrayRef<Decl *>
1828+
evaluate(Evaluator &evaluator, IterableDeclContext *idc) const;
1829+
1830+
public:
1831+
bool isCached() const { return true; }
1832+
};
1833+
18161834
class IsImplicitlyUnwrappedOptionalRequest :
18171835
public SimpleRequest<IsImplicitlyUnwrappedOptionalRequest,
18181836
bool(ValueDecl *),
@@ -3813,16 +3831,16 @@ class MacroDefinitionRequest
38133831
/// Find the definition of a given macro.
38143832
class ExpandMacroExpansionDeclRequest
38153833
: public SimpleRequest<ExpandMacroExpansionDeclRequest,
3816-
ArrayRef<Decl *>(MacroExpansionDecl *),
3834+
ArrayRef<ASTNode>(MacroExpansionDecl *),
38173835
RequestFlags::Cached> {
38183836
public:
38193837
using SimpleRequest::SimpleRequest;
38203838

38213839
private:
38223840
friend SimpleRequest;
38233841

3824-
ArrayRef<Decl *> evaluate(Evaluator &evaluator,
3825-
MacroExpansionDecl *med) const;
3842+
ArrayRef<ASTNode>
3843+
evaluate(Evaluator &evaluator, MacroExpansionDecl *med) const;
38263844

38273845
public:
38283846
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ SWIFT_REQUEST(TypeChecker, ABIMembersRequest,
8383
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
8484
SWIFT_REQUEST(TypeChecker, AllMembersRequest,
8585
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
86+
SWIFT_REQUEST(TypeChecker, ExpandedAllMembersRequest,
87+
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
8688
SWIFT_REQUEST(TypeChecker, SpecializeAttrTargetDeclRequest,
8789
ValueDecl *(const ValueDecl *, SpecializeAttr *),
8890
Cached, NoLocationInfo)
@@ -429,7 +431,7 @@ SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
429431
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
430432
Cached, NoLocationInfo)
431433
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
432-
ArrayRef<Decl *>(MacroExpansionDecl *),
434+
ArrayRef<ASTNode> (MacroExpansionDecl *),
433435
Cached, NoLocationInfo)
434436
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
435437
ArrayRef<unsigned>(Decl *),

include/swift/AST/TypeMemberVisitor.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,9 @@ class TypeMemberVisitor : public DeclVisitor<ImplClass, RetTy> {
8181

8282
/// Visit expanded macros.
8383
void visitMacroExpansionDecl(MacroExpansionDecl *D) {
84-
for (auto *decl : D->getRewritten())
85-
asImpl().visit(decl);
84+
for (auto node : D->getRewritten())
85+
if (auto *decl = node.dyn_cast<Decl *>())
86+
asImpl().visit(decl);
8687
}
8788
};
8889

include/swift/ClangImporter/ClangModule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class ClangModuleUnit final : public LoadedFile {
6565

6666
virtual bool isSystemModule() const override;
6767

68-
virtual void lookupValue(DeclName name, NLKind lookupKind,
68+
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
6969
SmallVectorImpl<ValueDecl*> &results) const override;
7070

7171
virtual TypeDecl *

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ class SerializedASTFile final : public LoadedFile {
359359

360360
virtual bool isSystemModule() const override;
361361

362-
virtual void lookupValue(DeclName name, NLKind lookupKind,
362+
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
363363
SmallVectorImpl<ValueDecl*> &results) const override;
364364

365365
virtual StringRef

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,12 +1322,12 @@ namespace {
13221322
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {
13231323
printCommon(MED, "macro_expansion_decl ");
13241324
OS << MED->getMacroName();
1325-
if (MED->getArgs()) {
1326-
OS << '\n';
1327-
OS.indent(Indent + 2);
1328-
printArgumentList(OS, MED->getArgs(), Indent,
1329-
[&](Expr *E) { printRec(E); });
1330-
}
1325+
OS << '\n';
1326+
printArgumentList(OS, MED->getArgs(), Indent,
1327+
[&](Expr *E) { printRec(E); });
1328+
auto rewritten = MED->getRewritten();
1329+
if (!rewritten.empty())
1330+
printASTNodes(rewritten, MED->getASTContext(), "rewritten");
13311331
PrintWithColorRAII(OS, ParenthesisColor) << ')';
13321332
}
13331333
};
@@ -3045,7 +3045,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
30453045
printArgumentList(E->getArgs());
30463046
}
30473047
if (auto rewritten = E->getRewritten()) {
3048-
OS << '\n';
3048+
OS << " rewritten=\n";
30493049
printRec(rewritten);
30503050
}
30513051
PrintWithColorRAII(OS, ParenthesisColor) << ')';

lib/AST/ASTPrinter.cpp

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

46094609
void PrintAST::visitMacroExpansionDecl(MacroExpansionDecl *decl) {
46104610
Printer << '#' << decl->getMacroName();
4611-
if (decl->getArgs()) {
4612-
Printer << '(';
4613-
auto args = decl->getArgs()->getOriginalArgs();
4614-
bool isFirst = true;
4615-
// FIXME: handle trailing closures.
4616-
for (auto arg : *args) {
4617-
if (!isFirst) {
4618-
Printer << ", ";
4619-
}
4620-
printArgument(arg);
4621-
isFirst = false;
4611+
Printer << '(';
4612+
auto args = decl->getArgs()->getOriginalArgs();
4613+
bool isFirst = true;
4614+
// FIXME: handle trailing closures.
4615+
for (auto arg : *args) {
4616+
if (!isFirst) {
4617+
Printer << ", ";
46224618
}
4623-
Printer << ')';
4619+
printArgument(arg);
4620+
isFirst = false;
46244621
}
4622+
Printer << ')';
46254623
}
46264624

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

0 commit comments

Comments
 (0)