Skip to content

[Macros] Mangle attached macro expansions based only on syntactic information #65032

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
12 changes: 6 additions & 6 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,13 @@ Entities

macro-discriminator-list ::= macro-discriminator-list? file-discriminator? macro-expansion-operator INDEX

macro-expansion-operator ::= identifier 'fMa' // attached accessor macro
macro-expansion-operator ::= identifier 'fMA' // attached member-attribute macro
macro-expansion-operator ::= decl-name identifier 'fMa' // attached accessor macro
macro-expansion-operator ::= decl-name identifier 'fMA' // attached member-attribute macro
macro-expansion-operator ::= identifier 'fMf' // freestanding macro
macro-expansion-operator ::= identifier 'fMm' // attached member macro
macro-expansion-operator ::= identifier 'fMp' // attached peer macro
macro-expansion-operator ::= identifier 'fMc' // attached conformance macro
macro-expansion-operator ::= identifier 'fMu' // uniquely-named entity
macro-expansion-operator ::= decl-name identifier 'fMm' // attached member macro
macro-expansion-operator ::= decl-name identifier 'fMp' // attached peer macro
macro-expansion-operator ::= decl-name identifier 'fMc' // attached conformance macro
macro-expansion-operator ::= decl-name identifier 'fMu' // uniquely-named entity

