Skip to content

Commit a56e760

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 7d93b75 commit a56e760

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

+705
-261
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/ASTWalker.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,10 @@ class ASTWalker {
532532
/// TODO: Consider changing this to false by default.
533533
virtual bool shouldWalkSerializedTopLevelInternalDecls() { return true; }
534534

535+
virtual bool shouldWalkIntoMacroArguments() { return true; }
536+
537+
virtual bool shouldWalkIntoMacroExpansions() { return true; }
538+
535539
/// walkToParameterListPre - This method is called when first visiting a
536540
/// ParameterList, before walking into its parameters.
537541
///

include/swift/AST/Decl.h

Lines changed: 4 additions & 1 deletion
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;
@@ -8452,9 +8453,11 @@ class MacroExpansionDecl : public Decl {
84528453
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
84538454
DeclNameRef getMacroName() const { return MacroName; }
84548455
ArgumentList *getArgs() const { return ArgList; }
8455-
ArrayRef<Decl *> getRewritten() const;
8456+
void setArgs(ArgumentList *args) { ArgList = args; }
8457+
ArrayRef<ASTNode> getRewritten() const;
84568458
ConcreteDeclRef getMacroRef() const { return macroRef; }
84578459
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
8460+
MacroExpansionExpr *createExpr() const;
84588461

84598462
/// Returns a discriminator which determines this macro expansion's index
84608463
/// 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
@@ -647,9 +647,19 @@ class ModuleDecl
647647
/// within the current module.
648648
///
649649
/// This does a simple local lookup, not recursively looking through imports.
650-
void lookupValue(DeclName Name, NLKind LookupKind,
650+
void lookupValue(DeclName Name, NLKind LookupKind, NLOptions Options,
651651
SmallVectorImpl<ValueDecl*> &Result) const;
652652

653+
/// Look up a (possibly overloaded) value set at top-level scope
654+
/// (but with the specified access path, which may come from an import decl)
655+
/// within the current module.
656+
///
657+
/// This does a simple local lookup, not recursively looking through imports.
658+
void lookupValue(DeclName Name, NLKind LookupKind,
659+
SmallVectorImpl<ValueDecl*> &Result) const {
660+
lookupValue(Name, LookupKind, getDefaultNLOptions(LookupKind), Result);
661+
}
662+
653663
/// Look up a local type declaration by its mangled name.
654664
///
655665
/// 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 *),
@@ -3810,16 +3828,16 @@ class MacroDefinitionRequest
38103828
/// Find the definition of a given macro.
38113829
class ExpandMacroExpansionDeclRequest
38123830
: public SimpleRequest<ExpandMacroExpansionDeclRequest,
3813-
ArrayRef<Decl *>(MacroExpansionDecl *),
3831+
ArrayRef<ASTNode>(MacroExpansionDecl *),
38143832
RequestFlags::Cached> {
38153833
public:
38163834
using SimpleRequest::SimpleRequest;
38173835

38183836
private:
38193837
friend SimpleRequest;
38203838

3821-
ArrayRef<Decl *> evaluate(Evaluator &evaluator,
3822-
MacroExpansionDecl *med) const;
3839+
ArrayRef<ASTNode>
3840+
evaluate(Evaluator &evaluator, MacroExpansionDecl *med) const;
38233841

38243842
public:
38253843
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)
@@ -426,7 +428,7 @@ SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
426428
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
427429
Cached, NoLocationInfo)
428430
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
429-
ArrayRef<Decl *>(MacroExpansionDecl *),
431+
ArrayRef<ASTNode> (MacroExpansionDecl *),
430432
Cached, NoLocationInfo)
431433
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
432434
bool(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
@@ -352,7 +352,7 @@ class SerializedASTFile final : public LoadedFile {
352352

353353
virtual bool isSystemModule() const override;
354354

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

358358
virtual StringRef

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,10 +1324,12 @@ namespace {
13241324
OS << MED->getMacroName();
13251325
if (MED->getArgs()) {
13261326
OS << '\n';
1327-
OS.indent(Indent + 2);
13281327
printArgumentList(OS, MED->getArgs(), Indent,
13291328
[&](Expr *E) { printRec(E); });
13301329
}
1330+
auto rewritten = MED->getRewritten();
1331+
if (!rewritten.empty())
1332+
printASTNodes(rewritten, MED->getASTContext(), "rewritten");
13311333
PrintWithColorRAII(OS, ParenthesisColor) << ')';
13321334
}
13331335
};
@@ -3045,7 +3047,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
30453047
printArgumentList(E->getArgs());
30463048
}
30473049
if (auto rewritten = E->getRewritten()) {
3048-
OS << '\n';
3050+
OS << " rewritten=\n";
30493051
printRec(rewritten);
30503052
}
30513053
PrintWithColorRAII(OS, ParenthesisColor) << ')';

lib/AST/ASTScope.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,34 @@ void ASTScope::dumpOneScopeMapLocation(std::pair<unsigned, unsigned> lineCol) {
7676
impl->dumpOneScopeMapLocation(lineCol);
7777
}
7878

79+
bool ASTScope::isLocWithinMacroDeclOrTopLevelMacroExpansionDeclScope(
80+
SourceFile *sf, SourceLoc loc) {
81+
// The innermost scope containing the loc.
82+
auto *innermostScope = sf->getScope().impl->findInnermostEnclosingScope(
83+
loc, nullptr);
84+
auto isMDOrTopLevelMED = [&](const ASTScopeImpl *scope) -> bool {
85+
if (auto *decl = scope->getDeclIfAny().getPtrOrNull()) {
86+
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) {
87+
if (med->getDeclContext()->getContextKind() ==
88+
DeclContextKind::FileUnit)
89+
return true;
90+
} else if (auto *md = dyn_cast<MacroDecl>(decl)) {
91+
return true;
92+
}
93+
}
94+
return false;
95+
};
96+
// Climb up the tree until we find a matching scope.
97+
const ASTScopeImpl *scope = innermostScope;
98+
while (!isMDOrTopLevelMED(scope)) {
99+
auto *parentScope = scope->getLookupParent().getPtrOrNull();
100+
if (!parentScope || parentScope == scope)
101+
return false;
102+
scope = parentScope;
103+
}
104+
return true;
105+
}
106+
79107
#pragma mark ASTScopeImpl
80108

81109

@@ -151,6 +179,7 @@ DEFINE_GET_CLASS_NAME(DifferentiableAttributeScope)
151179
DEFINE_GET_CLASS_NAME(SubscriptDeclScope)
152180
DEFINE_GET_CLASS_NAME(EnumElementScope)
153181
DEFINE_GET_CLASS_NAME(MacroDeclScope)
182+
DEFINE_GET_CLASS_NAME(MacroExpansionDeclScope)
154183
DEFINE_GET_CLASS_NAME(IfStmtScope)
155184
DEFINE_GET_CLASS_NAME(WhileStmtScope)
156185
DEFINE_GET_CLASS_NAME(GuardStmtScope)

0 commit comments

Comments
 (0)