Skip to content

[Macros] Freestanding declaration macros #62934

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

Merged
merged 1 commit into from
Jan 11, 2023
Merged
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
35 changes: 35 additions & 0 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/KnownProtocols.h"
#include "swift/AST/MacroDeclaration.h"
#include "swift/AST/Ownership.h"
#include "swift/AST/PlatformKind.h"
#include "swift/AST/Requirement.h"
Expand Down Expand Up @@ -2302,6 +2303,40 @@ class ObjCImplementationAttr final : public DeclAttribute {
}
};

class DeclarationAttr final
: public DeclAttribute,
private llvm::TrailingObjects<DeclarationAttr, MacroIntroducedDeclName> {
friend TrailingObjects;

MacroContext macroContext;
unsigned numPeerNames, numMemberNames;

DeclarationAttr(SourceLoc atLoc, SourceRange range, MacroContext macroContext,
ArrayRef<MacroIntroducedDeclName> peerNames,
ArrayRef<MacroIntroducedDeclName> memberNames,
bool implicit);

public:
static DeclarationAttr *create(ASTContext &ctx, SourceLoc atLoc,
SourceRange range, MacroContext macroContext,
ArrayRef<MacroIntroducedDeclName> peerNames,
ArrayRef<MacroIntroducedDeclName> memberNames,
bool implicit);

size_t numTrailingObjects(OverloadToken<MacroIntroducedDeclName>) const {
return numPeerNames + numMemberNames;
}

MacroContext getMacroContext() const { return macroContext; }
ArrayRef<MacroIntroducedDeclName> getPeerAndMemberNames() const;
ArrayRef<MacroIntroducedDeclName> getPeerNames() const;
ArrayRef<MacroIntroducedDeclName> getMemberNames() const;

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Declaration;
}
};

/// Attributes that may be applied to declarations.
class DeclAttributes {
/// Linked list of declaration attributes.
Expand Down
24 changes: 9 additions & 15 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8327,17 +8327,6 @@ class MissingMemberDecl : public Decl {
}
};

/// The context in which a macro can be used, which determines the syntax it
/// uses.
enum class MacroContext: uint8_t {
/// An expression macro, referenced explicitly via "#stringify" or similar
/// in the source code.
Expression = 0x01,
};

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