file-discriminator ::= identifier 'Ll' // anonymous file-discriminated declaration

Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ class ASTMangler : public Mangler {
void appendType(Type type, GenericSignature sig,
const ValueDecl *forDecl = nullptr);

void appendDeclName(const ValueDecl *decl);
void appendDeclName(
const ValueDecl *decl, DeclBaseName name = DeclBaseName());

GenericTypeParamType *appendAssocType(DependentMemberType *DepTy,
GenericSignature sig,
Expand Down
34 changes: 25 additions & 9 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1006,8 +1006,9 @@ static Optional<std::string> getOverriddenSwiftProtocolObjCName(
return None;
}

void ASTMangler::appendDeclName(const ValueDecl *decl) {
DeclBaseName name = decl->getBaseName();
void ASTMangler::appendDeclName(const ValueDecl *decl, DeclBaseName name) {
if (name.empty())
name = decl->getBaseName();
assert(!name.isSpecial() && "Cannot print special names");

auto *synthesizedTypeAttr =
Expand Down Expand Up @@ -4022,28 +4023,43 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
const Decl *decl, CustomAttr *attr, MacroRole role) {
beginMangling();

// Append the context and name of the declaration.
// We don't mangle the declaration itself because doing so requires semantic
// information (e.g., its interface type), which introduces cyclic
// dependencies.
const Decl *attachedTo = decl;
DeclBaseName attachedToName;
if (auto valueDecl = dyn_cast<ValueDecl>(decl)) {
if (role != MacroRole::MemberAttribute) {
appendAnyDecl(valueDecl);
} else {
// Appending the member would result in a cycle since `VarDecl` appends
// its type, which would then loop back around to getting the attributes
// again. We'll instead add a discriminator for each member.
appendContextOf(valueDecl);
appendContextOf(valueDecl);

// Mangle the name, replacing special names with their user-facing names.
attachedToName = valueDecl->getName().getBaseName();
if (attachedToName.isSpecial()) {
attachedToName =
decl->getASTContext().getIdentifier(attachedToName.userFacingName());
}
appendDeclName(valueDecl, attachedToName);

// For member attribute macros, the attribute is attached to the enclosing
// declaration.
if (role == MacroRole::MemberAttribute) {
attachedTo = decl->getDeclContext()->getAsDecl();
}
} else {
appendContext(decl->getDeclContext(), "");
appendIdentifier("_");
}

// Determine the name of the macro.
DeclBaseName macroName;
if (auto *macroDecl = attachedTo->getResolvedMacro(attr)) {
macroName = macroDecl->getName().getBaseName();
} else {
macroName = decl->getASTContext().getIdentifier("__unknown_macro__");
}

// FIXME: attached macro discriminators should take attachedToName into
// account.
appendMacroExpansionOperator(
macroName.userFacingName(), role,
decl->getAttachedMacroDiscriminator(macroName, role, attr));
Expand Down
35 changes: 31 additions & 4 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4061,47 +4061,74 @@ static bool isMacroExpansionNodeKind(Node::Kind kind) {

NodePointer Demangler::demangleMacroExpansion() {
Node::Kind kind;
bool isAttached;
bool isFreestanding;
switch (nextChar()) {
case 'a':
kind = Node::Kind::AccessorAttachedMacroExpansion;
isAttached = true;
isFreestanding = false;
break;

case 'A':
kind = Node::Kind::MemberAttributeAttachedMacroExpansion;
isAttached = true;
isFreestanding = false;
break;

case 'f':
kind = Node::Kind::FreestandingMacroExpansion;
isAttached = false;
isFreestanding = true;
break;

case 'm':
kind = Node::Kind::MemberAttachedMacroExpansion;
isAttached = true;
isFreestanding = false;
break;

case 'p':
kind = Node::Kind::PeerAttachedMacroExpansion;
isAttached = true;
isFreestanding = false;
break;

case 'c':
kind = Node::Kind::ConformanceAttachedMacroExpansion;
isAttached = true;
isFreestanding = false;
break;

case 'u':
kind = Node::Kind::MacroExpansionUniqueName;
isAttached = false;
isFreestanding = false;
break;

default:
return nullptr;
}

NodePointer name = popNode(Node::Kind::Identifier);
NodePointer privateDiscriminator = popNode(Node::Kind::PrivateDeclName);
NodePointer macroName = popNode(Node::Kind::Identifier);
NodePointer privateDiscriminator = nullptr;
if (isFreestanding)
privateDiscriminator = popNode(Node::Kind::PrivateDeclName);
NodePointer attachedName = nullptr;
if (isAttached)
attachedName = popNode(isDeclName);

NodePointer context = popNode(isMacroExpansionNodeKind);
if (!context)
context = popContext();
NodePointer discriminator = demangleIndexAsNode();
auto result = createWithChildren(
kind, context, name, discriminator);
NodePointer result;
if (isAttached) {
result = createWithChildren(
kind, context, attachedName, macroName, discriminator);
} else {
result = createWithChildren(kind, context, macroName, discriminator);
}
if (privateDiscriminator)
result->addChild(privateDiscriminator, *this);
return result;
Expand Down
30 changes: 20 additions & 10 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1434,28 +1434,38 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
/*hasName*/ true);
case Node::Kind::AccessorAttachedMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "accessor macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
/*hasName*/true,
("accessor macro @" +
nodeToString(Node->getChild(2)) + " expansion #"),
(int)Node->getChild(3)->getIndex() + 1);
case Node::Kind::FreestandingMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "freestanding macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
case Node::Kind::MemberAttributeAttachedMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "member attribute macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
/*hasName*/true,
("member attribute macro @" +
nodeToString(Node->getChild(2)) + " expansion #"),
(int)Node->getChild(3)->getIndex() + 1);
case Node::Kind::MemberAttachedMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "member macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
/*hasName*/true,
("member macro @" + nodeToString(Node->getChild(2)) +
" expansion #"),
(int)Node->getChild(3)->getIndex() + 1);
case Node::Kind::PeerAttachedMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "peer macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
/*hasName*/true,
("peer macro @" + nodeToString(Node->getChild(2)) +
" expansion #"),
(int)Node->getChild(3)->getIndex() + 1);
case Node::Kind::ConformanceAttachedMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "conformance macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
/*hasName*/true,
("conformance macro @" + nodeToString(Node->getChild(2)) +
" expansion #"),
(int)Node->getChild(3)->getIndex() + 1);
case Node::Kind::MacroExpansionUniqueName:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "unique name #",
Expand Down
25 changes: 10 additions & 15 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2908,51 +2908,46 @@ ManglingError Remangler::mangleFreestandingMacroExpansion(
ManglingError Remangler::mangleAccessorAttachedMacroExpansion(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
Buffer << "fMa";
return mangleChildNode(node, 2, depth + 1);
return mangleChildNode(node, 3, depth + 1);
}

ManglingError Remangler::mangleMemberAttributeAttachedMacroExpansion(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
Buffer << "fMA";
return mangleChildNode(node, 2, depth + 1);
return mangleChildNode(node, 3, depth + 1);
}

ManglingError Remangler::mangleMemberAttachedMacroExpansion(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
Buffer << "fMm";
return mangleChildNode(node, 2, depth + 1);
return mangleChildNode(node, 3, depth + 1);
}

ManglingError Remangler::manglePeerAttachedMacroExpansion(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
Buffer << "fMp";
return mangleChildNode(node, 2, depth + 1);
return mangleChildNode(node, 3, depth + 1);
}

ManglingError Remangler::mangleConformanceAttachedMacroExpansion(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
Buffer << "fMc";
return mangleChildNode(node, 2, depth + 1);
return mangleChildNode(node, 3, depth + 1);
}

ManglingError Remangler::mangleMacroExpansionUniqueName(
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/TypeCheckMacros.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,7 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
Optional<unsigned> swift::expandAccessors(
AbstractStorageDecl *storage, CustomAttr *attr, MacroDecl *macro
) {
(void)storage->getInterfaceType();
// Evaluate the macro.
auto macroSourceFile = evaluateAttachedMacro(macro, storage, attr,
/*passParentContext*/false,
Expand Down
4 changes: 1 addition & 3 deletions test/Demangle/Inputs/manglings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,5 @@ $s4main4TestVAA3ABCV4hereyySiFfa ---> runtime attribute generator of main.ABC.he
$s9MacroUser13testStringify1a1bySi_SitF9stringifyfMf1_ ---> freestanding macro expansion #3 of stringify in MacroUser.testStringify(a: Swift.Int, b: Swift.Int) -> ()
$s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_6methodfMu0_ ---> unique name #2 of method in freestanding macro expansion #1 of bitwidthNumberedStructs in Foo3 #1 in MacroUser.testFreestandingMacroExpansion() -> ()
@__swiftmacro_1a13testStringifyAA1bySi_SitF9stringifyfMf_ ---> freestanding macro expansion #1 of stringify in a.testStringify(a: Swift.Int, b: Swift.Int) -> ()
@__swiftmacro_15accessor_macros8MyStructV4nameSSvp17myPropertyWrapperfMa_ ---> accessor macro expansion #1 of myPropertyWrapper in accessor_macros.MyStruct.name : Swift.String
@__swiftmacro_18macro_expand_peers1SV1f1a3for_SSSi_SSSdtYaF20addCompletionHandlerfMp_ ---> peer macro expansion #1 of addCompletionHandler in macro_expand_peers.S.f(a: Swift.Int, for: Swift.String, _: Swift.Double) async -> Swift.String
@__swiftmacro_25macro_expand_conformances7GenericV20DelegatedConformancefMc_ ---> conformance macro expansion #1 of DelegatedConformance in macro_expand_conformances.Generic
@__swiftmacro_18macro_expand_peers1SV1f20addCompletionHandlerfMp_ ---> peer macro @addCompletionHandler expansion #1 of f in macro_expand_peers.S
@__swiftmacro_9MacroUser16MemberNotCoveredV33_4361AD9339943F52AE6186DD51E04E91Ll0dE0fMf0_ ---> freestanding macro expansion #2 of NotCovered(in _4361AD9339943F52AE6186DD51E04E91) in MacroUser.MemberNotCovered
4 changes: 2 additions & 2 deletions test/Macros/accessor_macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct MyStruct {

@myPropertyWrapper
var name: String
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV4nameSSvp17myPropertyWrapperfMa_.swift
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV4name17myPropertyWrapperfMa_.swift
// CHECK-DUMP: get {
// CHECK-DUMP: _name.wrappedValue
// CHECK-DUMP: }
Expand All @@ -53,7 +53,7 @@ struct MyStruct {

@myPropertyWrapper
var birthDate: Date?
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV9birthDateAA0F0VSgvp17myPropertyWrapperfMa_.swift
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV9birthDate17myPropertyWrapperfMa_.swift
// CHECK-DUMP: get {
// CHECK-DUMP: _birthDate.wrappedValue
// CHECK-DUMP: }
Expand Down
2 changes: 1 addition & 1 deletion test/Macros/macro_expand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct Bad {}
// CHECK-DIAGS: error: macro expansion cannot introduce default literal type '_ImageLiteralType'
// CHECK-DIAGS: error: macro expansion cannot introduce default literal type '_FileReferenceLiteralType'

// CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser3BadV7InvalidfMp_.swift
// CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser3Bad7InvalidfMp_.swift
// CHECK-DIAGS: import Swift
// CHECK-DIAGS: precedencegroup MyPrecedence {}
// CHECK-DIAGS: @attached(member) macro myMacro()
Expand Down
4 changes: 2 additions & 2 deletions test/Macros/macro_expand_conformances.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct S {}
@Hashable
struct S2 {}

// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances1SV9EquatablefMc_.swift
// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances1S9EquatablefMc_.swift
// CHECK-DUMP: extension S : Equatable {}

// CHECK: true
Expand All @@ -55,7 +55,7 @@ struct Wrapped: P {
@DelegatedConformance
struct Generic<Element> {}

// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances7GenericV20DelegatedConformancefMc_.swift
// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances7Generic20DelegatedConformancefMc_.swift
// CHECK-DUMP: extension Generic : P where Element: P {}

func requiresP(_ value: (some P).Type) {
Expand Down
Loading