mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Error when using emitter.Build().Emit() (#5152)
I've found myself cleaning up other cases of this, so moving to disallow
it.
```
In file included from toolchain/check/merge.cpp:5:
In file included from ./toolchain/check/merge.h:8:
In file included from ./toolchain/check/context.h:13:
In file included from ./toolchain/check/decl_introducer_state.h:8:
In file included from ./toolchain/check/keyword_modifier_set.h:11:
In file included from ./toolchain/sem_ir/name_scope.h:10:
In file included from ./toolchain/sem_ir/ids.h:12:
./toolchain/diagnostics/diagnostic_emitter.h:95:11: error: static assertion failed: Use `emitter.Emit(...)` or `emitter.Build(...).Note(...).Emit(...)` instead of `emitter.Build(...).Emit(...)`
95 | false,
| ^~~~~
toolchain/check/merge.cpp:92:61: note: in instantiation of function template specialization 'Carbon::DiagnosticEmitter<Carbon::Check::SemIRLoc>::DiagnosticBuilder::Emit<>' requested here
92 | context.emitter().Build(loc, ExternRequiresDeclInApiFile).Emit();
| ^
1 error generated.
```
This commit is contained in:
@@ -89,7 +89,7 @@ auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIRLoc loc)
|
||||
CARBON_DIAGNOSTIC(
|
||||
ExternRequiresDeclInApiFile, Error,
|
||||
"`extern` entities must have a declaration in the API file");
|
||||
context.emitter().Build(loc, ExternRequiresDeclInApiFile).Emit();
|
||||
context.emitter().Emit(loc, ExternRequiresDeclInApiFile);
|
||||
}
|
||||
|
||||
auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
|
||||
|
||||
@@ -86,7 +86,11 @@ class DiagnosticEmitter {
|
||||
// Emits the built diagnostic and its attached notes.
|
||||
// For the expected usage see the builder API: `DiagnosticEmitter::Build`.
|
||||
template <typename... Args>
|
||||
auto Emit() -> void;
|
||||
auto Emit() & -> void;
|
||||
|
||||
// Prevent trivial uses of the builder; always `static_assert`s.
|
||||
template <typename... Args>
|
||||
auto Emit() && -> void;
|
||||
|
||||
// Returns true if this DiagnosticBuilder may emit a diagnostic. Can be used
|
||||
// to avoid excess work computing notes, etc, if no diagnostic is going to
|
||||
@@ -282,7 +286,7 @@ auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Note(
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() -> void {
|
||||
auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() & -> void {
|
||||
if (!emitter_) {
|
||||
return;
|
||||
}
|
||||
@@ -292,6 +296,22 @@ auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() -> void {
|
||||
emitter_->consumer_->HandleDiagnostic(std::move(diagnostic_));
|
||||
}
|
||||
|
||||
namespace Internal {
|
||||
template <typename LocT>
|
||||
concept AlwaysFalse = false;
|
||||
} // namespace Internal
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() && -> void {
|
||||
// TODO: This is required by clang-16, but `false` may work in newer clang
|
||||
// versions. Replace when possible.
|
||||
static_assert(Internal::AlwaysFalse<LocT>,
|
||||
"Use `emitter.Emit(...)` or "
|
||||
"`emitter.Build(...).Note(...).Emit(...)` "
|
||||
"instead of `emitter.Build(...).Emit(...)`");
|
||||
}
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
DiagnosticEmitter<LocT>::DiagnosticBuilder::DiagnosticBuilder(
|
||||
@@ -364,8 +384,9 @@ template <typename... Args>
|
||||
auto DiagnosticEmitter<LocT>::Emit(
|
||||
LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> void {
|
||||
DiagnosticBuilder(this, loc, diagnostic_base, {MakeAny<Args>(args)...})
|
||||
.Emit();
|
||||
DiagnosticBuilder builder(this, loc, diagnostic_base,
|
||||
{MakeAny<Args>(args)...});
|
||||
builder.Emit();
|
||||
}
|
||||
|
||||
template <typename LocT>
|
||||
|
||||
Reference in New Issue
Block a user