Skip to content

Conversation

hnrklssn
Copy link
Contributor

This implements support for testing diagnostics in macro expansions using the -verify flag.

Clang, which heavily inspired Swift's -verify flag, supports naming
other files like so:
```
// expected-error@some-header.h:11:22{{some error}}
```
Swift hasn't had the same need for this, because of the lack of textual
header inclusion (where the same header file can emit different
diagnostics depending on where it's included). The lack of this
functionality has made it impossible to use -verify in cases where
diagnostics are emitted in a macro however, since the expected-lines
can't be placed inside the generated macro buffer.

Now the main Swift file can refer to diagnostics inside these generated
buffers by naming the buffers. The generated names aren't pretty, but
the identifier is stable, unique and it works.

Here is an example of what it can look like:
```
// expected-error@@__swiftmacro_4main3bar.swift:10:15{{no exact matches in call to initializer}}
// expected-note@+1{{in expansion of macro 'foo' on global function 'bar' here}}
@foo
func bar() {}
```
The double "@" is a result of the buffer name starting with an @, which
is unfortunate but is how the mangling scheme works for macro buffer
names.
The previous commit added support for checking diagnostics in other
buffers, enabling diagnostic verification for e.g. macro expansions.
Because the diagnostics are in a different buffer, there is no error for
not marking them as "expected". This commit expands the scope to
include generated sources originating in code in any checked buffer, to
help make sure that errors aren't accidentally missed.
Now that the DiagnosticsVerifier supports verifying diagnostics in
macro expansions it's time to enable this test case.
@hnrklssn
Copy link
Contributor Author

@swift-ci please smoke test

This refactors the parsing of "expected-*" lines to a separate function,
to enable recursive parsing in the next commit.
Since freestanding macro expansion buffer names include the line number
of their invocation, it can become quite fiddly to try to update a test
file with multiple macro expansions. This adds the option to use an
expected-expansion block and use a relative line number, nesting other
expected diagnostic statements inside this block.

Example syntax:
```swift
let myVar = #myMacro
/*
expected-expansion@-2:1{{
  expected-error@13:37{{I can't believe you've done this}}
  expected-note@14:38{{look at this and ponder your mistake}}
}}
*/
```
@hnrklssn hnrklssn requested a review from ktoso as a code owner September 18, 2025 23:43
@hnrklssn
Copy link
Contributor Author

@swift-ci please smoke test

When the syntax `expected-error@:42{{}}` was used, this would
accidentally trigger "absolute line" mode, despite not specifying a
line, resulting in the target line always being line 0.
@hnrklssn
Copy link
Contributor Author

@swift-ci please smoke test

When this function was extracted from a for loop, continue was mapped to
return, but these nested continues should remain.
@hnrklssn
Copy link
Contributor Author

@swift-ci please smoke test

This test case failed in CI when using a strict diff, because the output
also contained the text "swift runtime: unknown backtracing setting
'warnings'". Switch to using FileCheck to ignore this output.
@hnrklssn
Copy link
Contributor Author

@swift-ci please smoke test

@hnrklssn hnrklssn merged commit c82e85d into swiftlang:main Sep 23, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants