Skip to content

Commit cd9763a

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 are not handled in name lookup. The proper fix is to have a request to flatten expanded macros so that members can be obtained without explicitly visiting macro expansions everywhere. - Support local scope declaration macro expansions.
1 parent dcf90ba commit cd9763a

Some content is hidden

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

53 files changed

+593
-257
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
@@ -110,6 +110,7 @@ namespace swift {
110110
class VarDecl;
111111
class OpaqueReturnTypeRepr;
112112
class Witness;
113+
class MacroExpansionExpr;
113114

114115
namespace ast_scope {
115116
class AbstractPatternEntryScope;
@@ -8504,9 +8505,11 @@ class MacroExpansionDecl : public Decl {
85048505
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
85058506
DeclNameRef getMacroName() const { return MacroName; }
85068507
ArgumentList *getArgs() const { return ArgList; }
8507-
ArrayRef<Decl *> getRewritten() const;
8508+
void setArgs(ArgumentList *args) { ArgList = args; }
8509+
ArrayRef<ASTNode> getRewritten() const;
85088510
ConcreteDeclRef getMacroRef() const { return macroRef; }
85098511
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
8512+
MacroExpansionExpr *createExpr() const;
85108513

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

include/swift/AST/FileUnit.h

Lines changed: 7 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.
@@ -369,7 +374,7 @@ class BuiltinUnit final : public FileUnit {
369374
public:
370375
explicit BuiltinUnit(ModuleDecl &M);
371376

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

375380
/// 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: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3998,16 +3998,16 @@ class MacroDefinitionRequest
39983998
/// Find the definition of a given macro.
39993999
class ExpandMacroExpansionDeclRequest
40004000
: public SimpleRequest<ExpandMacroExpansionDeclRequest,
4001-
ArrayRef<Decl *>(MacroExpansionDecl *),
4001+
ArrayRef<ASTNode>(MacroExpansionDecl *),
40024002
RequestFlags::Cached> {
40034003
public:
40044004
using SimpleRequest::SimpleRequest;
40054005

40064006
private:
40074007
friend SimpleRequest;
40084008

4009-
ArrayRef<Decl *> evaluate(Evaluator &evaluator,
4010-
MacroExpansionDecl *med) const;
4009+
ArrayRef<ASTNode>
4010+
evaluate(Evaluator &evaluator, MacroExpansionDecl *med) const;
40114011

40124012
public:
40134013
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
459459
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
460460
Cached, NoLocationInfo)
461461
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
462-
ArrayRef<Decl *>(MacroExpansionDecl *),
462+
ArrayRef<ASTNode> (MacroExpansionDecl *),
463463
Cached, NoLocationInfo)
464464
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
465465
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/ASTContext.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,8 @@ void ASTContext::lookupInModule(
765765

766766
// Find all of the declarations with this name in the Swift module.
767767
auto identifier = getIdentifier(name);
768-
M->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
768+
M->lookupValue(identifier, NLKind::UnqualifiedLookup, NL_UnqualifiedDefault,
769+
results);
769770
}
770771

771772
void ASTContext::lookupInSwiftModule(
@@ -1140,7 +1141,7 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
11401141
if (!M)
11411142
return nullptr;
11421143
M->lookupValue(getIdentifier(getProtocolName(kind)),
1143-
NLKind::UnqualifiedLookup, results);
1144+
NLKind::UnqualifiedLookup, NL_UnqualifiedDefault, results);
11441145

11451146
for (auto result : results) {
11461147
if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
@@ -5194,7 +5195,8 @@ static NominalTypeDecl *findUnderlyingTypeInModule(ASTContext &ctx,
51945195
ModuleDecl *module) {
51955196
// Find all of the declarations with this name in the Swift module.
51965197
SmallVector<ValueDecl *, 1> results;
5197-
module->lookupValue(name, NLKind::UnqualifiedLookup, results);
5198+
module->lookupValue(name, NLKind::UnqualifiedLookup, NL_UnqualifiedDefault,
5199+
results);
51985200
for (auto result : results) {
51995201
if (auto nominal = dyn_cast<NominalTypeDecl>(result))
52005202
return nominal;

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)

lib/AST/ASTScopeCreation.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/SourceFile.h"
3131
#include "swift/AST/Stmt.h"
3232
#include "swift/AST/TypeRepr.h"
33+
#include "swift/AST/TypeCheckRequests.h"
3334
#include "swift/Basic/Debug.h"
3435
#include "swift/Basic/STLExtras.h"
3536
#include "llvm/Support/Compiler.h"
@@ -311,7 +312,6 @@ class NodeAdder
311312
VISIT_AND_IGNORE(PoundDiagnosticDecl)
312313
VISIT_AND_IGNORE(MissingDecl)
313314
VISIT_AND_IGNORE(MissingMemberDecl)
314-
VISIT_AND_IGNORE(MacroExpansionDecl)
315315

316316
// Only members of the active clause are in scope, and those
317317
// are visited separately.
@@ -347,6 +347,7 @@ class NodeAdder
347347
VISIT_AND_CREATE(CaseStmt, CaseStmtScope)
348348
VISIT_AND_CREATE(AbstractFunctionDecl, AbstractFunctionDeclScope)
349349
VISIT_AND_CREATE(MacroDecl, MacroDeclScope)
350+
VISIT_AND_CREATE(MacroExpansionDecl, MacroExpansionDeclScope)
350351

351352
#undef VISIT_AND_CREATE
352353

@@ -711,6 +712,7 @@ NO_NEW_INSERTION_POINT(IfStmtScope)
711712
NO_NEW_INSERTION_POINT(RepeatWhileScope)
712713
NO_NEW_INSERTION_POINT(SubscriptDeclScope)
713714
NO_NEW_INSERTION_POINT(MacroDeclScope)
715+
NO_NEW_INSERTION_POINT(MacroExpansionDeclScope)
714716
NO_NEW_INSERTION_POINT(SwitchStmtScope)
715717
NO_NEW_INSERTION_POINT(WhileStmtScope)
716718

@@ -1132,10 +1134,17 @@ void DefaultArgumentInitializerScope::
11321134
void AttachedPropertyWrapperScope::
11331135
expandAScopeThatDoesNotCreateANewInsertionPoint(
11341136
ScopeCreator &scopeCreator) {
1135-
if (auto *args = attr->getArgs()) {
1137+
if (auto *args = attr->getArgs())
1138+
for (auto arg : *args)
1139+
scopeCreator.addToScopeTree(arg.getExpr(), this);
1140+
}
1141+
1142+
void MacroExpansionDeclScope::
1143+
expandAScopeThatDoesNotCreateANewInsertionPoint(
1144+
ScopeCreator &scopeCreator) {
1145+
if (auto *args = decl->getArgs())
11361146
for (auto arg : *args)
11371147
scopeCreator.addToScopeTree(arg.getExpr(), this);
1138-
}
11391148
}
11401149

11411150
#pragma mark expandScope

0 commit comments

Comments
 (0)