Skip to content

Commit ac4aa41

Browse files
committed
[Macros] Use macro expansion mangling for unique names in macros
Use the name mangling scheme we've devised for macro expansions to back the implementation of the macro expansion context's `getUniqueName` operation. This way, we guarantee that the names provided by macro expansions don't conflict, as well as making them demangleable so we can determine what introduced the names.
1 parent 1e6daae commit ac4aa41

File tree

13 files changed

+110
-19
lines changed

13 files changed

+110
-19
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,8 @@ Entities
395395

396396
macro-discriminator-list ::= macro-discriminator-list? 'fM' macro-expansion-operator INDEX
397397

398-
macro-expansion-operator ::= 'f' // freestanding macro
399-
macro-expansion-operator ::= 'u' // uniquely-named entity
398+
macro-expansion-operator ::= identifier 'f' // freestanding macro
399+
macro-expansion-operator ::= identifier 'u' // uniquely-named entity
400400

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

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ NODE(LazyProtocolWitnessTableAccessor)
149149
NODE(LazyProtocolWitnessTableCacheVariable)
150150
NODE(LocalDeclName)
151151
NODE(Macro)
152+
NODE(MacroExpansionUniqueName)
152153
CONTEXT_NODE(MaterializeForSet)
153154
NODE(MergedFunction)
154155
NODE(Metatype)

