Skip to content

Commit 133c936

Browse files
authored
Merge pull request swiftlang#63359 from DougGregor/more-macro-fixes
More macro fixes
2 parents 23a4d2b + a54bc74 commit 133c936

File tree

5 files changed

+68
-20
lines changed

5 files changed

+68
-20
lines changed

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,11 @@ func expandFreestandingMacro(
199199
print("not on a macro expansion node: \(token.recursiveDescription)")
200200
return -1
201201
}
202+
macroName = parentExpansion.macro.text
202203
let decls = try declMacro.expansion(
203204
of: sourceManager.detach(parentExpansion, in: context),
204205
in: context
205206
)
206-
macroName = parentExpansion.macro.text
207207
evaluatedSyntax = Syntax(CodeBlockItemListSyntax(
208208
decls.map { CodeBlockItemSyntax(item: .decl($0)) }))
209209

@@ -213,11 +213,12 @@ func expandFreestandingMacro(
213213
}
214214
} catch {
215215
// Record the error
216-
context.diagnose(
217-
Diagnostic(
216+
sourceManager.diagnose(
217+
diagnostic: Diagnostic(
218218
node: parentSyntax,
219219
message: ThrownErrorDiagnostic(message: String(describing: error))
220-
)
220+
),
221+
messageSuffix: " (from macro '\(macroName)')"
221222
)
222223
return -1
223224
}
@@ -426,11 +427,12 @@ func expandAttachedMacro(
426427
} catch {
427428
// Record the error
428429
// FIXME: Need to decide where to diagnose the error:
429-
context.diagnose(
430-
Diagnostic(
430+
sourceManager.diagnose(
431+
diagnostic: Diagnostic(
431432
node: Syntax(declarationNode),
432433
message: ThrownErrorDiagnostic(message: String(describing: error))
433-
)
434+
),
435+
messageSuffix: " (from macro '\(macroName)')"
434436
)
435437

436438
return 1

lib/ASTGen/Sources/ASTGen/SourceManager.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,17 @@ extension SourceManager {
7676
return nil
7777
}
7878

79-
// Recursively find the root and its offset. This also must succeed.
79+
// Recursively find the root and its offset.
8080
guard let (rootSF, parentOffset) = rootSourceFile(of: parent) else {
8181
return nil
8282
}
8383

84-
// Add our offset to our parent's offset, and we're done.
85-
return (rootSF, parentOffset + SourceLength(utf8Length: offset))
84+
// The position of our node is...
85+
let finalPosition =
86+
node.position // Our position relative to its root
87+
+ SourceLength(utf8Length: offset) // and that root's offset in its parent
88+
+ SourceLength(utf8Length: parentOffset.utf8Offset)
89+
return (rootSF, finalPosition)
8690
}
8791

8892
/// Produce the C++ source location for a given position based on a
@@ -106,7 +110,7 @@ extension SourceManager {
106110
// node.
107111
let position = position ?? node.position
108112
let offsetWithinSyntaxNode =
109-
position.utf8Offset - node.root.position.utf8Offset
113+
position.utf8Offset - node.position.utf8Offset
110114
let offsetFromSourceFile = rootPosition.utf8Offset + offsetWithinSyntaxNode
111115

112116
// Compute the resulting address.

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,6 @@ public enum AddBlocker: ExpressionMacro {
147147
of node: some FreestandingMacroExpansionSyntax,
148148
in context: some MacroExpansionContext
149149
) -> ExprSyntax {
150-
let opTable = OperatorTable.standardOperators
151-
let node = opTable.foldAll(node) { error in
152-
context.diagnose(error.asDiagnostic)
153-
}.asProtocol(FreestandingMacroExpansionSyntax.self)!
154-
155-
guard let argument = node.argumentList.first?.expression else {
156-
fatalError("boom")
157-
}
158-
159150
let visitor = AddVisitor()
160151
let result = visitor.visit(Syntax(node))
161152

@@ -242,6 +233,35 @@ public struct DefineBitwidthNumberedStructsMacro: DeclarationMacro {
242233
}
243234
}
244235

236+
public struct WarningMacro: ExpressionMacro {
237+
public static func expansion(
238+
of macro: some FreestandingMacroExpansionSyntax,
239+
in context: some MacroExpansionContext
240+
) throws -> ExprSyntax {
241+
guard let firstElement = macro.argumentList.first,
242+
let stringLiteral = firstElement.expression
243+
.as(StringLiteralExprSyntax.self),
244+
stringLiteral.segments.count == 1,
245+
case let .stringSegment(messageString)? = stringLiteral.segments.first
246+
else {
247+
throw CustomError.message("#myWarning macro requires a string literal")
248+
}
249+
250+
context.diagnose(
251+
Diagnostic(
252+
node: Syntax(macro),
253+
message: SimpleDiagnosticMessage(
254+
message: messageString.content.description,
255+
diagnosticID: MessageID(domain: "test", id: "error"),
256+
severity: .warning
257+
)
258+
)
259+
)
260+
261+
return "()"
262+
}
263+
}
264+
245265
public struct PropertyWrapperMacro {}
246266

247267
extension PropertyWrapperMacro: AccessorMacro, Macro {

test/Macros/macro_expand.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
// Debug info SIL testing
1212
// RUN: %target-swift-frontend -emit-sil -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
1313

14+
// RUN: %target-swift-frontend -emit-sil -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
15+
1416
// Execution testing
1517
// RUN: %target-build-swift -g -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser
1618
// RUN: %target-run %t/main | %FileCheck %s
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath -swift-version 5
3+
4+
// Make sure the diagnostic comes through...
5+
// RUN: %target-typecheck-verify-swift -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser
6+
7+
// Make sure the diagnostic doesn't crash in SILGen
8+
// RUN: not %target-swift-frontend -emit-sil -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g
9+
10+
// FIXME: Swift parser is not enabled on Linux CI yet.
11+
// REQUIRES: OS=macosx
12+
13+
@freestanding(expression) macro myWarning(_ message: String) = #externalMacro(module: "MacroDefinition", type: "WarningMacro")
14+
15+
func testThrownError() {
16+
let name = "hello"
17+
#myWarning(name) // expected-error{{#myWarning macro requires a string literal (from macro 'myWarning')}}
18+
19+
#myWarning("experimental features ahead") // expected-warning{{experimental features ahead}}
20+
}

0 commit comments

Comments
 (0)