The _SwiftifyImport macro is emitted into an unnamed buffer and then
parsed, pretending it was in the header all along. This makes it hard to
add `expected-note` comments for `diag::in_macro_expansion` when they
point here. That's okay, because the macro expansion has already been
pointed out by `expected-expansion` directives. But
-verify-ignore-unrelated is too blunt of a tool, so this adds
-verify-ignore-macro-note to ignore these specific diagnostics.
`llvm::Twine` is not valid after the end of the statement. Pass it
directly as a parameter without storing it in a local variable to
prevent UAF. Also updates DiagnosticVerifier tests to capture all
relevant output.
This enables the previously added -verify-ignore-unrelated flag. When
-verify is used without -verify-ignore-unrelated, diagnostics emitted in
buffers other than the main file and those passed with
-verify-additional-file (except diagnostics emitted at <unknown>:0) will
now result in an error. They were previously ignored. The old behaviour
is still available as opt-in using -verify-ignore-unrelated.
This adds the implementation required for later changing the default
behaviour of the -verify flag to error when diagnostics are emitted
in buffers other than the main file and files added with
-verify-additional-file. To keep the current behaviour, use the flag
-verify-ignore-unrelated. This flag is added as a no-op so that tests
can start using it before the new behaviour is enabled by default.
When the diagnostic verifier encounters a fatal error, it reports:
<unknown>:0: error: fatal error encountered while in -verify mode
If we capture this, and fail to match this against an expected-error,
the diagnostic verifier complains:
<unknown>:0: error: unexpected error produced: fatal error encountered while in -verify mode
<unknown>:0: error: diagnostic produced elsewhere: fatal error encountered while in -verify mode
The current workaround is to use -verify-ignore-unknown, but that in
turn may mask actual errors coming from unknown source locations.
Ignoring these errors about errors removes the need for that workaround.
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.
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}}
}}
*/
```
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.
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.
We've been converging the implementations of educational notes and
diagnostic groups, where both provide category information in
diagnostics (e.g., `[#StrictMemorySafety]`) and corresponding
short-form documentation files. The diagnostic group model is more
useful in a few ways:
* It provides warnings-as-errors control for warnings in the group
* It is easier to associate a diagnostic with a group with
GROUPED_ERROR/GROUPED_WARNING than it is to have a separate diagnostic
ID -> mapping.
* It is easier to see our progress on diagnostic-group coverage
* It provides an easy name to use for diagnostic purposes.
Collapse the educational-notes infrastructure into diagnostic groups,
migrating all of the existing educational notes into new groups.
Simplify the code paths that dealt with multiple educational notes to
have a single, possibly-missing "category documentation URL", which is
how we're treating this.
This commit makes a number of adjustments to how the diagnostic verifier handles source buffers and source locations. Specifically:
• Files named by `-verify-additional-file` are read as late as possible so that if some other component of the compiler has already loaded the file, even in some exotic way (e.g. ClangImporter’s source buffer mirroring), it will use the same buffer.
• Expectation source locations now ignore virtual files and other trickery; they are based on the source buffer and physical location in the file.
Hopefully this will make `-verify-additional-file` work better on Windows. As an unintended side effect, it also changes how expectations work in tests that use `#sourceLocation()`.
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
LLVM is presumably moving towards `std::string_view` -
`StringRef::startswith` is deprecated on tip. `SmallString::startswith`
was just renamed there (maybe with some small deprecation inbetween, but
if so, we've missed it).
The `SmallString::startswith` references were moved to
`.str().starts_with()`, rather than adding the `starts_with` on
`stable/20230725` as we only had a few of them. Open to switching that
over if anyone feels strongly though.
This enables one to use varying prefixes when checking diagnostics with the
DiagnosticVerifier. So for instance, I can make a test work both with and
without send-non-sendable enabled by adding additional prefixes. As an example:
```swift
// RUN: %target-swift-frontend ... -verify-additional-prefix no-sns-
// RUN: %target-swift-frontend ... -verify-additional-prefix sns-
let x = ... // expected-error {{This is always checked no matter what prefixes I added}}
let y = ... // expected-no-sns-error {{This is only checked if send non sendable is disabled}}
let z = ... // expected-sns-error {{This is only checked if send non sendable is enabled}}
let w = ... // expected-no-sns-error {{This is checked for a specific error when sns is disabled...}}
// expected-sns-error @-1 {{and for a different error when sns is enabled}}
```
rdar://114643840
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`
The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.
rdar://102362022
You can now put `||` between two fix-its to indicate that the test succeeds if either of them is present. This is meant for situations where a fix-it might vary slightly in different subtests or test configurations.
Also fixes a bug in the diagnostic verifier where "expected-whatever" would search beyond the same line for its opening "{{", potentially finding one many lines away and giving a bad diagnostic and poor recovery behavior.
If, for instance, an error is emitted as a warning instead, the verifier now detects this and emits a single diagnostic saying that the warning was found but had the wrong kind, instead of emitting one diagnostic saying the error was missing and another saying the warning was unexpected.
In theory there are some edge cases we could handle better by doing two separate passes—one to detect exact expectation matches and remove them, another to detect near-misses and diagnose them—but in practice, I think the text + diagnostic location is likely to be unique enough to keep this from being a problem. (I would hesitate to do wrong-line diagnostics in the same pass like this, though.)
This commit fixes two weird bugs in -verify mode:
1. SourceLocs from the wrong SourceManager could be passed through a ForwardingDiagnosticConsumer into the DiagnosticVerifier.
2. -verify-additional-file did not error out correctly when the file couldn’t be opened.
No tests, as we only have basic tests for the diagnostic verifier.
This change adds a frontend flag, -verify-additional-file, which can be used to pass extra files directly to the diagnostic verifier. These files are not otherwise considered to be Swift source files; they are not compiled or even properly parsed.
This feature can be used to verify diagnostics emitted in non-source files, such as in module interfaces or header files.
The newer llvm StringRef library has removed the implicit StringRef to
std::string conversion. (See: llvm/llvm-project@adcd026)
This patch also uses a StringRef to compare another StringRef
eliminating the need to perform a StringRef to std::string conversion.
I am concerned that StringRef's are being stored in
ExpectedEducationalNotes, but as long as the StringRef does not out live
the definition this is totally cool then.
* [Diagnostics] Improve {{none}} fix-it verifier
* split two conditions
* define "none" constant
* support plural
* use Twine and add comment for replacement range
* check if {{none}} is at the end
* use noneMarkerStartLoc
* update second {{none}} error message
Co-Authored-By: Owen Voorhees <owenvoorhees@gmail.com>
* update test case for second {{none}}
* fix test case for new {{none}} check
* Use named struct
* set const
Co-authored-by: Owen Voorhees <owenvoorhees@gmail.com>