/// Provides a declaration of a macro.
///
/// Macros are declared within the source code with the `macro` introducer.
Expand Down Expand Up @@ -8410,7 +8399,10 @@ class MacroExpansionDecl : public Decl {
SourceLoc LeftAngleLoc, RightAngleLoc;
ArrayRef<TypeRepr *> GenericArgs;
ArgumentList *ArgList;
Decl *Rewritten;
ArrayRef<Decl *> Rewritten;

/// The referenced macro.
ConcreteDeclRef macroRef;

public:
MacroExpansionDecl(DeclContext *dc, SourceLoc poundLoc, DeclNameRef macro,
Expand All @@ -8422,7 +8414,7 @@ class MacroExpansionDecl : public Decl {
: Decl(DeclKind::MacroExpansion, dc), PoundLoc(poundLoc),
Macro(macro), MacroLoc(macroLoc),
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
GenericArgs(genericArgs), ArgList(args), Rewritten(nullptr) {}
GenericArgs(genericArgs), ArgList(args), Rewritten({}) {}

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

Expand All @@ -8436,8 +8428,10 @@ class MacroExpansionDecl : public Decl {
DeclNameLoc getMacroLoc() const { return MacroLoc; }
DeclNameRef getMacro() const { return Macro; }
ArgumentList *getArgs() const { return ArgList; }
Decl *getRewritten() const { return Rewritten; }
void setRewritten(Decl *rewritten) { Rewritten = rewritten; }
ArrayRef<Decl *> getRewritten() const { return Rewritten; }
void setRewritten(ArrayRef<Decl *> rewritten) { Rewritten = rewritten; }
ConcreteDeclRef getMacroRef() const { return macroRef; }
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }

static bool classof(const Decl *D) {
return D->getKind() == DeclKind::MacroExpansion;
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,9 @@ ERROR(macro_expansion_expr_expected_macro_identifier,PointsToFirstBadToken,
ERROR(macro_expansion_decl_expected_macro_identifier,PointsToFirstBadToken,
"expected a macro identifier for a pound literal declaration", ())

ERROR(declaration_attr_expected_kind,PointsToFirstBadToken,
"expected a declaration macro kind ('freestanding' or 'attached')", ())

ERROR(parser_round_trip_error,none,
"source file did not round-trip through the new Swift parser", ())
ERROR(parser_new_parser_errors,none,
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -6780,6 +6780,8 @@ ERROR(experimental_no_metadata_feature_can_only_be_used_when_enabled,

ERROR(expected_macro_expansion_expr,PointsToFirstBadToken,
"expected macro expansion to produce an expression", ())
ERROR(expected_macro_expansion_decls,PointsToFirstBadToken,
"expected macro expansion to produce declarations", ())
ERROR(macro_undefined,PointsToFirstBadToken,
"no macro named %0", (Identifier))
ERROR(external_macro_not_found,none,
Expand Down Expand Up @@ -6836,6 +6838,8 @@ ERROR(macro_definition_unsupported,none,
ERROR(external_macro_arg_not_type_name,none,
"argument to `#externalMacro` must be a string literal naming "
"the external macro's %select{module|type}", (unsigned))
ERROR(attached_declaration_macro_not_supported,none,
"attached declaration macros are not yet supported", ())

//------------------------------------------------------------------------------
// MARK: Move Only Errors
Expand Down
90 changes: 90 additions & 0 deletions include/swift/AST/MacroDeclaration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//===--- MacroDeclaration.h - Swift Macro Declaration -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Data structures that configure the declaration of a macro.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_MACRO_DECLARATION_H
#define SWIFT_AST_MACRO_DECLARATION_H

#include "swift/AST/Identifier.h"

namespace swift {

/// The context in which a macro can be used, which determines the syntax it
/// uses.
enum class MacroContext: uint8_t {
/// An expression macro, referenced explicitly via "#stringify" or similar
/// in the source code.
Expression = 0x01,
/// A freestanding declaration macro.
FreestandingDeclaration = 0x02,
/// An attached declaration macro.
AttachedDeclaration = 0x03,
};

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

enum class MacroIntroducedDeclNameKind {
Named,
Overloaded,
Accessors,
Prefixed,
Suffixed,
Arbitrary,
};

class MacroIntroducedDeclName {
public:
using Kind = MacroIntroducedDeclNameKind;

private:
Kind kind;
Identifier identifier;

public:
MacroIntroducedDeclName(Kind kind, Identifier identifier = Identifier())
: kind(kind), identifier(identifier) {};

static MacroIntroducedDeclName getNamed(Identifier name) {
return MacroIntroducedDeclName(Kind::Named, name);
}

static MacroIntroducedDeclName getOverloaded() {
return MacroIntroducedDeclName(Kind::Overloaded);
}

static MacroIntroducedDeclName getAccessors() {
return MacroIntroducedDeclName(Kind::Accessors);
}

static MacroIntroducedDeclName getPrefixed(Identifier prefix) {
return MacroIntroducedDeclName(Kind::Prefixed, prefix);
}

static MacroIntroducedDeclName getSuffixed(Identifier suffix) {
return MacroIntroducedDeclName(Kind::Suffixed, suffix);
}

static MacroIntroducedDeclName getArbitrary() {
return MacroIntroducedDeclName(Kind::Arbitrary);
}

Kind getKind() const { return kind; }
Identifier getIdentifier() const { return identifier; }
};

}

#endif // SWIFT_AST_MACRO_DECLARATION_H
35 changes: 35 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3765,6 +3765,23 @@ class GetTypeWrapperInitializer
bool isCached() const { return true; }
};

/// Check whether this is a protocol that has a type wrapper attribute
/// or one of its dependencies does.
class UsesTypeWrapperFeature
: public SimpleRequest<UsesTypeWrapperFeature, bool(NominalTypeDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

bool evaluate(Evaluator &evaluator, NominalTypeDecl *) const;

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

/// Find the definition of a given macro.
class MacroDefinitionRequest
: public SimpleRequest<MacroDefinitionRequest,
Expand All @@ -3785,6 +3802,24 @@ class MacroDefinitionRequest
bool isCached() const { return true; }
};

/// Find the definition of a given macro.
class ExpandMacroExpansionDeclRequest
: public SimpleRequest<ExpandMacroExpansionDeclRequest,
ArrayRef<Decl *>(MacroExpansionDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

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

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

/// Resolve an external macro given its module and type name.
class ExternalMacroDefinitionRequest
: public SimpleRequest<ExternalMacroDefinitionRequest,
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,9 @@ SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
ArrayRef<Decl *>(MacroExpansionDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SynthesizeRuntimeMetadataAttrGenerator,
Expr *(CustomAttr *, ValueDecl *),
Cached, NoLocationInfo)
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/TypeMemberVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ class TypeMemberVisitor : public DeclVisitor<ImplClass, RetTy> {
asImpl().visit(dd);
}
}

/// Visit expanded macros.
void visitMacroExpansionDecl(MacroExpansionDecl *D) {
for (auto *decl : D->getRewritten())
asImpl().visit(decl);
}
};

template<typename ImplClass, typename RetTy = void>
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,10 @@ class Parser {
bool parseDocumentationAttributeArgument(Optional<StringRef> &Metadata,
Optional<AccessLevel> &Visibility);

/// Parse the @declaration attribute.
ParserResult<DeclarationAttr> parseDeclarationAttribute(SourceLoc AtLoc,
SourceLoc Loc);

/// Parse a specific attribute.
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
PatternBindingInitializer *&initContext,
Expand Down
5 changes: 3 additions & 2 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
bool visitMacroExpansionDecl(MacroExpansionDecl *MED) {
if (MED->getArgs() && doIt(MED->getArgs()))
return true;
if (MED->getRewritten() && doIt(MED->getRewritten()))
return true;
for (auto *decl : MED->getRewritten())
if (doIt(decl))
return true;
return false;
}

Expand Down
48 changes: 48 additions & 0 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,8 @@ StringRef DeclAttribute::getAttrName() const {
return "_expose";
case DAK_Documentation:
return "_documentation";
case DAK_Declaration:
return "declaration";
}
llvm_unreachable("bad DeclAttrKind");
}
Expand Down Expand Up @@ -2308,6 +2310,52 @@ bool CustomAttr::isArgUnsafe() const {
return isArgUnsafeBit;
}

DeclarationAttr::DeclarationAttr(SourceLoc atLoc, SourceRange range,
MacroContext macroContext,
ArrayRef<MacroIntroducedDeclName> peerNames,
ArrayRef<MacroIntroducedDeclName> memberNames,
bool implicit)
: DeclAttribute(DAK_Declaration, atLoc, range, implicit),
macroContext(macroContext), numPeerNames(peerNames.size()),
numMemberNames(memberNames.size()) {
auto *trailingNamesBuffer = getTrailingObjects<MacroIntroducedDeclName>();
std::uninitialized_copy(peerNames.begin(), peerNames.end(),
trailingNamesBuffer);
std::uninitialized_copy(memberNames.begin(), memberNames.end(),
trailingNamesBuffer + peerNames.size());
}

DeclarationAttr *
DeclarationAttr::create(ASTContext &ctx, SourceLoc atLoc, SourceRange range,
MacroContext macroContext,
ArrayRef<MacroIntroducedDeclName> peerNames,
ArrayRef<MacroIntroducedDeclName> memberNames,
bool implicit) {
unsigned size = totalSizeToAlloc<MacroIntroducedDeclName>(
peerNames.size() + memberNames.size());
auto *mem = ctx.Allocate(size, alignof(DeclarationAttr));
return new (mem) DeclarationAttr(atLoc, range, macroContext, peerNames,
memberNames, implicit);
}

ArrayRef<MacroIntroducedDeclName> DeclarationAttr::getPeerAndMemberNames() const {
return {
getTrailingObjects<MacroIntroducedDeclName>(),
numPeerNames + numMemberNames
};
}

ArrayRef<MacroIntroducedDeclName> DeclarationAttr::getPeerNames() const {
return {getTrailingObjects<MacroIntroducedDeclName>(), numPeerNames};
}

ArrayRef<MacroIntroducedDeclName> DeclarationAttr::getMemberNames() const {
return {
getTrailingObjects<MacroIntroducedDeclName>() + numPeerNames,
numMemberNames
};
}

const DeclAttribute *
DeclAttributes::getEffectiveSendableAttr() const {
const NonSendableAttr *assumedAttr = nullptr;
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9713,6 +9713,8 @@ MacroContexts MacroDecl::getMacroContexts() const {
MacroContexts contexts = None;
if (getAttrs().hasAttribute<ExpressionAttr>())
contexts |= MacroContext::Expression;
for (auto attr : getAttrs().getAttributes<DeclarationAttr>())
contexts |= attr->getMacroContext();
return contexts;
}

Expand Down
1 change: 1 addition & 0 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "swift/AST/ParameterList.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Debug.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/SourceManager.h"
Expand Down
Loading