Skip to content

[Macros] Deserialization and printing for @attached. #63040

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
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
10 changes: 10 additions & 0 deletions include/swift/AST/MacroDeclaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ enum class MacroRole: uint32_t {
/// The contexts in which a particular macro declaration can be used.
using MacroRoles = OptionSet<MacroRole>;

/// Retrieve the string form of the given macro role, as written on the
/// corresponding attribute.
StringRef getMacroRoleString(MacroRole role);

/// Whether a macro with the given set of macro contexts is freestanding, i.e.,
/// written in the source code with the `#` syntax.
bool isFreestandingMacro(MacroRoles contexts);
Expand All @@ -53,6 +57,12 @@ enum class MacroIntroducedDeclNameKind {
Arbitrary,
};

/// Whether a macro-introduced name of this kind requires an argument.
bool macroIntroducedNameRequiresArgument(MacroIntroducedDeclNameKind kind);

StringRef getMacroIntroducedDeclNameString(
MacroIntroducedDeclNameKind kind);

class MacroIntroducedDeclName {
public:
using Kind = MacroIntroducedDeclNameKind;
Expand Down
24 changes: 24 additions & 0 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,30 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
break;
}

case DAK_Attached: {
Printer.printAttrName("@attached");
Printer << "(";
auto Attr = cast<AttachedAttr>(this);
Printer << getMacroRoleString(Attr->getMacroRole());
if (!Attr->getNames().empty()) {
Printer << ", names: ";
interleave(
Attr->getNames(),
[&](MacroIntroducedDeclName name) {
Printer << getMacroIntroducedDeclNameString(name.getKind());
if (macroIntroducedNameRequiresArgument(name.getKind())) {
Printer << "(" << name.getIdentifier() << ")";
}
},
[&] {
Printer << ", ";
}
);
}
Printer << ")";
break;
}

case DAK_Count:
llvm_unreachable("exceed declaration attribute kinds");

Expand Down
48 changes: 48 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9672,6 +9672,54 @@ BuiltinTupleDecl::BuiltinTupleDecl(Identifier Name, DeclContext *Parent)
: NominalTypeDecl(DeclKind::BuiltinTuple, Parent, Name, SourceLoc(),
ArrayRef<InheritedEntry>(), nullptr) {}

StringRef swift::getMacroRoleString(MacroRole role) {
switch (role) {
case MacroRole::Expression:
return "expression";

case MacroRole::FreestandingDeclaration:
return "freestanding";

case MacroRole::Accessor:
return "accessor";
}
}

bool swift::macroIntroducedNameRequiresArgument(
MacroIntroducedDeclNameKind kind
) {
switch (kind) {
case MacroIntroducedDeclNameKind::Named:
case MacroIntroducedDeclNameKind::Prefixed:
case MacroIntroducedDeclNameKind::Suffixed:
return true;

case MacroIntroducedDeclNameKind::Overloaded:
case MacroIntroducedDeclNameKind::Arbitrary:
return false;
}
}

StringRef swift::getMacroIntroducedDeclNameString(
MacroIntroducedDeclNameKind kind) {
switch (kind) {
case MacroIntroducedDeclNameKind::Named:
return "named";

case MacroIntroducedDeclNameKind::Overloaded:
return "overloaded";

case MacroIntroducedDeclNameKind::Prefixed:
return "prefixed";

case MacroIntroducedDeclNameKind::Suffixed:
return "suffixed";

case MacroIntroducedDeclNameKind::Arbitrary:
return "arbitrary";
}
}

static MacroRoles freestandingMacroRoles =
(MacroRoles() |
MacroRole::Expression |
Expand Down
19 changes: 2 additions & 17 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2236,21 +2236,6 @@ static Optional<MacroRole> getMacroRole(
return role;
}

/// Determine whether a macro-introduced name requires an argument (which is
/// always a string literal).
static bool introducedNameRequiresArgument(MacroIntroducedDeclNameKind kind) {
switch (kind) {
case MacroIntroducedDeclNameKind::Named:
case MacroIntroducedDeclNameKind::Prefixed:
case MacroIntroducedDeclNameKind::Suffixed:
return true;

case MacroIntroducedDeclNameKind::Overloaded:
case MacroIntroducedDeclNameKind::Arbitrary:
return false;
}
}

static Optional<MacroIntroducedDeclNameKind>
getMacroIntroducedDeclNameKind(Identifier name) {
return llvm::StringSwitch<Optional<MacroIntroducedDeclNameKind>>(name.str())
Expand Down Expand Up @@ -2307,7 +2292,7 @@ static SmallVector<MacroIntroducedDeclName, 2> getMacroIntroducedNames(
continue;
}

if (introducedNameRequiresArgument(*introducedKind)) {
if (macroIntroducedNameRequiresArgument(*introducedKind)) {
diags.diagnose(
arg.getExpr()->getLoc(),
diag::macro_attribute_introduced_name_requires_argument,
Expand Down Expand Up @@ -2352,7 +2337,7 @@ static SmallVector<MacroIntroducedDeclName, 2> getMacroIntroducedNames(
continue;
}

if (!introducedNameRequiresArgument(*introducedKind)) {
if (!macroIntroducedNameRequiresArgument(*introducedKind)) {
diags.diagnose(
call->getArgs()->getLoc(),
diag::macro_attribute_introduced_name_requires_no_argument,
Expand Down
24 changes: 24 additions & 0 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5447,6 +5447,30 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
break;
}

case decls_block::Attached_DECL_ATTR: {
bool isImplicit;
uint8_t rawMacroRole;
uint64_t numNames;
ArrayRef<uint64_t> introducedDeclNames;
serialization::decls_block::AttachedDeclAttrLayout::
readRecord(scratch, isImplicit, rawMacroRole, numNames,
introducedDeclNames);
auto role = *getActualMacroRole(rawMacroRole);
if (introducedDeclNames.size() != numNames * 2)
return MF.diagnoseFatal();
SmallVector<MacroIntroducedDeclName, 1> names;
for (unsigned i = 0; i < introducedDeclNames.size(); i += 2) {
auto kind = getActualMacroIntroducedDeclNameKind(
(uint8_t)introducedDeclNames[i]);
auto identifier =
MF.getIdentifier(IdentifierID(introducedDeclNames[i + 1]));
names.push_back(MacroIntroducedDeclName(*kind, identifier));
}
Attr = AttachedAttr::create(
ctx, SourceLoc(), SourceRange(), role, names, isImplicit);
break;
}

#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
case decls_block::CLASS##_DECL_ATTR: { \
bool isImplicit; \
Expand Down
5 changes: 5 additions & 0 deletions test/ModuleInterface/macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@
// CHECK-NEXT: #endif
@expression public macro publicLine<T: ExpressibleByIntegerLiteral>: T = #externalMacro(module: "SomeModule", type: "Line")

// CHECK: #if compiler(>=5.3) && $Macros
// CHECK: @attached(accessor) public macro myWrapper: Swift.Void = #externalMacro(module: "SomeModule", type: "Wrapper")
// CHECK-NEXT: #endif
@attached(accessor) public macro myWrapper: Void = #externalMacro(module: "SomeModule", type: "Wrapper")

// CHECK-NOT: internalStringify
@expression macro internalStringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "SomeModule", type: "StringifyMacro")
2 changes: 2 additions & 0 deletions test/Serialization/Inputs/def_macros.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@expression public macro publicStringify<T>(_ value: T) -> (T, String) = SomeModule.StringifyMacro

@expression macro internalStringify<T>(_ value: T) -> (T, String) = SomeModule.StringifyMacro

@attached(accessor) public macro myWrapper: Void = SomeModule.MyWrapperMacro
5 changes: 5 additions & 0 deletions test/Serialization/macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ func test(a: Int, b: Int) {
_ = #internalStringify(a + b)
// expected-error@-1{{no macro named 'internalStringify'}}
}

struct TestStruct {
@myWrapper var x: Int
// expected-error@-1{{external macro implementation type 'SomeModule.MyWrapperMacro' could not be found for macro 'myWrapper'}}
}