include/swift/Parse/Parser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ class Parser {
195195

196196
bool allowTopLevelCode() const;
197197

198+
bool isInMacroExpansion(SourceLoc loc) const;
199+
198200
const std::vector<Token> &getSplitTokens() const { return SplitTokens; }
199201

200202
void markSplitToken(tok Kind, StringRef Txt);
@@ -575,7 +577,8 @@ class Parser {
575577
return;
576578

577579
if (tok.getText().size() == 1 || Context.LangOpts.EnableDollarIdentifiers ||
578-
isInSILMode() || L->isSwiftInterface())
580+
isInSILMode() || L->isSwiftInterface() ||
581+
isInMacroExpansion(tok.getLoc()))
579582
return;
580583

581584
diagnose(tok.getLoc(), diag::dollar_identifier_decl,

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,13 @@ fileprivate struct ThrownErrorDiagnostic: DiagnosticMessage {
106106
}
107107
}
108108

109-
@_cdecl("swift_ASTGen_evaluateMacro")
109+
@_cdecl("swift_ASTGen_expandFreestandingMacro")
110110
@usableFromInline
111-
func evaluateMacro(
111+
func expandFreestandingMacro(
112112
diagEnginePtr: UnsafeMutablePointer<UInt8>,
113113
macroPtr: UnsafeRawPointer,
114+
discriminatorText: UnsafePointer<UInt8>,
115+
discriminatorTextLength: Int,
114116
sourceFilePtr: UnsafeRawPointer,
115117
sourceLocationPtr: UnsafePointer<UInt8>?,
116118
expandedSourcePointer: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
@@ -144,7 +146,13 @@ func evaluateMacro(
144146
let sourceManager = SourceManager(cxxDiagnosticEngine: diagEnginePtr)
145147
sourceManager.insert(sourceFilePtr)
146148

147-
let context = sourceManager.createMacroExpansionContext()
149+
let discriminatorBuffer = UnsafeBufferPointer(
150+
start: discriminatorText, count: discriminatorTextLength
151+
)
152+
let discriminator = String(decoding: discriminatorBuffer, as: UTF8.self)
153+
let context = sourceManager.createMacroExpansionContext(
154+
discriminator: discriminator
155+
)
148156

149157
guard let parentSyntax = token.parent else {
150158
print("not on a macro expansion node: \(token.recursiveDescription)")

lib/ASTGen/Sources/ASTGen/SourceManager.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ extension SourceManager {
145145
}
146146

147147
/// Create a new macro expansion context
148-
func createMacroExpansionContext() -> BasicMacroExpansionContext {
148+
func createMacroExpansionContext(discriminator: String = "") -> BasicMacroExpansionContext {
149149
// Collect the set of source files for this context.
150150
var sourceFiles: [SourceFileSyntax : BasicMacroExpansionContext.KnownSourceFile] = [:]
151151
for (syntax, exported) in exportedSourceFilesBySyntax {
@@ -155,6 +155,8 @@ extension SourceManager {
155155
)
156156
}
157157

158-
return BasicMacroExpansionContext(sourceFiles: sourceFiles)
158+
return BasicMacroExpansionContext(
159+
expansionDiscriminator: discriminator, sourceFiles: sourceFiles
160+
)
159161
}
160162
}

lib/Demangling/Demangler.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3902,12 +3902,18 @@ NodePointer Demangler::demangleMacroExpansion() {
39023902
kind = Node::Kind::FreestandingMacroExpansion;
39033903
break;
39043904

3905+
case 'u':
3906+
kind = Node::Kind::MacroExpansionUniqueName;
3907+
break;
3908+
39053909
default:
39063910
return nullptr;
39073911
}
39083912

39093913
NodePointer name = popNode(Node::Kind::Identifier);
3910-
NodePointer context = popContext();
3914+
NodePointer context = popNode(Node::Kind::FreestandingMacroExpansion);
3915+
if (!context)
3916+
context = popContext();
39113917
NodePointer discriminator = demangleIndexAsNode();
39123918
return createWithChildren(kind, context, name, discriminator);
39133919
}

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ class NodePrinter {
440440
case Node::Kind::LazyProtocolWitnessTableCacheVariable:
441441
case Node::Kind::LocalDeclName:
442442
case Node::Kind::Macro:
443+
case Node::Kind::MacroExpansionUniqueName:
443444
case Node::Kind::MaterializeForSet:
444445
case Node::Kind::MergedFunction:
445446
case Node::Kind::Metaclass:
@@ -1341,6 +1342,10 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
13411342
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
13421343
/*hasName*/true, "freestanding macro expansion #",
13431344
(int)Node->getChild(2)->getIndex() + 1);
1345+
case Node::Kind::MacroExpansionUniqueName:
1346+
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1347+
/*hasName*/true, "unique name #",
1348+
(int)Node->getChild(2)->getIndex() + 1);
13441349
case Node::Kind::GenericTypeParamDecl:
13451350
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
13461351
/*hasName*/ true);

lib/Demangling/OldRemangler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,13 @@ ManglingError Remangler::mangleFreestandingMacroExpansion(
10701070
return mangleChildNodes(node, depth + 1);
10711071
}
10721072

1073+
ManglingError Remangler::mangleMacroExpansionUniqueName(
1074+
Node *node, unsigned depth) {
1075+
Buffer << "fMu";
1076+
RETURN_IF_ERROR(mangleIndex(node, depth + 1));
1077+
return mangleChildNodes(node, depth + 1);
1078+
}
1079+
10731080
ManglingError Remangler::mangleAccessor(Node *storageNode,
10741081
StringRef accessorCode,
10751082
EntityContext &ctx, unsigned depth) {

lib/Demangling/Remangler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,6 +2880,14 @@ ManglingError Remangler::mangleFreestandingMacroExpansion(
28802880
return mangleChildNode(node, 2, depth + 1);
28812881
}
28822882

2883+
ManglingError Remangler::mangleMacroExpansionUniqueName(
2884+
Node *node, unsigned depth) {
2885+
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
2886+
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
2887+
Buffer << "fMu";
2888+
return mangleChildNode(node, 2, depth + 1);
2889+
}
2890+
28832891
ManglingError Remangler::mangleSuffix(Node *node, unsigned depth) {
28842892
// Just add the suffix back on.
28852893
Buffer << node->getText();

lib/Parse/Parser.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,18 @@ bool Parser::allowTopLevelCode() const {
520520
return SF.isScriptMode();
521521
}
522522

523+
bool Parser::isInMacroExpansion(SourceLoc loc) const {
524+
if (loc.isInvalid())
525+
return false;
526+
527+
auto bufferID = SourceMgr.findBufferContainingLoc(loc);
528+
auto generatedSourceInfo = SourceMgr.getGeneratedSourceInfo(bufferID);
529+
if (!generatedSourceInfo)
530+
return false;
531+
532+
return true;
533+
}
534+
523535
const Token &Parser::peekToken() {
524536
return L->peekNextToken();
525537
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ extern "C" void *swift_ASTGen_resolveMacroType(const void *macroType);
3939

4040
extern "C" void swift_ASTGen_destroyMacro(void *macro);
4141

42-
extern "C" ptrdiff_t swift_ASTGen_evaluateMacro(
43-
void *diagEngine, void *macro, void *sourceFile,
42+
extern "C" ptrdiff_t swift_ASTGen_expandFreestandingMacro(
43+
void *diagEngine, void *macro,
44+
const char *discriminator,
45+
ptrdiff_t discriminatorLength,
46+
void *sourceFile,
4447
const void *sourceLocation,
4548
const char **evaluatedSource, ptrdiff_t *evaluatedSourceLength);
4649

@@ -412,6 +415,7 @@ Expr *swift::expandMacroExpr(
412415
return nullptr;
413416
}
414417

418+
std::string discriminator;
415419
auto macroDef = macro->getDefinition();
416420
switch (macroDef.kind) {
417421
case MacroDefinition::Kind::Undefined:
@@ -462,11 +466,17 @@ Expr *swift::expandMacroExpr(
462466
if (!astGenSourceFile)
463467
return nullptr;
464468

469+
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
470+
Mangle::ASTMangler mangler;
471+
discriminator = mangler.mangleMacroExpansion(expansionExpr);
472+
}
473+
465474
const char *evaluatedSourceAddress;
466475
ptrdiff_t evaluatedSourceLength;
467-
swift_ASTGen_evaluateMacro(
476+
swift_ASTGen_expandFreestandingMacro(
468477
&ctx.Diags,
469478
externalDef.opaqueHandle,
479+
discriminator.data(), discriminator.size(),
470480
astGenSourceFile, expr->getStartLoc().getOpaquePointerValue(),
471481
&evaluatedSourceAddress, &evaluatedSourceLength);
472482
if (!evaluatedSourceAddress)
@@ -483,12 +493,10 @@ Expr *swift::expandMacroExpr(
483493

484494
// Figure out a reasonable name for the macro expansion buffer.
485495
std::string bufferName;
486-
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
487-
Mangle::ASTMangler mangler;
488-
bufferName = adjustMacroExpansionBufferName(
489-
mangler.mangleMacroExpansion(expansionExpr));
490-
} else {
496+
if (discriminator.empty())
491497
bufferName = "macro-expansion";
498+
else {
499+
bufferName = adjustMacroExpansionBufferName(discriminator);
492500
}
493501

494502
// Dump macro expansions to standard output, if requested.
@@ -628,11 +636,15 @@ bool swift::expandFreestandingDeclarationMacro(
628636
if (!astGenSourceFile)
629637
return false;
630638

639+
Mangle::ASTMangler mangler;
640+
auto discriminator = mangler.mangleMacroExpansion(med);
641+
631642
const char *evaluatedSourceAddress;
632643
ptrdiff_t evaluatedSourceLength;
633-
swift_ASTGen_evaluateMacro(
644+
swift_ASTGen_expandFreestandingMacro(
634645
&ctx.Diags,
635646
externalDef.opaqueHandle,
647+
discriminator.data(), discriminator.size(),
636648
astGenSourceFile, med->getStartLoc().getOpaquePointerValue(),
637649
&evaluatedSourceAddress, &evaluatedSourceLength);
638650
if (!evaluatedSourceAddress)

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,25 @@ public struct DefineBitwidthNumberedStructsMacro: DeclarationMacro {
218218
throw CustomError.message("#bitwidthNumberedStructs macro requires a string literal")
219219
}
220220

221+
if prefix.content.text == "BUG" {
222+
return [
223+
"""
224+
225+
struct \(raw: prefix) {
226+
func \(context.createUniqueName("method"))() { return 1 }
227+
func \(context.createUniqueName("method"))() { return 1 }
228+
}
229+
"""
230+
]
231+
}
232+
221233
return [8, 16, 32, 64].map { bitwidth in
222234
"""
223235
224-
struct \(raw: prefix)\(raw: String(bitwidth)) { }
236+
struct \(raw: prefix)\(raw: String(bitwidth)) {
237+
func \(context.createUniqueName("method"))() { }
238+
func \(context.createUniqueName("method"))() { }
239+
}
225240
"""
226241
}
227242
}

test/Macros/macro_expand.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ func testFreestandingMacroExpansion() {
134134
struct Foo {
135135
#bitwidthNumberedStructs("MyIntOne")
136136
}
137+
137138
// CHECK: MyIntOne8
138139
print(Foo.MyIntOne8.self)
139140
// CHECK: MyIntOne16
@@ -155,6 +156,17 @@ func testFreestandingMacroExpansion() {
155156
// CHECK: MyIntTwo64
156157
print(Foo2.MyIntTwo64.self)
157158

159+
#if TEST_DIAGNOSTICS
160+
struct Foo3 {
161+
#bitwidthNumberedStructs("BUG", blah: false)
162+
// expected-note@-1 4{{in expansion of macro 'bitwidthNumberedStructs' here}}
163+
// CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_.swift
164+
// CHECK-DIAGS: struct BUG {
165+
// CHECK-DIAGS: func $s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_6methodfMu_()
166+
// CHECK-DIAGS: func $s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_6methodfMu0{{_?}}()
167+
}
168+
#endif
169+
158170
// FIXME: Declaration macro expansions in BraceStmt don't work yet.
159171
// HECK: MyIntGlobal8
160172
// print(MyIntGlobal8.self)

0 commit comments

Comments
 (0)