Skip to content

[Macros] Freestanding macro expansions in code blocks #63217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion include/swift/AST/ASTScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,12 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
static const ASTScopeImpl *findStartingScopeForLookup(SourceFile *,
const SourceLoc where);

protected:
public:
/// Not const because may reexpand some scopes.
ASTScopeImpl *findInnermostEnclosingScope(SourceLoc,
NullablePtr<raw_ostream>);

protected:
ASTScopeImpl *findInnermostEnclosingScopeImpl(SourceLoc,
NullablePtr<raw_ostream>,
SourceManager &,
Expand Down Expand Up @@ -1216,6 +1218,29 @@ class MacroDeclScope final : public ASTScopeImpl {
NullablePtr<const GenericParamList> genericParams() const override;
};

class MacroExpansionDeclScope final : public ASTScopeImpl {
public:
MacroExpansionDecl *const decl;

MacroExpansionDeclScope(MacroExpansionDecl *d) : decl(d) {}
virtual ~MacroExpansionDeclScope() {}

protected:
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
std::string getClassName() const override;
SourceRange
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

public:
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
Decl *getDecl() const { return decl; }
};

class AbstractStmtScope : public ASTScopeImpl {
public:
SourceRange
Expand Down
12 changes: 8 additions & 4 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ namespace swift {
class VarDecl;
class OpaqueReturnTypeRepr;
class Witness;
class MacroExpansionExpr;

namespace ast_scope {
class AbstractPatternEntryScope;
Expand Down Expand Up @@ -8452,7 +8453,8 @@ class MacroExpansionDecl : public Decl {
SourceLoc LeftAngleLoc, RightAngleLoc;
ArrayRef<TypeRepr *> GenericArgs;
ArgumentList *ArgList;
ArrayRef<Decl *> Rewritten;
// An implicit brace statement serving as the container for the expansion.
BraceStmt *Rewritten = nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brace statements imply a nested scope, which probably isn't what we want semantically. Can this become an ArrayRef<ASTNode> to mimic the [CodeBlockItemSyntax] we recently agreed upon for the macro implementation interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I was relying on BraceStmt merely as a convenient container, and the BraceStmt was never visited as a child of MacroExpransionDecl; ASTWalker directly walks the BraceStmt's children instead. I think it's better than ArrayRef<ASTNode> because we can distinguish between nullptr (expansion failure) and an empty list from the return of swift::expandFreestandingMacro(). Otherwise I would need to make it return a bool and produce indirect results into a ASTNode vector. Thoughts?


/// The referenced macro.
ConcreteDeclRef macroRef;
Expand All @@ -8469,7 +8471,7 @@ class MacroExpansionDecl : public Decl {
: Decl(DeclKind::MacroExpansion, dc), PoundLoc(poundLoc),
Macro(macro), MacroLoc(macroLoc),
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
GenericArgs(genericArgs), ArgList(args), Rewritten({}) {
GenericArgs(genericArgs), ArgList(args) {
Bits.MacroExpansionDecl.Discriminator = InvalidDiscriminator;
}

Expand All @@ -8485,10 +8487,12 @@ class MacroExpansionDecl : public Decl {
DeclNameLoc getMacroLoc() const { return MacroLoc; }
DeclNameRef getMacro() const { return Macro; }
ArgumentList *getArgs() const { return ArgList; }
ArrayRef<Decl *> getRewritten() const { return Rewritten; }
void setRewritten(ArrayRef<Decl *> rewritten) { Rewritten = rewritten; }
void setArgs(ArgumentList *args) { ArgList = args; }
BraceStmt *getRewritten() const { return Rewritten; }
void setRewritten(BraceStmt *rewritten) { Rewritten = rewritten; }
ConcreteDeclRef getMacroRef() const { return macroRef; }
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
MacroExpansionExpr *createExpr() const;

/// Returns a discriminator which determines this macro expansion's index
/// in the sequence of macro expansions within the current function.
Expand Down
10 changes: 8 additions & 2 deletions include/swift/AST/FileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,15 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
/// within this file.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupValue(DeclName name, NLKind lookupKind,
virtual void lookupValue(DeclName name, NLKind lookupKind, NLOptions options,
SmallVectorImpl<ValueDecl*> &result) const = 0;

void lookupValue(DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl*> &result) const {
lookupValue(name, lookupKind, getDefaultNLOptions(lookupKind), result);
}


/// Look up a local type declaration by its mangled name.
///
/// This does a simple local lookup, not recursively looking through imports.
Expand Down Expand Up @@ -366,7 +372,7 @@ class BuiltinUnit final : public FileUnit {
public:
explicit BuiltinUnit(ModuleDecl &M);

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

/// Find all Objective-C methods with the given selector.
Expand Down
10 changes: 10 additions & 0 deletions include/swift/AST/LookupKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ enum NLOptions : unsigned {
// Include @usableFromInline and @inlinable
NL_IncludeUsableFromInline = 1 << 6,

/// Don't expand macros.
NL_DisableMacroExpansions = 1 << 7,

/// The default set of options used for qualified name lookup.
///
/// FIXME: Eventually, add NL_ProtocolMembers to this, once all of the
Expand All @@ -79,6 +82,13 @@ static inline NLOptions operator~(NLOptions value) {
return NLOptions(~(unsigned)value);
}

static inline NLOptions getDefaultNLOptions(NLKind kind) {
switch (kind) {
case NLKind::QualifiedLookup: return NL_QualifiedDefault;
case NLKind::UnqualifiedLookup: return NL_UnqualifiedDefault;
}
}

void simple_display(llvm::raw_ostream &out, NLOptions options);

} // end namespace swift
Expand Down
10 changes: 10 additions & 0 deletions include/swift/AST/MacroDeclaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,17 @@ enum class MacroRole: uint32_t {
/// An attached macro that generates synthesized members
/// inside the declaration.
SynthesizedMembers = 0x10,
/// A freestanding code item macro.
CodeItem = 0x20,
};

/// The contexts in which a particular macro declaration can be used.
using MacroRoles = OptionSet<MacroRole>;

void simple_display(llvm::raw_ostream &out, MacroRoles roles);
bool operator==(MacroRoles lhs, MacroRoles rhs);
llvm::hash_code hash_value(MacroRoles roles);

/// Retrieve the string form of the given macro role, as written on the
/// corresponding attribute.
StringRef getMacroRoleString(MacroRole role);
Expand All @@ -62,10 +68,14 @@ StringRef getMacroRoleString(MacroRole role);
/// written in the source code with the `#` syntax.
bool isFreestandingMacro(MacroRoles contexts);

MacroRoles getFreestandingMacroRoles();

/// Whether a macro with the given set of macro contexts is attached, i.e.,
/// written in the source code as an attribute with the `@` syntax.
bool isAttachedMacro(MacroRoles contexts);

MacroRoles getAttachedMacroRoles();

enum class MacroIntroducedDeclNameKind {
Named,
Overloaded,
Expand Down
12 changes: 11 additions & 1 deletion include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,9 +637,19 @@ class ModuleDecl
/// within the current module.
///
/// This does a simple local lookup, not recursively looking through imports.
void lookupValue(DeclName Name, NLKind LookupKind,
void lookupValue(DeclName Name, NLKind LookupKind, NLOptions Options,
SmallVectorImpl<ValueDecl*> &Result) const;

/// Look up a (possibly overloaded) value set at top-level scope
/// (but with the specified access path, which may come from an import decl)
/// within the current module.
///
/// This does a simple local lookup, not recursively looking through imports.
void lookupValue(DeclName Name, NLKind LookupKind,
SmallVectorImpl<ValueDecl*> &Result) const {
lookupValue(Name, LookupKind, getDefaultNLOptions(LookupKind), Result);
}

/// Look up a local type declaration by its mangled name.
///
/// This does a simple local lookup, not recursively looking through imports.
Expand Down
9 changes: 9 additions & 0 deletions include/swift/AST/NameLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ enum class UnqualifiedLookupFlags {
// This lookup should include results that are @inlinable or
// @usableFromInline.
IncludeUsableFromInline = 1 << 5,
// This lookup should not expand macros.
DisableMacroExpansions = 1 << 6,
// This lookup should only return macros.
MacroLookup = 1 << 7,
};

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

/// Returns true if the given location is within a \c MacroDecl or a top-level
/// \c MacroExpansionDecl.
static bool isLocWithinMacroDeclOrTopLevelMacroExpansionDeclScope(
SourceFile *sf, SourceLoc loc);

SWIFT_DEBUG_DUMP;
void print(llvm::raw_ostream &) const;
void dumpOneScopeMapLocation(std::pair<unsigned, unsigned>);
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/SourceFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ class SourceFile final : public FileUnit {
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;

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

virtual void lookupVisibleDecls(ImportPath::Access accessPath,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/SynthesizedFileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SynthesizedFileUnit final : public FileUnit {
/// Add a synthesized top-level declaration.
void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); }

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

void lookupObjCMethods(
Expand Down
57 changes: 50 additions & 7 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3128,10 +3128,53 @@ class CheckRedeclarationRequest
evaluator::SideEffect) const;
};

class UnresolvedMacroReference {
private:
llvm::PointerUnion<MacroExpansionDecl *, MacroExpansionExpr *, CustomAttr *>
pointer;

public:
UnresolvedMacroReference(MacroExpansionDecl *decl) : pointer(decl) {}
UnresolvedMacroReference(MacroExpansionExpr *expr) : pointer(expr) {}
UnresolvedMacroReference(CustomAttr *attr) : pointer(attr) {}

MacroExpansionDecl *getDecl() const {
return pointer.dyn_cast<MacroExpansionDecl *>();
}
MacroExpansionExpr *getExpr() const {
return pointer.dyn_cast<MacroExpansionExpr *>();
}
CustomAttr *getAttr() const {
return pointer.dyn_cast<CustomAttr *>();
}
void *getOpaqueValue() const {
return pointer.getOpaqueValue();
}

DeclNameRef getMacroName() const;
DeclNameLoc getMacroNameLoc() const;
SourceRange getGenericArgsRange() const;
ArrayRef<TypeRepr *> getGenericArgs() const;
ArgumentList *getArgs() const;

friend bool operator==(const UnresolvedMacroReference &lhs,
const UnresolvedMacroReference &rhs) {
return lhs.getOpaqueValue() == rhs.getOpaqueValue();
}

friend llvm::hash_code hash_value(const UnresolvedMacroReference &ref) {
return reinterpret_cast<ptrdiff_t>(ref.pointer.getOpaqueValue());
}
};

void simple_display(llvm::raw_ostream &out,
const UnresolvedMacroReference &ref);

/// Resolve a given custom attribute to an attached macro declaration.
class ResolveAttachedMacroRequest
: public SimpleRequest<ResolveAttachedMacroRequest,
MacroDecl *(CustomAttr *, DeclContext *),
class ResolveMacroRequest
: public SimpleRequest<ResolveMacroRequest,
MacroDecl *(UnresolvedMacroReference, MacroRoles,
DeclContext *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;
Expand All @@ -3140,7 +3183,8 @@ class ResolveAttachedMacroRequest
friend SimpleRequest;

MacroDecl *
evaluate(Evaluator &evaluator, CustomAttr *attr, DeclContext *dc) const;
evaluate(Evaluator &evaluator, UnresolvedMacroReference macroRef,
MacroRoles roles, DeclContext *dc) const;

public:
bool isCached() const { return true; }
Expand Down Expand Up @@ -3806,16 +3850,15 @@ class MacroDefinitionRequest
/// Find the definition of a given macro.
class ExpandMacroExpansionDeclRequest
: public SimpleRequest<ExpandMacroExpansionDeclRequest,
ArrayRef<Decl *>(MacroExpansionDecl *),
BraceStmt *(MacroExpansionDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

ArrayRef<Decl *> evaluate(Evaluator &evaluator,
MacroExpansionDecl *med) const;
BraceStmt *evaluate(Evaluator &evaluator, MacroExpansionDecl *med) const;

public:
bool isCached() const { return true; }
Expand Down
8 changes: 4 additions & 4 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ SWIFT_REQUEST(TypeChecker, DefaultArgumentInitContextRequest,
SWIFT_REQUEST(TypeChecker, DefaultDefinitionTypeRequest,
Type(AssociatedTypeDecl *), Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, DefaultTypeRequest,
Type(KnownProtocolKind, const DeclContext *), SeparatelyCached,
NoLocationInfo)
Type(KnownProtocolKind, const DeclContext *),
SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, DifferentiableAttributeTypeCheckRequest,
IndexSubset *(DifferentiableAttr *),
SeparatelyCached, NoLocationInfo)
Expand Down Expand Up @@ -340,7 +340,7 @@ SWIFT_REQUEST(TypeChecker, PreCheckResultBuilderRequest,
SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
evaluator::SideEffect(NominalTypeDecl *, ImplicitMemberAction),
Uncached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ResolveAttachedMacroRequest,
SWIFT_REQUEST(TypeChecker, ResolveMacroRequest,
MacroDecl *(CustomAttr *, DeclContext *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ResolveTypeEraserTypeRequest,
Expand Down Expand Up @@ -453,7 +453,7 @@ SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
ArrayRef<Decl *>(MacroExpansionDecl *),
BraceStmt *(MacroExpansionDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
bool(Decl *),
Expand Down
6 changes: 4 additions & 2 deletions include/swift/AST/TypeMemberVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ class TypeMemberVisitor : public DeclVisitor<ImplClass, RetTy> {

/// Visit expanded macros.
void visitMacroExpansionDecl(MacroExpansionDecl *D) {
for (auto *decl : D->getRewritten())
asImpl().visit(decl);
if (auto *rewritten = D->getRewritten())
for (auto node : rewritten->getElements())
if (auto *decl = node.dyn_cast<Decl *>())
asImpl().visit(decl);
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/swift/ClangImporter/ClangModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ClangModuleUnit final : public LoadedFile {

virtual bool isSystemModule() const override;

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

virtual TypeDecl *
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ class SerializedASTFile final : public LoadedFile {

virtual bool isSystemModule() const override;

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

virtual StringRef
Expand Down
Loading