From 4845f40dff2429ec2c72b2400a3e167bff18c456 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Thu, 12 Sep 2024 09:42:08 -0700 Subject: [PATCH] Switch `CARBON_CHECK` to a format string API (#4285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This switches `DCHECK` and `FATAL` as well. The goal is to reduce the code size impact of these assertions so that we can keep more of them enabled. Currently, the largest cost I see from `CHECK` is not the actual check or the cold code itself, but actually the failure to inline trivial functions due to the presence of the cold code. This means that our goal isn't to reduce apparent code size in the final binary but the LLVM IR cost assessed for these routines in the inliner, which closely correlates with code size but is a bit different. As discussed in #4283, experimentation shows that a single function call with a minimal number of arguments is the lowest cost model for these. This is easily achieved with a format-string API that internally uses `llvm::formatv`. This PR is essentially the `CHECK` version of #4283. However, the check macros are substantially harder to make work with both format strings and streaming because they also take a condition. Also, unexpectedly, I was very successful at devising a regular expression based automated rewrite from the streaming to the format string form with only low 10s of manual fixes. This includes compacting strings broken up across lines, etc. Given how well that went, I've prepared this PR which just directly switches to the format string API and migrate everything to use it. One nice side-effect is that the format string approach ends up greatly simplifying the implementation here as well. This is ... *shockingly* effective. Parsing speeds up by more than 3% with just this change. And checking speeds up by **8%** with this change alone: ``` BM_CompileAPIFileDenseDecls/256 86.3µs ± 1% 82.9µs ± 1% -3.94% (p=0.000 n=17+19) BM_CompileAPIFileDenseDecls/1024 431µs ± 1% 415µs ± 1% -3.76% (p=0.000 n=18+19) BM_CompileAPIFileDenseDecls/4096 1.77ms ± 1% 1.71ms ± 1% -3.18% (p=0.000 n=18+19) BM_CompileAPIFileDenseDecls/16384 7.44ms ± 1% 7.17ms ± 2% -3.56% (p=0.000 n=18+20) BM_CompileAPIFileDenseDecls/65536 30.7ms ± 1% 29.7ms ± 1% -3.15% (p=0.000 n=18+20) BM_CompileAPIFileDenseDecls/262144 131ms ± 1% 127ms ± 1% -2.81% (p=0.000 n=18+18) BM_CompileAPIFileDenseDecls/256 878µs ± 2% 800µs ± 1% -8.91% (p=0.000 n=19+20) BM_CompileAPIFileDenseDecls/1024 1.88ms ± 2% 1.72ms ± 1% -8.56% (p=0.000 n=19+20) BM_CompileAPIFileDenseDecls/4096 5.78ms ± 2% 5.28ms ± 1% -8.70% (p=0.000 n=20+18) BM_CompileAPIFileDenseDecls/16384 21.9ms ± 1% 20.1ms ± 1% -8.02% (p=0.000 n=18+20) BM_CompileAPIFileDenseDecls/65536 90.4ms ± 2% 83.1ms ± 1% -8.04% (p=0.000 n=19+20) BM_CompileAPIFileDenseDecls/262144 381ms ± 2% 352ms ± 1% -7.79% (p=0.000 n=19+19) ``` --------- Co-authored-by: Richard Smith Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com> --- common/BUILD | 2 + common/array_stack.h | 8 +- common/check.h | 42 +++-- common/check_internal.cpp | 28 ++-- common/check_internal.h | 153 +++++++++++------- common/check_test.cpp | 21 ++- common/command_line.cpp | 148 +++++++++-------- common/command_line.h | 8 +- common/error.h | 2 +- common/hashing_test.cpp | 2 +- common/map.h | 4 +- common/map_benchmark.cpp | 6 +- common/raw_hashtable.h | 46 +++--- common/raw_hashtable_benchmark_helpers.cpp | 7 +- common/raw_hashtable_metadata_group.h | 101 ++++++------ common/set.h | 2 +- common/set_benchmark.cpp | 6 +- explorer/ast/bindings.cpp | 6 +- explorer/ast/clone_context.cpp | 10 +- explorer/ast/clone_context.h | 2 +- explorer/ast/declaration.cpp | 2 +- explorer/ast/declaration.h | 6 +- explorer/ast/element_path.h | 4 +- explorer/ast/expression.cpp | 3 +- explorer/ast/expression.h | 7 +- explorer/ast/impl_binding.h | 6 +- explorer/ast/pattern.h | 4 +- explorer/ast/statement.h | 6 +- explorer/ast/static_scope.cpp | 4 +- explorer/ast/value.cpp | 46 +++--- explorer/ast/value.h | 20 +-- explorer/file_test.cpp | 4 +- explorer/fuzzing/ast_to_proto.cpp | 18 +-- explorer/fuzzing/fuzzer_util.cpp | 4 +- explorer/interpreter/action.cpp | 16 +- explorer/interpreter/action.h | 2 +- explorer/interpreter/action_stack.cpp | 14 +- explorer/interpreter/heap.cpp | 4 +- explorer/interpreter/impl_scope.cpp | 14 +- explorer/interpreter/interpreter.cpp | 138 ++++++++-------- explorer/interpreter/matching_impl_set.cpp | 2 +- explorer/interpreter/pattern_match.cpp | 25 ++- explorer/interpreter/resolve_names.cpp | 14 +- explorer/interpreter/resolve_unformed.cpp | 4 +- explorer/interpreter/stack.h | 10 +- explorer/interpreter/type_checker.cpp | 132 +++++++-------- explorer/interpreter/type_utils.cpp | 4 +- explorer/syntax/parse.cpp | 4 +- explorer/syntax/prelude.cpp | 3 +- migrate_cpp/rewriter_test.cpp | 4 +- testing/base/global_exe_path.cpp | 7 +- testing/base/source_gen.cpp | 42 ++--- testing/file_test/autoupdate.cpp | 26 +-- testing/file_test/autoupdate.h | 11 +- testing/file_test/file_test_base.cpp | 6 +- toolchain/base/value_store.h | 6 +- toolchain/base/yaml.h | 2 +- toolchain/check/check.cpp | 39 +++-- toolchain/check/check_fuzzer.cpp | 2 +- toolchain/check/context.cpp | 61 +++---- toolchain/check/context.h | 3 +- toolchain/check/convert.cpp | 29 ++-- toolchain/check/decl_introducer_state.h | 5 +- toolchain/check/decl_name_stack.cpp | 48 +++--- toolchain/check/deduce.cpp | 8 +- toolchain/check/eval.cpp | 43 ++--- toolchain/check/generic.cpp | 50 +++--- toolchain/check/handle_binding_pattern.cpp | 8 +- toolchain/check/handle_class.cpp | 8 +- toolchain/check/handle_if_statement.cpp | 2 +- toolchain/check/handle_interface.cpp | 4 +- toolchain/check/handle_let_and_var.cpp | 4 +- toolchain/check/handle_name.cpp | 2 +- toolchain/check/handle_noop.cpp | 4 +- toolchain/check/handle_struct.cpp | 4 +- toolchain/check/impl.cpp | 20 +-- toolchain/check/import.cpp | 12 +- toolchain/check/import_ref.cpp | 36 ++--- toolchain/check/inst_block_stack.cpp | 10 +- toolchain/check/inst_block_stack.h | 6 +- toolchain/check/lexical_lookup.h | 23 +-- toolchain/check/member_access.cpp | 11 +- toolchain/check/merge.cpp | 12 +- toolchain/check/node_stack.cpp | 2 +- toolchain/check/node_stack.h | 39 +++-- toolchain/check/return.cpp | 8 +- toolchain/check/scope_stack.cpp | 62 +++---- .../check/sem_ir_diagnostic_converter.cpp | 12 +- toolchain/check/subst.cpp | 12 +- toolchain/diagnostics/diagnostic_emitter.h | 17 +- .../diagnostics/sorting_diagnostic_consumer.h | 4 +- toolchain/docs/idioms.md | 2 +- toolchain/driver/clang_runner.cpp | 2 +- toolchain/driver/clang_runner_test.cpp | 2 +- toolchain/driver/driver.cpp | 4 +- toolchain/driver/driver_fuzzer.cpp | 2 +- toolchain/driver/driver_test.cpp | 19 +-- toolchain/install/install_paths.cpp | 6 +- toolchain/install/install_paths_test.cpp | 10 +- .../install/install_paths_test_helpers.cpp | 6 +- toolchain/lex/lex.cpp | 58 +++---- toolchain/lex/numeric_literal.cpp | 2 +- toolchain/lex/string_literal.cpp | 12 +- toolchain/lex/test_helpers.h | 4 +- toolchain/lex/token_kind.h | 4 +- toolchain/lex/tokenized_buffer.cpp | 42 ++--- toolchain/lex/tokenized_buffer.h | 4 +- toolchain/lex/tokenized_buffer_benchmark.cpp | 31 ++-- toolchain/lex/tokenized_buffer_fuzzer.cpp | 8 +- toolchain/lower/constant.cpp | 19 +-- toolchain/lower/file_context.cpp | 25 ++- toolchain/lower/file_context.h | 4 +- toolchain/lower/function_context.cpp | 33 ++-- toolchain/lower/function_context.h | 4 +- toolchain/lower/handle.cpp | 12 +- toolchain/lower/handle_aggregates.cpp | 31 ++-- toolchain/lower/handle_call.cpp | 8 +- toolchain/lower/handle_expr_category.cpp | 6 +- toolchain/lower/mangler.cpp | 4 +- toolchain/parse/context.cpp | 29 ++-- toolchain/parse/context.h | 4 +- toolchain/parse/handle_expr.cpp | 11 +- toolchain/parse/handle_paren_expr.cpp | 4 +- toolchain/parse/handle_requirement.cpp | 4 +- toolchain/parse/node_kind.h | 7 +- toolchain/parse/parse.cpp | 6 +- toolchain/parse/precedence.cpp | 12 +- toolchain/parse/tree_and_subtrees.cpp | 37 ++--- toolchain/parse/tree_and_subtrees.h | 4 +- toolchain/sem_ir/block_value_store.h | 4 +- toolchain/sem_ir/constant.cpp | 6 +- toolchain/sem_ir/file.cpp | 10 +- toolchain/sem_ir/generic.cpp | 9 +- toolchain/sem_ir/ids.h | 18 +-- toolchain/sem_ir/inst.h | 10 +- toolchain/sem_ir/inst_namer.cpp | 2 +- toolchain/sem_ir/name.cpp | 2 +- toolchain/sem_ir/name_scope.h | 4 +- toolchain/sem_ir/type.h | 4 +- toolchain/testing/file_test.cpp | 6 +- 140 files changed, 1234 insertions(+), 1161 deletions(-) diff --git a/common/BUILD b/common/BUILD index b6d1ff7ac018..a3d5173df792 100644 --- a/common/BUILD +++ b/common/BUILD @@ -68,6 +68,7 @@ cc_library( hdrs = ["check.h"], deps = [ ":ostream", + ":template_string", "@llvm-project//llvm:Support", ], ) @@ -329,6 +330,7 @@ cc_library( hdrs = ["raw_hashtable_metadata_group.h"], deps = [ ":check", + ":ostream", "@llvm-project//llvm:Support", ], ) diff --git a/common/array_stack.h b/common/array_stack.h index ff22147722da..c39bccf1d8cf 100644 --- a/common/array_stack.h +++ b/common/array_stack.h @@ -62,15 +62,15 @@ class ArrayStack { // Appends a value to the top array on the stack. auto AppendToTop(ValueT value) -> void { - CARBON_CHECK(!array_offsets_.empty()) - << "Must call PushArray before PushValue."; + CARBON_CHECK(!array_offsets_.empty(), + "Must call PushArray before PushValue."); values_.push_back(value); } // Adds multiple values to the top array on the stack. auto AppendToTop(llvm::ArrayRef values) -> void { - CARBON_CHECK(!array_offsets_.empty()) - << "Must call PushArray before PushValues."; + CARBON_CHECK(!array_offsets_.empty(), + "Must call PushArray before PushValues."); values_.append(values.begin(), values.end()); } diff --git a/common/check.h b/common/check.h index ef8e1367a37c..1db43681c7d0 100644 --- a/common/check.h +++ b/common/check.h @@ -14,30 +14,40 @@ namespace Carbon { // a bug in the application. // // For example: -// CARBON_CHECK(is_valid) << "Data is not valid!"; -#define CARBON_CHECK(...) \ - (__VA_ARGS__) ? (void)0 \ - : CARBON_CHECK_INTERNAL_STREAM() \ - << "CHECK failure at " << __FILE__ << ":" << __LINE__ \ - << ": " #__VA_ARGS__ \ - << Carbon::Internal::ExitingStream::AddSeparator() +// CARBON_CHECK(is_valid, "Data is not valid!"); +// +// The condition must be parenthesized if it contains top-level commas, for +// example in a template argument list: +// CARBON_CHECK((inst.IsOneOf()), +// "Unexpected inst {0}", inst); +#define CARBON_CHECK(condition, ...) \ + (condition) ? (void)0 \ + : CARBON_INTERNAL_CHECK(condition __VA_OPT__(, ) __VA_ARGS__) // DCHECK calls CHECK in debug mode, and does nothing otherwise. #ifndef NDEBUG -#define CARBON_DCHECK(...) CARBON_CHECK(__VA_ARGS__) +#define CARBON_DCHECK(condition, ...) \ + CARBON_CHECK(condition __VA_OPT__(, ) __VA_ARGS__) #else -#define CARBON_DCHECK(...) CARBON_CHECK(true || (__VA_ARGS__)) +// When in a debug build we want to preserve as much as we can of how the +// parameters are used, other than making them be trivially in dead code and +// eliminated by the optimizer. As a consequence we preserve the condition but +// prefix it with a short-circuit operator, and we still emit the (dead) call to +// the check implementation. But we use a special implementation that reduces +// the compile time cost. +#define CARBON_DCHECK(condition, ...) \ + (true || (condition)) \ + ? (void)0 \ + : CARBON_INTERNAL_DEAD_DCHECK(condition __VA_OPT__(, ) __VA_ARGS__) #endif -// This is similar to CHECK, but is unconditional. Writing CARBON_FATAL() is -// clearer than CARBON_CHECK(false) because it avoids confusion about control -// flow. +// This is similar to CHECK, but is unconditional. Writing +// `CARBON_FATAL("message")` is clearer than `CARBON_CHECK(false, "message") +// because it avoids confusion about control flow. // // For example: -// CARBON_FATAL() << "Unreachable!"; -#define CARBON_FATAL() \ - CARBON_CHECK_INTERNAL_STREAM() \ - << "FATAL failure at " << __FILE__ << ":" << __LINE__ << ": " +// CARBON_FATAL("Unreachable!"); +#define CARBON_FATAL(...) CARBON_INTERNAL_FATAL(__VA_ARGS__) } // namespace Carbon diff --git a/common/check_internal.cpp b/common/check_internal.cpp index f365eed0c66a..9fc5cd653a15 100644 --- a/common/check_internal.cpp +++ b/common/check_internal.cpp @@ -4,7 +4,7 @@ #include "common/check_internal.h" -#include "llvm/Support/ErrorHandling.h" +#include "common/ostream.h" #include "llvm/Support/Signals.h" namespace Carbon::Internal { @@ -14,22 +14,20 @@ static auto PrintAfterStackTrace(void* str) -> void { llvm::errs() << reinterpret_cast(str); } -ExitingStream::~ExitingStream() { - llvm_unreachable( - "Exiting streams should only be constructed by check.h macros that " - "ensure the special operator| exits the program prior to their " - "destruction!"); -} +auto CheckFailImpl(const char* kind, const char* file, int line, + const char* condition_str, llvm::StringRef extra_message) + -> void { + // Render the final check string here. + std::string message = llvm::formatv( + "{0} failure at {1}:{2}{3}{4}{5}{6}\n", kind, file, line, + llvm::StringRef(condition_str).empty() ? "" : ": ", condition_str, + extra_message.empty() ? "" : ": ", extra_message); -auto ExitingStream::Done() -> void { - buffer_ << "\n"; - buffer_.flush(); - - // Register another signal handler to print the buffered message. This is - // because we want it at the bottom of output, after LLVM's builtin stack - // output, rather than the top. + // Register another signal handler to print the message. This is because we + // want it at the bottom of output, after LLVM's builtin stack output, rather + // than the top. llvm::sys::AddSignalHandler(PrintAfterStackTrace, - const_cast(buffer_str_.c_str())); + const_cast(message.c_str())); // It's useful to exit the program with `std::abort()` for integration with // debuggers and other tools. We also assume LLVM's exit handling is // installed, which will stack trace on `std::abort()`. diff --git a/common/check_internal.h b/common/check_internal.h index 9f4ea0e042c7..300b6028cff9 100644 --- a/common/check_internal.h +++ b/common/check_internal.h @@ -5,73 +5,106 @@ #ifndef CARBON_COMMON_CHECK_INTERNAL_H_ #define CARBON_COMMON_CHECK_INTERNAL_H_ -#include "common/ostream.h" +#include "common/template_string.h" +#include "llvm/Support/FormatVariadic.h" namespace Carbon::Internal { -// Wraps a stream and exiting for fatal errors. Should only be used by check.h -// macros. -class ExitingStream { - public: - // A tag type that renders as ": " in an ExitingStream, but only if it is - // followed by additional output. Otherwise, it renders as "". Primarily used - // when building macros around these streams. - struct AddSeparator {}; +// Implements the check failure message printing. +// +// This is out-of-line and will arrange to stop the program, print any debugging +// information and this string. +// +// This API uses `const char*` C string arguments rather than `llvm::StringRef` +// because we know that these are available as C strings and passing them that +// way lets the code size of calling it be smaller: it only needs to materialize +// a single pointer argument for each. The runtime cost of re-computing the size +// should be minimal. The extra message however might not be compile-time +// guaranteed to be a C string so we use a normal `StringRef` there. +[[noreturn]] auto CheckFailImpl(const char* kind, const char* file, int line, + const char* condition_str, + llvm::StringRef extra_message) -> void; - // Internal type used in macros to dispatch to the `operator|` overload. - struct Helper {}; - - ExitingStream() - // Prefix the buffer with the current bug report message. - : buffer_(buffer_str_) {} - - // Never called. - [[noreturn]] ~ExitingStream(); - - // If the bool cast occurs, it's because the condition is false. This supports - // && short-circuiting the creation of ExitingStream. - explicit operator bool() const { return true; } - - // Forward output to llvm::errs. - template - auto operator<<(const T& message) -> ExitingStream& { - if (separator_) { - buffer_ << ": "; - separator_ = false; - } - buffer_ << message; - return *this; +// Prints a check failure, including rendering any user-provided message using +// a format string. +// +// Most of the parameters are passed as compile-time template strings to avoid +// runtime cost of parameter setup in optimized builds. Each of these are passed +// along to the underlying implementation to include in the final printed +// message. +// +// Any user-provided format string and values are directly passed to +// `llvm::formatv` which handles all of the formatting of output. +template +[[noreturn, gnu::cold, clang::noinline, clang::preserve_most]] auto CheckFail( + Ts&&... values) -> void { + if constexpr (llvm::StringRef(FormatStr).empty()) { + // Skip the format string rendering if empty. Note that we don't skip it + // even if there are no values as we want to have consistent handling of + // `{}`s in the format string. This case is about when there is no message + // at all, just the condition. + CheckFailImpl(Kind.c_str(), File.c_str(), Line, ConditionStr.c_str(), ""); + } else { + CheckFailImpl( + Kind.c_str(), File.c_str(), Line, ConditionStr.c_str(), + llvm::formatv(FormatStr.c_str(), std::forward(values)...).str()); } - - auto operator<<(AddSeparator /*add_separator*/) -> ExitingStream& { - separator_ = true; - return *this; - } - - // Low-precedence binary operator overload used in check.h macros to flush the - // output and exit the program. We do this in a binary operator rather than - // the destructor to ensure good debug info and backtraces for errors. - [[noreturn]] friend auto operator|(Helper /*helper*/, ExitingStream& stream) - -> void { - stream.Done(); - } - - private: - [[noreturn]] auto Done() -> void; - - // Whether a separator should be printed if << is used again. - bool separator_ = false; - - std::string buffer_str_; - llvm::raw_string_ostream buffer_; -}; +} } // namespace Carbon::Internal -// Raw exiting stream. This should be used when building forms of exiting -// macros. It evaluates to a temporary `ExitingStream` object that can be -// manipulated, streamed into, and then will exit the program. -#define CARBON_CHECK_INTERNAL_STREAM() \ - Carbon::Internal::ExitingStream::Helper() | Carbon::Internal::ExitingStream() +// Implements check messages without any formatted values. +// +// Passes each of the provided components of the message to the template +// parameters of the check failure printing function above, including an empty +// string for the format string. Because there are multiple template arguments, +// the entire call is wrapped in parentheses. +#define CARBON_INTERNAL_CHECK_IMPL(kind, file, line, condition_str) \ + (Carbon::Internal::CheckFail()) + +// Implements check messages with a format string and potentially formatted +// values. +// +// Each of the main components is passed as a template arguments, and then any +// formatted values are passed as arguments. Because there are multiple template +// arguments, the entire call is wrapped in parentheses. +#define CARBON_INTERNAL_CHECK_IMPL_FORMAT(kind, file, line, condition_str, \ + format_str, ...) \ + (Carbon::Internal::CheckFail( \ + __VA_ARGS__)) + +// Implements the failure of a check. +// +// Collects all the metadata about the failure to be printed, such as source +// location and stringified condition, and passes those, any format string and +// formatted arguments to the correct implementation macro above. +#define CARBON_INTERNAL_CHECK(condition, ...) \ + CARBON_INTERNAL_CHECK_IMPL##__VA_OPT__(_FORMAT)( \ + "CHECK", __FILE__, __LINE__, #condition __VA_OPT__(, ) __VA_ARGS__) + +// Implements the fatal macro. +// +// Similar to the check failure macro, but tags the message as a fatal one and +// leaves the stringified condition empty. +#define CARBON_INTERNAL_FATAL(...) \ + CARBON_INTERNAL_CHECK_IMPL##__VA_OPT__(_FORMAT)( \ + "FATAL", __FILE__, __LINE__, "" __VA_OPT__(, ) __VA_ARGS__) + +#ifdef NDEBUG +// For `DCHECK` in optimized builds we have a dead check that we want to +// potentially "use" arguments, but otherwise have the minimal overhead. We +// avoid forming interesting format strings here so that we don't have to +// repeatedly instantiate the `Check` function above. This format string would +// be an error if actually used. +#define CARBON_INTERNAL_DEAD_DCHECK(condition, ...) \ + CARBON_INTERNAL_DEAD_DCHECK_IMPL##__VA_OPT__(_FORMAT)(__VA_ARGS__) + +#define CARBON_INTERNAL_DEAD_DCHECK_IMPL() \ + Carbon::Internal::CheckFail<"", "", 0, "", "">() + +#define CARBON_INTERNAL_DEAD_DCHECK_IMPL_FORMAT(format_str, ...) \ + Carbon::Internal::CheckFail<"", "", 0, "", "">(__VA_ARGS__) +#endif #endif // CARBON_COMMON_CHECK_INTERNAL_H_ diff --git a/common/check_test.cpp b/common/check_test.cpp index 96660bcaf32d..24963bd6f6e1 100644 --- a/common/check_test.cpp +++ b/common/check_test.cpp @@ -26,32 +26,41 @@ TEST(CheckTest, CheckTrueCallbackNotUsed) { called = true; return "called"; }; - CARBON_CHECK(true) << callback(); + CARBON_CHECK(true, "{0}", callback()); EXPECT_FALSE(called); } TEST(CheckTest, CheckFalseMessage) { - ASSERT_DEATH({ CARBON_CHECK(false) << "msg"; }, + ASSERT_DEATH({ CARBON_CHECK(false, "msg"); }, "\nCHECK failure at common/check_test.cpp:.+: false: msg\n"); } +TEST(CheckTest, CheckFalseFormattedMessage) { + const char msg[] = "msg"; + std::string str = "str"; + int i = 1; + ASSERT_DEATH( + { CARBON_CHECK(false, "{0} {1} {2} {3}", msg, str, i, 0); }, + "\nCHECK failure at common/check_test.cpp:.+: false: msg str 1 0\n"); +} + TEST(CheckTest, CheckOutputForms) { const char msg[] = "msg"; std::string str = "str"; int i = 1; - CARBON_CHECK(true) << msg << str << i << 0; + CARBON_CHECK(true, "{0} {1} {2} {3}", msg, str, i, 0); } TEST(CheckTest, Fatal) { - ASSERT_DEATH({ CARBON_FATAL() << "msg"; }, + ASSERT_DEATH({ CARBON_FATAL("msg"); }, "\nFATAL failure at common/check_test.cpp:.+: msg\n"); } TEST(CheckTest, FatalHasStackDump) { - ASSERT_DEATH({ CARBON_FATAL() << "msg"; }, "\nStack dump:\n"); + ASSERT_DEATH({ CARBON_FATAL("msg"); }, "\nStack dump:\n"); } -auto FatalNoReturnRequired() -> int { CARBON_FATAL() << "msg"; } +auto FatalNoReturnRequired() -> int { CARBON_FATAL("msg"); } TEST(ErrorTest, FatalNoReturnRequired) { ASSERT_DEATH({ FatalNoReturnRequired(); }, diff --git a/common/command_line.cpp b/common/command_line.cpp index 8f1b60b9510c..bc95c8e73faf 100644 --- a/common/command_line.cpp +++ b/common/command_line.cpp @@ -22,7 +22,7 @@ auto operator<<(llvm::raw_ostream& output, ParseResult result) case ParseResult::Success: return output << "Success"; } - CARBON_FATAL() << "Corrupt parse result!"; + CARBON_FATAL("Corrupt parse result!"); } auto operator<<(llvm::raw_ostream& output, ArgKind kind) -> llvm::raw_ostream& { @@ -40,7 +40,7 @@ auto operator<<(llvm::raw_ostream& output, ArgKind kind) -> llvm::raw_ostream& { case ArgKind::Invalid: return output << "Invalid"; } - CARBON_FATAL() << "Corrupt argument kind!"; + CARBON_FATAL("Corrupt argument kind!"); } auto operator<<(llvm::raw_ostream& output, CommandKind kind) @@ -55,7 +55,7 @@ auto operator<<(llvm::raw_ostream& output, CommandKind kind) case CommandKind::MetaAction: return output << "MetaAction"; } - CARBON_FATAL() << "Corrupt command kind!"; + CARBON_FATAL("Corrupt command kind!"); } Arg::Arg(const ArgInfo& info) : info(info) {} @@ -315,8 +315,9 @@ void MetaPrinter::PrintHelpForSubcommandName( } void MetaPrinter::PrintVersion(const Command& command) const { - CARBON_CHECK(!command.info.version.empty()) - << "Printing should not be enabled without a version string configured."; + CARBON_CHECK( + !command.info.version.empty(), + "Printing should not be enabled without a version string configured."); PrintRawVersion(command, /*indent=*/""); if (!command.info.build_info.empty()) { out_ << "\n"; @@ -463,13 +464,14 @@ void MetaPrinter::PrintOptionUsage(const Arg& option) const { } void MetaPrinter::PrintOptionShortName(const Arg& arg) const { - CARBON_CHECK(!arg.info.short_name.empty()) << "No short name to use."; + CARBON_CHECK(!arg.info.short_name.empty(), "No short name to use."); out_ << "-" << arg.info.short_name; } void MetaPrinter::PrintArgShortValues(const Arg& arg) const { - CARBON_CHECK(arg.kind == Arg::Kind::OneOf) - << "Only one-of arguments have interesting value snippets to print."; + CARBON_CHECK( + arg.kind == Arg::Kind::OneOf, + "Only one-of arguments have interesting value snippets to print."); llvm::ListSeparator sep; for (llvm::StringRef value_string : arg.value_strings) { out_ << sep << value_string; @@ -517,7 +519,7 @@ void MetaPrinter::PrintArgHelp(const Arg& arg, llvm::StringRef indent) const { // No value help. break; case Arg::Kind::Invalid: - CARBON_FATAL() << "Argument configured without any action or kind!"; + CARBON_FATAL("Argument configured without any action or kind!"); } } @@ -793,11 +795,11 @@ void Parser::PopulateMaps(const Command& command) { if (option->info.short_name.empty()) { continue; } - CARBON_CHECK(option->info.short_name.size() == 1) - << "Short option names must have exactly one character."; + CARBON_CHECK(option->info.short_name.size() == 1, + "Short option names must have exactly one character."); unsigned char short_char = option->info.short_name[0]; - CARBON_CHECK(short_char < short_option_table_.size()) - << "Short option name outside of the expected range."; + CARBON_CHECK(short_char < short_option_table_.size(), + "Short option name outside of the expected range."); short_option_table_[short_char] = &map_entry.second; } subcommand_map_.clear(); @@ -807,7 +809,7 @@ void Parser::PopulateMaps(const Command& command) { } void Parser::SetOptionDefault(const Arg& option) { - CARBON_CHECK(option.has_default) << "No default value available!"; + CARBON_CHECK(option.has_default, "No default value available!"); switch (option.kind) { case Arg::Kind::Flag: *option.flag_storage = option.default_flag; @@ -822,9 +824,9 @@ void Parser::SetOptionDefault(const Arg& option) { option.default_action(option); break; case Arg::Kind::MetaActionOnly: - CARBON_FATAL() << "Can't set a default value for a meta action!"; + CARBON_FATAL("Can't set a default value for a meta action!"); case Arg::Kind::Invalid: - CARBON_FATAL() << "Option configured without any action or kind!"; + CARBON_FATAL("Option configured without any action or kind!"); } } @@ -846,7 +848,7 @@ auto Parser::ParseNegatedFlag(const Arg& flag, auto Parser::ParseFlag(const Arg& flag, std::optional value) -> bool { - CARBON_CHECK(flag.kind == Arg::Kind::Flag) << "Incorrect kind: " << flag.kind; + CARBON_CHECK(flag.kind == Arg::Kind::Flag, "Incorrect kind: {0}", flag.kind); if (!value || *value == "true") { *flag.flag_storage = true; } else if (*value == "false") { @@ -862,8 +864,7 @@ auto Parser::ParseFlag(const Arg& flag, std::optional value) auto Parser::ParseIntegerArgValue(const Arg& arg, llvm::StringRef value) -> bool { - CARBON_CHECK(arg.kind == Arg::Kind::Integer) - << "Incorrect kind: " << arg.kind; + CARBON_CHECK(arg.kind == Arg::Kind::Integer, "Incorrect kind: {0}", arg.kind); int integer_value; // Note that this method returns *true* on error! if (value.getAsInteger(/*Radix=*/0, integer_value)) { @@ -881,7 +882,7 @@ auto Parser::ParseIntegerArgValue(const Arg& arg, llvm::StringRef value) auto Parser::ParseStringArgValue(const Arg& arg, llvm::StringRef value) -> bool { - CARBON_CHECK(arg.kind == Arg::Kind::String) << "Incorrect kind: " << arg.kind; + CARBON_CHECK(arg.kind == Arg::Kind::String, "Incorrect kind: {0}", arg.kind); if (!arg.is_append) { *arg.string_storage = value; } else { @@ -891,7 +892,7 @@ auto Parser::ParseStringArgValue(const Arg& arg, llvm::StringRef value) } auto Parser::ParseOneOfArgValue(const Arg& arg, llvm::StringRef value) -> bool { - CARBON_CHECK(arg.kind == Arg::Kind::OneOf) << "Incorrect kind: " << arg.kind; + CARBON_CHECK(arg.kind == Arg::Kind::OneOf, "Incorrect kind: {0}", arg.kind); if (!arg.value_action(arg, value)) { errors_ << "ERROR: Option '--" << arg.info.name << "="; llvm::printEscapedString(value, errors_); @@ -967,7 +968,7 @@ auto Parser::ParseArg(const Arg& arg, bool short_spelling, return false; case Arg::Kind::Flag: case Arg::Kind::Invalid: - CARBON_FATAL() << "Invalid kind!"; + CARBON_FATAL("Invalid kind!"); } } @@ -984,8 +985,8 @@ auto Parser::SplitValue(llvm::StringRef& unparsed_arg) } auto Parser::ParseLongOption(llvm::StringRef unparsed_arg) -> bool { - CARBON_CHECK(unparsed_arg.starts_with("--") && unparsed_arg.size() > 2) - << "Must only be called on a potential long option."; + CARBON_CHECK(unparsed_arg.starts_with("--") && unparsed_arg.size() > 2, + "Must only be called on a potential long option."); // Walk past the double dash. unparsed_arg = unparsed_arg.drop_front(2); @@ -1009,8 +1010,8 @@ auto Parser::ParseLongOption(llvm::StringRef unparsed_arg) -> bool { } auto Parser::ParseShortOptionSeq(llvm::StringRef unparsed_arg) -> bool { - CARBON_CHECK(unparsed_arg.starts_with("-") && unparsed_arg.size() > 1) - << "Must only be called on a potential short option sequence."; + CARBON_CHECK(unparsed_arg.starts_with("-") && unparsed_arg.size() > 1, + "Must only be called on a potential short option sequence."); unparsed_arg = unparsed_arg.drop_front(); std::optional value = SplitValue(unparsed_arg); @@ -1143,10 +1144,10 @@ auto Parser::FinalizeParse() -> ParseResult { // If we were appending to a positional argument, mark that as complete. llvm::ArrayRef positional_args = command_->positional_args; if (appending_to_positional_arg_) { - CARBON_CHECK(static_cast(positional_arg_index_) < - positional_args.size()) - << "Appending to a positional argument with an invalid index: " - << positional_arg_index_; + CARBON_CHECK( + static_cast(positional_arg_index_) < positional_args.size(), + "Appending to a positional argument with an invalid index: {0}", + positional_arg_index_); ++positional_arg_index_; } @@ -1162,15 +1163,15 @@ auto Parser::FinalizeParse() -> ParseResult { return ParseResult::Error; } for (const auto& arg_ptr : unparsed_positional_args) { - CARBON_CHECK(!arg_ptr->is_required) - << "Cannot have required positional parameters after an optional " - "one."; + CARBON_CHECK( + !arg_ptr->is_required, + "Cannot have required positional parameters after an optional one."); } } switch (command_->kind) { case Command::Kind::Invalid: - CARBON_FATAL() << "Should never have a parser with an invalid command!"; + CARBON_FATAL("Should never have a parser with an invalid command!"); case Command::Kind::RequiresSubcommand: errors_ << "ERROR: No subcommand specified. Available subcommands: "; error_meta_printer_.PrintSubcommands(*command_); @@ -1189,11 +1190,13 @@ auto Parser::FinalizeParse() -> ParseResult { auto Parser::ParsePositionalSuffix( llvm::ArrayRef unparsed_args) -> bool { - CARBON_CHECK(!command_->positional_args.empty()) - << "Cannot do positional suffix parsing without positional arguments!"; - CARBON_CHECK(!unparsed_args.empty() && unparsed_args.front() == "--") - << "Must be called with a suffix of arguments starting with a `--` that " - "switches to positional suffix parsing."; + CARBON_CHECK( + !command_->positional_args.empty(), + "Cannot do positional suffix parsing without positional arguments!"); + CARBON_CHECK( + !unparsed_args.empty() && unparsed_args.front() == "--", + "Must be called with a suffix of arguments starting with a `--` that " + "switches to positional suffix parsing."); // Once we're in the positional suffix, we can track empty positional // arguments. bool empty_positional = false; @@ -1291,9 +1294,9 @@ auto Parser::Parse(llvm::ArrayRef unparsed_args) continue; } - CARBON_CHECK(command_->positional_args.empty() || - command_->subcommands.empty()) - << "Cannot have both positional arguments and subcommands!"; + CARBON_CHECK( + command_->positional_args.empty() || command_->subcommands.empty(), + "Cannot have both positional arguments and subcommands!"); if (command_->positional_args.empty() && command_->subcommands.empty()) { errors_ << "ERROR: Found unexpected positional argument or subcommand: '" << unparsed_arg << "'\n"; @@ -1439,12 +1442,13 @@ void CommandBuilder::AddOneOfPositionalArg( void CommandBuilder::AddSubcommand( const CommandInfo& info, llvm::function_ref build) { - CARBON_CHECK(IsValidName(info.name)) - << "Invalid subcommand name: " << info.name; - CARBON_CHECK(subcommand_names_.insert(info.name).second) - << "Added a duplicate subcommand: " << info.name; - CARBON_CHECK(command_.positional_args.empty()) - << "Cannot add subcommands to a command with a positional argument."; + CARBON_CHECK(IsValidName(info.name), "Invalid subcommand name: {0}", + info.name); + CARBON_CHECK(subcommand_names_.insert(info.name).second, + "Added a duplicate subcommand: {0}", info.name); + CARBON_CHECK( + command_.positional_args.empty(), + "Cannot add subcommands to a command with a positional argument."); command_.subcommands.emplace_back(new Command(info, &command_)); CommandBuilder builder(*command_.subcommands.back(), meta_printer_); @@ -1457,25 +1461,28 @@ void CommandBuilder::HelpHidden(bool is_help_hidden) { } void CommandBuilder::RequiresSubcommand() { - CARBON_CHECK(!command_.subcommands.empty()) - << "Cannot require subcommands unless there are subcommands."; - CARBON_CHECK(command_.positional_args.empty()) - << "Cannot require subcommands and have a positional argument."; - CARBON_CHECK(command_.kind == Kind::Invalid) - << "Already established the kind of this command as: " << command_.kind; + CARBON_CHECK(!command_.subcommands.empty(), + "Cannot require subcommands unless there are subcommands."); + CARBON_CHECK(command_.positional_args.empty(), + "Cannot require subcommands and have a positional argument."); + CARBON_CHECK(command_.kind == Kind::Invalid, + "Already established the kind of this command as: {0}", + command_.kind); command_.kind = Kind::RequiresSubcommand; } void CommandBuilder::Do(ActionT action) { - CARBON_CHECK(command_.kind == Kind::Invalid) - << "Already established the kind of this command as: " << command_.kind; + CARBON_CHECK(command_.kind == Kind::Invalid, + "Already established the kind of this command as: {0}", + command_.kind); command_.kind = Kind::Action; command_.action = std::move(action); } void CommandBuilder::Meta(ActionT action) { - CARBON_CHECK(command_.kind == Kind::Invalid) - << "Already established the kind of this command as: " << command_.kind; + CARBON_CHECK(command_.kind == Kind::Invalid, + "Already established the kind of this command as: {0}", + command_.kind); command_.kind = Kind::MetaAction; command_.action = std::move(action); } @@ -1484,10 +1491,9 @@ CommandBuilder::CommandBuilder(Command& command, MetaPrinter& meta_printer) : command_(command), meta_printer_(meta_printer) {} auto CommandBuilder::AddArgImpl(const ArgInfo& info, Arg::Kind kind) -> Arg& { - CARBON_CHECK(IsValidName(info.name)) - << "Invalid argument name: " << info.name; - CARBON_CHECK(arg_names_.insert(info.name).second) - << "Added a duplicate argument name: " << info.name; + CARBON_CHECK(IsValidName(info.name), "Invalid argument name: {0}", info.name); + CARBON_CHECK(arg_names_.insert(info.name).second, + "Added a duplicate argument name: {0}", info.name); command_.options.emplace_back(new Arg(info)); Arg& arg = *command_.options.back(); @@ -1497,23 +1503,23 @@ auto CommandBuilder::AddArgImpl(const ArgInfo& info, Arg::Kind kind) -> Arg& { void CommandBuilder::AddPositionalArgImpl( const ArgInfo& info, Arg::Kind kind, llvm::function_ref build) { - CARBON_CHECK(IsValidName(info.name)) - << "Invalid argument name: " << info.name; - CARBON_CHECK(command_.subcommands.empty()) - << "Cannot add a positional argument to a command with subcommands."; + CARBON_CHECK(IsValidName(info.name), "Invalid argument name: {0}", info.name); + CARBON_CHECK( + command_.subcommands.empty(), + "Cannot add a positional argument to a command with subcommands."); command_.positional_args.emplace_back(new Arg(info)); Arg& arg = *command_.positional_args.back(); arg.kind = kind; build(arg); - CARBON_CHECK(!arg.is_help_hidden) - << "Cannot have a help-hidden positional argument."; + CARBON_CHECK(!arg.is_help_hidden, + "Cannot have a help-hidden positional argument."); if (arg.is_required && command_.positional_args.size() > 1) { - CARBON_CHECK((*std::prev(command_.positional_args.end(), 2))->is_required) - << "A required positional argument cannot be added after an optional " - "one."; + CARBON_CHECK((*std::prev(command_.positional_args.end(), 2))->is_required, + "A required positional argument cannot be added after an " + "optional one."); } } diff --git a/common/command_line.h b/common/command_line.h index c8a8a98598f9..3b0498e023df 100644 --- a/common/command_line.h +++ b/common/command_line.h @@ -735,7 +735,7 @@ struct Command { template void ArgBuilder::MetaAction(T action) { - CARBON_CHECK(!arg_.meta_action) << "Cannot set a meta action twice!"; + CARBON_CHECK(!arg_.meta_action, "Cannot set a meta action twice!"); arg_.meta_action = std::move(action); } @@ -814,9 +814,9 @@ void OneOfArgBuilder::OneOfImpl(const OneOfValueT (&input_values)[N], // Fold over all the input values to see if there is a default. if ((input_values[Indices].is_default || ...)) { - CARBON_CHECK(!arg_.is_append) << "Can't append default."; - CARBON_CHECK((input_values[Indices].is_default + ... + 0) == 1) - << "Cannot default more than one value."; + CARBON_CHECK(!arg_.is_append, "Can't append default."); + CARBON_CHECK((input_values[Indices].is_default + ... + 0) == 1, + "Cannot default more than one value."); arg_.has_default = true; diff --git a/common/error.h b/common/error.h index 9364afae75a8..ffe8557032f7 100644 --- a/common/error.h +++ b/common/error.h @@ -27,7 +27,7 @@ class [[nodiscard]] Error : public Printable { // Represents an error state. explicit Error(llvm::Twine location, llvm::Twine message) : location_(location.str()), message_(message.str()) { - CARBON_CHECK(!message_.empty()) << "Errors must have a message."; + CARBON_CHECK(!message_.empty(), "Errors must have a message."); } // Represents an error with no associated location. diff --git a/common/hashing_test.cpp b/common/hashing_test.cpp index 98d18d52172f..c332db8ccac3 100644 --- a/common/hashing_test.cpp +++ b/common/hashing_test.cpp @@ -653,7 +653,7 @@ auto FindBitRangeCollisions(llvm::ArrayRef> hashes) auto CheckNoDuplicateValues(llvm::ArrayRef hashes) -> void { for (int i = 0, size = hashes.size(); i < size - 1; ++i) { const auto& [_, value] = hashes[i]; - CARBON_CHECK(value != hashes[i + 1].v) << "Duplicate value: " << value; + CARBON_CHECK(value != hashes[i + 1].v, "Duplicate value: {0}", value); } } diff --git a/common/map.h b/common/map.h index 9cc92561282f..33c261073cec 100644 --- a/common/map.h +++ b/common/map.h @@ -472,7 +472,7 @@ MapBase::Insert( std::invocable) { auto [entry, inserted] = this->InsertImpl(lookup_key, key_context); - CARBON_DCHECK(entry) << "Should always result in a valid index."; + CARBON_DCHECK(entry, "Should always result in a valid index."); if (LLVM_LIKELY(!inserted)) { return InsertKVResult(false, *entry); @@ -538,7 +538,7 @@ MapBase::Update( std::invocable) { auto [entry, inserted] = this->InsertImpl(lookup_key, key_context); - CARBON_DCHECK(entry) << "Should always result in a valid index."; + CARBON_DCHECK(entry, "Should always result in a valid index."); if (LLVM_LIKELY(!inserted)) { update_cb(entry->key(), entry->value()); diff --git a/common/map_benchmark.cpp b/common/map_benchmark.cpp index e4224f98d08b..9b7c311bd680 100644 --- a/common/map_benchmark.cpp +++ b/common/map_benchmark.cpp @@ -460,12 +460,12 @@ static void BM_MapInsertSeq(benchmark::State& state) { MapWrapperT m; for (auto k : keys) { bool inserted = m.BenchInsert(k, MakeValue()); - CARBON_DCHECK(inserted) << "Must be a successful insert!"; + CARBON_DCHECK(inserted, "Must be a successful insert!"); } // Now insert a final random repeated key. bool inserted = m.BenchInsert(lookup_keys[i], MakeValue2()); - CARBON_DCHECK(!inserted) << "Must already be in the map!"; + CARBON_DCHECK(!inserted, "Must already be in the map!"); // Rotate through the shuffled keys. i = (i + static_cast(!inserted)) & (LookupKeysSize - 1); @@ -484,7 +484,7 @@ static void BM_MapInsertSeq(benchmark::State& state) { MapWrapperT m; for (auto k : keys) { bool inserted = m.BenchInsert(k, MakeValue()); - CARBON_DCHECK(inserted) << "Must be a successful insert!"; + CARBON_DCHECK(inserted, "Must be a successful insert!"); } ReportMetrics(m, state); diff --git a/common/raw_hashtable.h b/common/raw_hashtable.h index ff5fdace03c1..8a413ce2d8eb 100644 --- a/common/raw_hashtable.h +++ b/common/raw_hashtable.h @@ -381,8 +381,8 @@ class ViewImpl { // given size. This is trivial, but we use this routine to enforce invariants // on the sizes. static constexpr auto EntriesOffset(ssize_t alloc_size) -> ssize_t { - CARBON_DCHECK(llvm::isPowerOf2_64(alloc_size)) - << "Size must be a power of two for a hashed buffer!"; + CARBON_DCHECK(llvm::isPowerOf2_64(alloc_size), + "Size must be a power of two for a hashed buffer!"); // The size is always a power of two. We prevent any too-small sizes so it // being a power of two provides the needed alignment. As a result, the // offset is exactly the size. We validate this here to catch alignment bugs @@ -615,8 +615,8 @@ inline auto ComputeSeed() -> uint64_t { } inline auto ComputeProbeMaskFromSize(ssize_t size) -> size_t { - CARBON_DCHECK(llvm::isPowerOf2_64(size)) - << "Size must be a power of two for a hashed buffer!"; + CARBON_DCHECK(llvm::isPowerOf2_64(size), + "Size must be a power of two for a hashed buffer!"); // Since `size` is a power of two, we can make sure the probes are less // than `size` by making the mask `size - 1`. We also mask off the low // bits so the probes are a multiple of the size of the groups of entries. @@ -659,12 +659,14 @@ class ProbeSequence { // everything down by `GroupSize`. CARBON_DCHECK( (p_ / GroupSize) == - ((start_ / GroupSize + - (step_ / GroupSize + (step_ / GroupSize) * (step_ / GroupSize)) / 2) % - (size_ / GroupSize))) - << "Index in probe sequence does not match the expected formula."; - CARBON_DCHECK(step_ < size_) << "We necessarily visit all groups, so we " - "can't have more probe steps than groups."; + ((start_ / GroupSize + + (step_ / GroupSize + (step_ / GroupSize) * (step_ / GroupSize)) / + 2) % + (size_ / GroupSize)), + "Index in probe sequence does not match the expected formula."); + CARBON_DCHECK(step_ < size_, + "We necessarily visit all groups, so we can't have more " + "probe steps than groups."); #endif } @@ -924,13 +926,14 @@ auto BaseImpl::InsertImpl( } --growth_budget_; - CARBON_DCHECK(growth_budget() >= 0) - << "Growth budget shouldn't have gone negative!"; + CARBON_DCHECK(growth_budget() >= 0, + "Growth budget shouldn't have gone negative!"); return return_insert_at_index(group_index + empty_match.index()); } - CARBON_FATAL() << "We should never finish probing without finding the entry " - "or an empty slot."; + CARBON_FATAL( + "We should never finish probing without finding the entry or an empty " + "slot."); } template @@ -1264,11 +1267,11 @@ BaseImpl::InsertIntoEmpty( template auto BaseImpl::ComputeNextAllocSize( ssize_t old_alloc_size) -> ssize_t { - CARBON_DCHECK(llvm::isPowerOf2_64(old_alloc_size)) - << "Expected a power of two!"; + CARBON_DCHECK(llvm::isPowerOf2_64(old_alloc_size), + "Expected a power of two!"); ssize_t new_alloc_size; bool overflow = __builtin_mul_overflow(old_alloc_size, 2, &new_alloc_size); - CARBON_CHECK(!overflow) << "Computing the new size overflowed `ssize_t`!"; + CARBON_CHECK(!overflow, "Computing the new size overflowed `ssize_t`!"); return new_alloc_size; } @@ -1340,11 +1343,10 @@ auto BaseImpl::GrowToNextAllocSize( llvm::count(llvm::ArrayRef(old_metadata, old_size), MetadataGroup::Empty); ssize_t debug_deleted_count = llvm::count( llvm::ArrayRef(old_metadata, old_size), MetadataGroup::Deleted); - CARBON_DCHECK(debug_empty_count >= - (old_size - GrowthThresholdForAllocSize(old_size))) - << "debug_empty_count: " << debug_empty_count - << ", debug_deleted_count: " << debug_deleted_count - << ", size: " << old_size; + CARBON_DCHECK( + debug_empty_count >= (old_size - GrowthThresholdForAllocSize(old_size)), + "debug_empty_count: {0}, debug_deleted_count: {1}, size: {2}", + debug_empty_count, debug_deleted_count, old_size); #endif // Configure for the new size and allocate the new storage. diff --git a/common/raw_hashtable_benchmark_helpers.cpp b/common/raw_hashtable_benchmark_helpers.cpp index ccb82d2919b4..1199748b35fb 100644 --- a/common/raw_hashtable_benchmark_helpers.cpp +++ b/common/raw_hashtable_benchmark_helpers.cpp @@ -43,8 +43,9 @@ static auto MakeChars() -> llvm::OwningArrayRef { ++i; } } - CARBON_CHECK(i == NumChars) << "Expected exactly " << NumChars - << " characters, got " << i << " instead!"; + CARBON_CHECK(i == NumChars, + "Expected exactly {0} characters, got {1} instead!", NumChars, + i); return characters; } @@ -344,7 +345,7 @@ auto DumpHashStatistics(llvm::ArrayRef keys) -> void { GroupShift); for (auto [i, k] : llvm::enumerate(keys)) { ssize_t hash_index = get_hash_index(k); - CARBON_CHECK(hash_index < (expected_size >> GroupShift)) << hash_index; + CARBON_CHECK(hash_index < (expected_size >> GroupShift), "{0}", hash_index); grouped_key_indices[hash_index].push_back(i); } ssize_t max_group_index = diff --git a/common/raw_hashtable_metadata_group.h b/common/raw_hashtable_metadata_group.h index 497db6009388..5cc03cd4e585 100644 --- a/common/raw_hashtable_metadata_group.h +++ b/common/raw_hashtable_metadata_group.h @@ -10,6 +10,7 @@ #include #include "common/check.h" +#include "common/ostream.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/bit.h" #include "llvm/Support/FormatVariadic.h" @@ -80,14 +81,14 @@ class BitIndex // Returns true when there are no matches for the tag. auto empty() const -> bool { - CARBON_DCHECK((bits_ & ZeroMask) == 0) << "Unexpected non-zero bits!"; + CARBON_DCHECK((bits_ & ZeroMask) == 0, "Unexpected non-zero bits!"); __builtin_assume((bits_ & ZeroMask) == 0); return bits_ == 0; } // Returns the index of the first matched tag. auto index() -> ssize_t { - CARBON_DCHECK(bits_ != 0) << "Cannot get an index from zero bits!"; + CARBON_DCHECK(bits_ != 0, "Cannot get an index from zero bits!"); __builtin_assume(bits_ != 0); ssize_t index = unscaled_index(); @@ -102,7 +103,7 @@ class BitIndex // Optimized tool to index a pointer `p` by `index()`. template auto index_ptr(T* pointer) -> T* { - CARBON_DCHECK(bits_ != 0) << "Cannot get an index from zero bits!"; + CARBON_DCHECK(bits_ != 0, "Cannot get an index from zero bits!"); __builtin_assume(bits_ != 0); if constexpr (!ByteEncoding) { return &pointer[unscaled_index()]; @@ -191,7 +192,7 @@ class BitIndexRange : public Printable> { } auto operator*() -> ssize_t& { - CARBON_DCHECK(bits_ != 0) << "Cannot get an index from zero bits!"; + CARBON_DCHECK(bits_ != 0, "Cannot get an index from zero bits!"); __builtin_assume(bits_ != 0); index_ = BitIndexT(bits_).index(); // Note that we store the index in a member so we can return a reference @@ -205,7 +206,7 @@ class BitIndexRange : public Printable> { } auto operator++() -> Iterator& { - CARBON_DCHECK(bits_ != 0) << "Must not increment past the end!"; + CARBON_DCHECK(bits_ != 0, "Must not increment past the end!"); __builtin_assume(bits_ != 0); // Clears the least significant set bit, effectively stepping to the next // match. @@ -270,7 +271,7 @@ class BitIndexRange : public Printable> { // } // if (UseSIMD || DebugSIMD) { // simd_result = SIMDOperation(...) -// CARBON_DCHECK(result == portable_result) << ...; +// CARBON_DCHECK(result == portable_result, "{0}", ...); // } // return UseSIMD ? simd_result : portable_result; // } @@ -533,9 +534,8 @@ inline auto MetadataGroup::Store(uint8_t* metadata, ssize_t index) const } inline auto MetadataGroup::ClearByte(ssize_t byte_index) -> void { - CARBON_DCHECK(FastByteClear) << "Only use byte clearing when fast!"; - CARBON_DCHECK(Size == 8) - << "The clear implementation assumes an 8-byte group."; + CARBON_DCHECK(FastByteClear, "Only use byte clearing when fast!"); + CARBON_DCHECK(Size == 8, "The clear implementation assumes an 8-byte group."); metadata_ints[0] &= ~(static_cast(0xff) << (byte_index * 8)); } @@ -548,9 +548,10 @@ inline auto MetadataGroup::ClearDeleted() -> void { } if constexpr (UseSIMD || DebugSIMD) { simd_g.SIMDClearDeleted(); - CARBON_DCHECK(simd_g == portable_g) - << "SIMD cleared group '" << simd_g - << "' doesn't match portable cleared group '" << portable_g << "'"; + CARBON_DCHECK( + simd_g == portable_g, + "SIMD cleared group '{0}' doesn't match portable cleared group '{1}'", + simd_g, portable_g); } *this = UseSIMD ? simd_g : portable_g; } @@ -559,7 +560,7 @@ inline auto MetadataGroup::Match(uint8_t tag) const -> MatchRange { // The caller should provide us with the present byte hash, and not set any // present bit tag on it so that this layer can manage tagging the high bit of // a present byte. - CARBON_DCHECK((tag & PresentMask) == 0) << llvm::formatv("{0:x}", tag); + CARBON_DCHECK((tag & PresentMask) == 0, "{0:x}", tag); MatchRange portable_result; MatchRange simd_result; @@ -568,9 +569,9 @@ inline auto MetadataGroup::Match(uint8_t tag) const -> MatchRange { } if constexpr (UseSIMD || DebugSIMD) { simd_result = SIMDMatch(tag); - CARBON_DCHECK(simd_result == portable_result) - << "SIMD result '" << simd_result << "' doesn't match portable result '" - << portable_result << "'"; + CARBON_DCHECK(simd_result == portable_result, + "SIMD result '{0}' doesn't match portable result '{1}'", + simd_result, portable_result); } return UseSIMD ? simd_result : portable_result; } @@ -583,9 +584,9 @@ inline auto MetadataGroup::MatchPresent() const -> MatchRange { } if constexpr (UseSIMD || DebugSIMD) { simd_result = SIMDMatchPresent(); - CARBON_DCHECK(simd_result == portable_result) - << "SIMD result '" << simd_result << "' doesn't match portable result '" - << portable_result << "'"; + CARBON_DCHECK(simd_result == portable_result, + "SIMD result '{0}' doesn't match portable result '{1}'", + simd_result, portable_result); } return UseSIMD ? simd_result : portable_result; } @@ -598,9 +599,9 @@ inline auto MetadataGroup::MatchEmpty() const -> MatchIndex { } if constexpr (UseSIMD || DebugSIMD) { simd_result = SIMDMatchEmpty(); - CARBON_DCHECK(simd_result == portable_result) - << "SIMD result '" << simd_result << "' doesn't match portable result '" - << portable_result << "'"; + CARBON_DCHECK(simd_result == portable_result, + "SIMD result '{0}' doesn't match portable result '{1}'", + simd_result, portable_result); } return UseSIMD ? simd_result : portable_result; } @@ -613,9 +614,9 @@ inline auto MetadataGroup::MatchDeleted() const -> MatchIndex { } if constexpr (UseSIMD || DebugSIMD) { simd_result = SIMDMatchDeleted(); - CARBON_DCHECK(simd_result == portable_result) - << "SIMD result '" << simd_result << "' doesn't match portable result '" - << portable_result << "'"; + CARBON_DCHECK(simd_result == portable_result, + "SIMD result '{0}' doesn't match portable result '{1}'", + simd_result, portable_result); } return UseSIMD ? simd_result : portable_result; } @@ -640,29 +641,31 @@ inline auto MetadataGroup::VerifyIndexBits( for (ssize_t byte_index : llvm::seq(0, Size)) { if constexpr (!ByteEncoding) { if (byte_match(metadata_bytes[byte_index])) { - CARBON_CHECK(((index_bits >> byte_index) & 1) == 1) - << "Bit not set at matching byte index: " << byte_index; + CARBON_CHECK(((index_bits >> byte_index) & 1) == 1, + "Bit not set at matching byte index: {0}", byte_index); // Only the first match is needed, so stop scanning once found. break; } - CARBON_CHECK(((index_bits >> byte_index) & 1) == 0) - << "Bit set at non-matching byte index: " << byte_index; + CARBON_CHECK(((index_bits >> byte_index) & 1) == 0, + "Bit set at non-matching byte index: {0}", byte_index); } else { // `index_bits` is byte-encoded rather than bit encoded, so extract a // byte. uint8_t index_byte = (index_bits >> (byte_index * 8)) & 0xFF; if (byte_match(metadata_bytes[byte_index])) { - CARBON_CHECK((index_byte & 0x80) == 0x80) - << "Should have the high bit set for a matching byte, found: " - << llvm::formatv("{0:x}", index_byte); + CARBON_CHECK( + (index_byte & 0x80) == 0x80, + "Should have the high bit set for a matching byte, found: {0:x}", + index_byte); // Only the first match is needed so stop scanning once found. break; } - CARBON_CHECK(index_byte == 0) - << "Should have no bits set for an unmatched byte, found: " - << llvm::formatv("{0:x}", index_byte); + CARBON_CHECK( + index_byte == 0, + "Should have no bits set for an unmatched byte, found: {0:x}", + index_byte); } } return true; @@ -674,24 +677,26 @@ inline auto MetadataGroup::VerifyRangeBits( for (ssize_t byte_index : llvm::seq(0, Size)) { if constexpr (!ByteEncoding) { if (byte_match(metadata_bytes[byte_index])) { - CARBON_CHECK(((range_bits >> byte_index) & 1) == 1) - << "Bit not set at matching byte index: " << byte_index; + CARBON_CHECK(((range_bits >> byte_index) & 1) == 1, + "Bit not set at matching byte index: {0}", byte_index); } else { - CARBON_CHECK(((range_bits >> byte_index) & 1) == 0) - << "Bit set at non-matching byte index: " << byte_index; + CARBON_CHECK(((range_bits >> byte_index) & 1) == 0, + "Bit set at non-matching byte index: {0}", byte_index); } } else { // `range_bits` is byte-encoded rather than bit encoded, so extract a // byte. uint8_t range_byte = (range_bits >> (byte_index * 8)) & 0xFF; if (byte_match(metadata_bytes[byte_index])) { - CARBON_CHECK(range_byte == 0x80) - << "Should just have the high bit set for a matching byte, found: " - << llvm::formatv("{0:x}", range_byte); + CARBON_CHECK(range_byte == 0x80, + "Should just have the high bit set for a matching byte, " + "found: {0:x}", + range_byte); } else { - CARBON_CHECK(range_byte == 0) - << "Should have no bits set for an unmatched byte, found: " - << llvm::formatv("{0:x}", range_byte); + CARBON_CHECK( + range_byte == 0, + "Should have no bits set for an unmatched byte, found: {0:x}", + range_byte); } } } @@ -730,7 +735,7 @@ inline auto MetadataGroup::PortableMatch(uint8_t tag) const -> MatchRange { // The caller should provide us with the present byte hash, and not set any // present bit tag on it so that this layer can manage tagging the high bit of // a present byte. - CARBON_DCHECK((tag & PresentMask) == 0) << llvm::formatv("{0:x}", tag); + CARBON_DCHECK((tag & PresentMask) == 0, "{0:x}", tag); // Use a simple fallback approach for sizes beyond 8. // TODO: Instead of a simple fallback, we should generalize the below @@ -783,8 +788,8 @@ inline auto MetadataGroup::PortableMatch(uint8_t tag) const -> MatchRange { // know that the add cannot carry, and this way it can be lowered using // combined multiply-add instructions if available. uint64_t broadcast = LSBs * tag + MSBs; - CARBON_DCHECK(broadcast == (LSBs * tag | MSBs)) - << "Unexpected carry from addition!"; + CARBON_DCHECK(broadcast == (LSBs * tag | MSBs), + "Unexpected carry from addition!"); // Xor the broadcast byte pattern. This makes bytes with matches become 0, and // clears the high-bits of non-matches. Note that if we are looking for a tag diff --git a/common/set.h b/common/set.h index 6116dae8e376..b85027eafde1 100644 --- a/common/set.h +++ b/common/set.h @@ -372,7 +372,7 @@ auto SetBase::Insert(LookupKeyT lookup_key, requires std::invocable { auto [entry, inserted] = this->InsertImpl(lookup_key, key_context); - CARBON_DCHECK(entry) << "Should always result in a valid index."; + CARBON_DCHECK(entry, "Should always result in a valid index."); if (LLVM_LIKELY(!inserted)) { return InsertResult(false, entry->key()); diff --git a/common/set_benchmark.cpp b/common/set_benchmark.cpp index 2702cb62e853..e3b4a36e5af7 100644 --- a/common/set_benchmark.cpp +++ b/common/set_benchmark.cpp @@ -336,12 +336,12 @@ static void BM_SetInsertSeq(benchmark::State& state) { SetWrapperT s; for (auto k : keys) { bool inserted = s.BenchInsert(k); - CARBON_DCHECK(inserted) << "Must be a successful insert!"; + CARBON_DCHECK(inserted, "Must be a successful insert!"); } // Now insert a final random repeated key. bool inserted = s.BenchInsert(lookup_keys[i]); - CARBON_DCHECK(!inserted) << "Must already be in the map!"; + CARBON_DCHECK(!inserted, "Must already be in the map!"); // Rotate through the shuffled keys. i = (i + static_cast(!inserted)) & (LookupKeysSize - 1); @@ -360,7 +360,7 @@ static void BM_SetInsertSeq(benchmark::State& state) { SetT s; for (auto k : keys) { bool inserted = s.Insert(k).is_inserted(); - CARBON_DCHECK(inserted) << "Must be a successful insert!"; + CARBON_DCHECK(inserted, "Must be a successful insert!"); } ReportTableMetrics(s, state); diff --git a/explorer/ast/bindings.cpp b/explorer/ast/bindings.cpp index 827b7a3e1223..d1c1d3a8ee61 100644 --- a/explorer/ast/bindings.cpp +++ b/explorer/ast/bindings.cpp @@ -25,15 +25,15 @@ void Bindings::Add(Nonnull binding, Nonnull value, std::optional> witness) { bool added_value = args_.insert({binding, value}).second; - CARBON_CHECK(added_value) << "Add of already-existing binding"; + CARBON_CHECK(added_value, "Add of already-existing binding"); if (witness) { // TODO: Eventually we should check that we have a witness if and only if // the binding has an impl binding. auto impl_binding = binding->impl_binding(); - CARBON_CHECK(impl_binding) << "Given witness but have no impl binding"; + CARBON_CHECK(impl_binding, "Given witness but have no impl binding"); bool added_witness = witnesses_.insert({*impl_binding, *witness}).second; - CARBON_CHECK(added_witness) << "Add of already-existing binding"; + CARBON_CHECK(added_witness, "Add of already-existing binding"); } } diff --git a/explorer/ast/clone_context.cpp b/explorer/ast/clone_context.cpp index f5b2eed35ee7..e24794713ccc 100644 --- a/explorer/ast/clone_context.cpp +++ b/explorer/ast/clone_context.cpp @@ -13,10 +13,10 @@ namespace Carbon { auto CloneContext::CloneBase(Nonnull node) -> Nonnull { auto [it, added] = nodes_.insert({node, nullptr}); - CARBON_CHECK(added) << (it->second - ? "node was cloned multiple times: " - : "node was remapped before it was cloned: ") - << *node; + CARBON_CHECK( + added, "node was {0}: {1}", + it->second ? "cloned multiple times" : "remapped before it was cloned", + *node); // TODO: Generate a Visit member on AstNode and use it here to avoid these // macros. @@ -34,7 +34,7 @@ auto CloneContext::CloneBase(Nonnull node) // Cloning may have invalidated our iterator; redo lookup. auto* result = nodes_[node]; - CARBON_CHECK(result) << "CloneImpl didn't set the result pointer"; + CARBON_CHECK(result, "CloneImpl didn't set the result pointer"); return result; } diff --git a/explorer/ast/clone_context.h b/explorer/ast/clone_context.h index 7be00a42d538..fce87adc3325 100644 --- a/explorer/ast/clone_context.h +++ b/explorer/ast/clone_context.h @@ -131,7 +131,7 @@ class CloneContext { template auto GetExistingClone(Nonnull node) -> Nonnull { AstNode* cloned = nodes_.lookup(node); - CARBON_CHECK(cloned) << "expected node to be cloned"; + CARBON_CHECK(cloned, "expected node to be cloned"); return llvm::cast(cloned); } diff --git a/explorer/ast/declaration.cpp b/explorer/ast/declaration.cpp index b04f18e8ddb0..7a0670fc862c 100644 --- a/explorer/ast/declaration.cpp +++ b/explorer/ast/declaration.cpp @@ -413,7 +413,7 @@ auto FunctionDeclaration::Create(Nonnull arena, void CallableDeclaration::PrintIndent(int indent_num_spaces, llvm::raw_ostream& out) const { auto name = GetName(*this); - CARBON_CHECK(name) << "Unexpected missing name for `" << *this << "`."; + CARBON_CHECK(name, "Unexpected missing name for `{0}`.", *this); out.indent(indent_num_spaces) << "fn " << *name << " "; if (!deduced_parameters_.empty() || self_pattern_) { out << "["; diff --git a/explorer/ast/declaration.h b/explorer/ast/declaration.h index d09013f338ff..7668cbc4f686 100644 --- a/explorer/ast/declaration.h +++ b/explorer/ast/declaration.h @@ -101,7 +101,7 @@ class Declaration : public AstNode { // Set that this node is declared. Should only be called once, by the // type-checker, once the node is ready to be named and used. void set_is_declared() { - CARBON_CHECK(!is_declared_) << "should not be declared twice"; + CARBON_CHECK(!is_declared_, "should not be declared twice"); is_declared_ = true; } @@ -111,7 +111,7 @@ class Declaration : public AstNode { // Set that this node is type-checked. Should only be called once, by the // type-checker, once full type-checking is complete. void set_is_type_checked() { - CARBON_CHECK(!is_type_checked_) << "should not be type-checked twice"; + CARBON_CHECK(!is_type_checked_, "should not be type-checked twice"); is_type_checked_ = true; } @@ -674,7 +674,7 @@ class VariableDeclaration : public Declaration { // Can only be called by type-checking, if a conversion was required. void set_initializer(Nonnull initializer) { - CARBON_CHECK(has_initializer()) << "should not add a new initializer"; + CARBON_CHECK(has_initializer(), "should not add a new initializer"); initializer_ = initializer; } diff --git a/explorer/ast/element_path.h b/explorer/ast/element_path.h index 74d834ac37e2..4ba019bcd08a 100644 --- a/explorer/ast/element_path.h +++ b/explorer/ast/element_path.h @@ -113,8 +113,8 @@ class ElementPath : public Printable { // Removes all trailing `BaseElement`s, errors if there are no base elements. auto RemoveTrailingBaseElements() -> void { CARBON_CHECK(!components_.empty() && components_.back().element()->kind() == - ElementKind::BaseElement) - << "No base elements to remove."; + ElementKind::BaseElement, + "No base elements to remove."); const auto r_it = std::find_if( components_.rbegin(), components_.rend(), [](const Component& c) { return c.element()->kind() != ElementKind::BaseElement; diff --git a/explorer/ast/expression.cpp b/explorer/ast/expression.cpp index 7b216e4a671b..60212bee8684 100644 --- a/explorer/ast/expression.cpp +++ b/explorer/ast/expression.cpp @@ -231,8 +231,7 @@ void Expression::Print(llvm::raw_ostream& out) const { << *op.arguments()[1]; break; default: - CARBON_FATAL() << "Unexpected argument count: " - << op.arguments().size(); + CARBON_FATAL("Unexpected argument count: {0}", op.arguments().size()); } out << ")"; break; diff --git a/explorer/ast/expression.h b/explorer/ast/expression.h index cb9206f11b79..791e41b8f2af 100644 --- a/explorer/ast/expression.h +++ b/explorer/ast/expression.h @@ -113,7 +113,7 @@ class RewritableMixin : public Base { // Set the rewritten form of this expression. Can only be called during type // checking. auto set_rewritten_form(Nonnull rewritten_form) -> void { - CARBON_CHECK(!rewritten_form_.has_value()) << "rewritten form set twice"; + CARBON_CHECK(!rewritten_form_.has_value(), "rewritten form set twice"); rewritten_form_ = rewritten_form; this->set_static_type(&rewritten_form->static_type()); this->set_expression_category(rewritten_form->expression_category()); @@ -660,8 +660,9 @@ class StructTypeLiteral : public ConstantValueLiteral { std::vector fields) : ConstantValueLiteral(AstNodeKind::StructTypeLiteral, loc), fields_(std::move(fields)) { - CARBON_CHECK(!fields_.empty()) - << "`{}` is represented as a StructLiteral, not a StructTypeLiteral."; + CARBON_CHECK( + !fields_.empty(), + "`{}` is represented as a StructLiteral, not a StructTypeLiteral."); } explicit StructTypeLiteral(CloneContext& context, diff --git a/explorer/ast/impl_binding.h b/explorer/ast/impl_binding.h index 89a9153e37ce..0ccbef791eca 100644 --- a/explorer/ast/impl_binding.h +++ b/explorer/ast/impl_binding.h @@ -49,14 +49,14 @@ class ImplBinding : public AstNode { // The constraint being implemented. // TODO: Rename this to `constraint`. auto interface() const -> Nonnull { - CARBON_CHECK(iface_) << "interface has not been set yet"; + CARBON_CHECK(iface_, "interface has not been set yet"); return *iface_; } // Set the interface being implemented, if not set by the constructor. Should // only be called by typechecking. void set_interface(Nonnull iface) { - CARBON_CHECK(!iface_) << "interface set twice"; + CARBON_CHECK(!iface_, "interface set twice"); iface_ = iface; } @@ -75,7 +75,7 @@ class ImplBinding : public AstNode { // These functions exist only so that an `ImplBinding` can be used as a // `ValueNodeView` as a key in a `StaticScope`. auto static_type() const -> const Value& { - CARBON_FATAL() << "an ImplBinding has no type"; + CARBON_FATAL("an ImplBinding has no type"); } auto expression_category() const -> ExpressionCategory { return ExpressionCategory::Value; diff --git a/explorer/ast/pattern.h b/explorer/ast/pattern.h index a81b1f919ecc..c1d3c42b73b1 100644 --- a/explorer/ast/pattern.h +++ b/explorer/ast/pattern.h @@ -79,7 +79,7 @@ class Pattern : public AstNode { // Sets the value of this pattern. Can only be called once, during // typechecking. void set_value(Nonnull value) { - CARBON_CHECK(!value_) << "set_value called more than once"; + CARBON_CHECK(!value_, "set_value called more than once"); value_ = value; } @@ -307,7 +307,7 @@ class GenericBinding : public Pattern { // Set the index of this binding. Should be called only during type-checking. void set_index(int index) { - CARBON_CHECK(!index_) << "should only set depth and index once"; + CARBON_CHECK(!index_, "should only set depth and index once"); index_ = index; } diff --git a/explorer/ast/statement.h b/explorer/ast/statement.h index e90504380205..efb194820d75 100644 --- a/explorer/ast/statement.h +++ b/explorer/ast/statement.h @@ -150,7 +150,7 @@ class Assign : public Statement { // Set the rewritten form of this statement. Can only be called during type // checking. auto set_rewritten_form(Nonnull rewritten_form) -> void { - CARBON_CHECK(!rewritten_form_.has_value()) << "rewritten form set twice"; + CARBON_CHECK(!rewritten_form_.has_value(), "rewritten form set twice"); rewritten_form_ = rewritten_form; } @@ -196,7 +196,7 @@ class IncrementDecrement : public Statement { // Set the rewritten form of this statement. Can only be called during type // checking. auto set_rewritten_form(Nonnull rewritten_form) -> void { - CARBON_CHECK(!rewritten_form_.has_value()) << "rewritten form set twice"; + CARBON_CHECK(!rewritten_form_.has_value(), "rewritten form set twice"); rewritten_form_ = rewritten_form; } @@ -256,7 +256,7 @@ class VariableDefinition : public Statement { // Can only be called by type-checking, if a conversion was required. void set_init(Nonnull init) { - CARBON_CHECK(has_init()) << "should not add a new initializer"; + CARBON_CHECK(has_init(), "should not add a new initializer"); init_ = init; } diff --git a/explorer/ast/static_scope.cpp b/explorer/ast/static_scope.cpp index f5d6b62964e1..480bdb061935 100644 --- a/explorer/ast/static_scope.cpp +++ b/explorer/ast/static_scope.cpp @@ -54,7 +54,7 @@ void StaticScope::PrintID(llvm::raw_ostream& out) const { void StaticScope::MarkDeclared(std::string_view name) { auto it = declared_names_.find(name); - CARBON_CHECK(it != declared_names_.end()) << name << " not found"; + CARBON_CHECK(it != declared_names_.end(), "{0} not found", name); if (it->second.status == NameStatus::KnownButNotDeclared) { it->second.status = NameStatus::DeclaredButNotUsable; if (trace_stream_->is_enabled()) { @@ -67,7 +67,7 @@ void StaticScope::MarkDeclared(std::string_view name) { void StaticScope::MarkUsable(std::string_view name) { auto it = declared_names_.find(name); - CARBON_CHECK(it != declared_names_.end()) << name << " not found"; + CARBON_CHECK(it != declared_names_.end(), "{0} not found", name); it->second.status = NameStatus::Usable; if (trace_stream_->is_enabled()) { trace_stream_->Result() diff --git a/explorer/ast/value.cpp b/explorer/ast/value.cpp index bbd87ab7c1dc..b17792bb24b2 100644 --- a/explorer/ast/value.cpp +++ b/explorer/ast/value.cpp @@ -159,8 +159,8 @@ static auto GetPositionalElement(Nonnull tuple, const ElementPath::Component& path_comp, SourceLocation source_loc) -> ErrorOr> { - CARBON_CHECK(path_comp.element()->kind() == ElementKind::PositionalElement) - << "Invalid non-tuple member"; + CARBON_CHECK(path_comp.element()->kind() == ElementKind::PositionalElement, + "Invalid non-tuple member"); const auto* tuple_element = cast(path_comp.element()); const size_t index = tuple_element->index(); if (index < 0 || index >= tuple->elements().size()) { @@ -175,8 +175,8 @@ static auto GetNamedElement(Nonnull arena, Nonnull v, SourceLocation source_loc, std::optional> me_value) -> ErrorOr> { - CARBON_CHECK(field.element()->kind() == ElementKind::NamedElement) - << "Invalid element, expecting NamedElement"; + CARBON_CHECK(field.element()->kind() == ElementKind::NamedElement, + "Invalid element, expecting NamedElement"); const auto* member = cast(field.element()); const auto f = member->name(); if (field.witness().has_value()) { @@ -186,7 +186,7 @@ static auto GetNamedElement(Nonnull arena, Nonnull v, if (const auto* assoc_const = dyn_cast_or_null( member->declaration().value_or(nullptr))) { - CARBON_CHECK(field.interface()) << "have witness but no interface"; + CARBON_CHECK(field.interface(), "have witness but no interface"); // TODO: Use witness to find the value of the constant. return arena->New(v, *field.interface(), assoc_const, witness); @@ -259,8 +259,8 @@ static auto GetNamedElement(Nonnull arena, Nonnull v, // Get class value matching the virtual method, and turn it into a // bound method. for (int i = 0; i < level_diff; ++i) { - CARBON_CHECK(m_class_value->base()) - << "Error trying to access function class value"; + CARBON_CHECK(m_class_value->base(), + "Error trying to access function class value"); m_class_value = *m_class_value->base(); } return arena->New( @@ -299,7 +299,7 @@ static auto GetNamedElement(Nonnull arena, Nonnull v, &class_type.bindings()); } default: - CARBON_FATAL() << "named element access not supported for value " << *v; + CARBON_FATAL("named element access not supported for value {0}", *v); } } @@ -315,7 +315,7 @@ static auto GetElement(Nonnull arena, Nonnull v, if (const auto* tuple = dyn_cast(v)) { return GetPositionalElement(tuple, path_comp, source_loc); } else { - CARBON_FATAL() << "Invalid value for positional element"; + CARBON_FATAL("Invalid value for positional element"); } } case ElementKind::BaseElement: @@ -328,7 +328,7 @@ static auto GetElement(Nonnull arena, Nonnull v, ptr->address().ElementAddress(path_comp.element())); } default: - CARBON_FATAL() << "Invalid value for base element"; + CARBON_FATAL("Invalid value for base element"); } } } @@ -404,9 +404,9 @@ static auto SetFieldImpl( } case Value::Kind::TupleType: case Value::Kind::TupleValue: { - CARBON_CHECK((*path_begin).element()->kind() == - ElementKind::PositionalElement) - << "Invalid non-positional member for tuple"; + CARBON_CHECK( + (*path_begin).element()->kind() == ElementKind::PositionalElement, + "Invalid non-positional member for tuple"); std::vector> elements = cast(*value).elements(); const size_t index = @@ -425,7 +425,7 @@ static auto SetFieldImpl( } } default: - CARBON_FATAL() << "field access not allowed for value " << *value; + CARBON_FATAL("field access not allowed for value {0}", *value); } } @@ -841,7 +841,7 @@ void IntrinsicConstraint::Print(llvm::raw_ostream& out) const { static auto BindingMapEqual( const BindingMap& map1, const BindingMap& map2, std::optional> equality_ctx) -> bool { - CARBON_CHECK(map1.size() == map2.size()) << "maps should have same keys"; + CARBON_CHECK(map1.size() == map2.size(), "maps should have same keys"); for (const auto& [key, value] : map1) { if (!ValueEqual(value, map2.at(key), equality_ctx)) { return false; @@ -1025,17 +1025,16 @@ auto TypeEqual(Nonnull t1, Nonnull t2, case Value::Kind::MixinPseudoType: case Value::Kind::TypeOfMixinPseudoType: case Value::Kind::TypeOfNamespaceName: - CARBON_FATAL() << "TypeEqual used to compare non-type values\n" - << *t1 << "\n" - << *t2; + CARBON_FATAL("TypeEqual used to compare non-type values\n{0}\n{1}", *t1, + *t2); case Value::Kind::ImplWitness: case Value::Kind::BindingWitness: case Value::Kind::ConstraintWitness: case Value::Kind::ConstraintImplWitness: - CARBON_FATAL() << "TypeEqual: unexpected Witness"; + CARBON_FATAL("TypeEqual: unexpected Witness"); break; case Value::Kind::AutoType: - CARBON_FATAL() << "TypeEqual: unexpected AutoType"; + CARBON_FATAL("TypeEqual: unexpected AutoType"); break; } } @@ -1123,8 +1122,8 @@ static auto ValueStructurallyEqual( GetName(cast(v1)->declaration()); std::optional name2 = GetName(cast(v2)->declaration()); - CARBON_CHECK(name1.has_value() && name2.has_value()) - << "parameterized name refers to unnamed declaration"; + CARBON_CHECK(name1.has_value() && name2.has_value(), + "parameterized name refers to unnamed declaration"); return *name1 == *name2; } case Value::Kind::AssociatedConstant: { @@ -1171,8 +1170,7 @@ static auto ValueStructurallyEqual( case Value::Kind::MemberName: // TODO: support pointer comparisons once we have a clearer distinction // between pointers and lvalues. - CARBON_FATAL() << "ValueEqual does not support this kind of value: " - << *v1; + CARBON_FATAL("ValueEqual does not support this kind of value: {0}", *v1); } } diff --git a/explorer/ast/value.h b/explorer/ast/value.h index 49211f9e164d..ed3e4b6b353e 100644 --- a/explorer/ast/value.h +++ b/explorer/ast/value.h @@ -924,8 +924,8 @@ class MixinPseudoType : public Value { public: explicit MixinPseudoType(Nonnull declaration) : Value(Kind::MixinPseudoType), declaration_(declaration) { - CARBON_CHECK(!declaration->params().has_value()) - << "missing arguments for parameterized mixin type"; + CARBON_CHECK(!declaration->params().has_value(), + "missing arguments for parameterized mixin type"); } explicit MixinPseudoType(Nonnull declaration, Nonnull bindings) @@ -982,8 +982,8 @@ class InterfaceType : public Value { public: explicit InterfaceType(Nonnull declaration) : Value(Kind::InterfaceType), declaration_(declaration) { - CARBON_CHECK(!declaration->params().has_value()) - << "missing arguments for parameterized interface type"; + CARBON_CHECK(!declaration->params().has_value(), + "missing arguments for parameterized interface type"); } explicit InterfaceType(Nonnull declaration, Nonnull bindings) @@ -1334,8 +1334,8 @@ class ConstraintImplWitness : public Witness { // element. static auto Make(Nonnull arena, Nonnull witness, int index) -> Nonnull { - CARBON_CHECK(!llvm::isa(witness)) - << "impl witness has no components to access"; + CARBON_CHECK(!llvm::isa(witness), + "impl witness has no components to access"); if (const auto* constraint_witness = llvm::dyn_cast(witness)) { return constraint_witness->witnesses()[index]; @@ -1348,8 +1348,8 @@ class ConstraintImplWitness : public Witness { : Witness(Kind::ConstraintImplWitness), constraint_witness_(constraint_witness), index_(index) { - CARBON_CHECK(!llvm::isa(constraint_witness)) - << "should have resolved element from constraint witness"; + CARBON_CHECK(!llvm::isa(constraint_witness), + "should have resolved element from constraint witness"); } static auto classof(const Value* value) -> bool { @@ -1480,8 +1480,8 @@ class MemberName : public Value, public Printable { base_type_(base_type), interface_(interface), member_(member) { - CARBON_CHECK(base_type || interface) - << "member name must be in a type, an interface, or both"; + CARBON_CHECK(base_type || interface, + "member name must be in a type, an interface, or both"); } static auto classof(const Value* value) -> bool { diff --git a/explorer/file_test.cpp b/explorer/file_test.cpp index 89f60d63c03a..90791dcb85be 100644 --- a/explorer/file_test.cpp +++ b/explorer/file_test.cpp @@ -23,8 +23,8 @@ class ExplorerFileTest : public FileTestBase { : FileTestBase(test_name), prelude_line_re_(R"(prelude.carbon:(\d+))"), timing_re_(R"((Time elapsed in \w+: )\d+(ms))") { - CARBON_CHECK(prelude_line_re_.ok()) << prelude_line_re_.error(); - CARBON_CHECK(timing_re_.ok()) << timing_re_.error(); + CARBON_CHECK(prelude_line_re_.ok(), "{0}", prelude_line_re_.error()); + CARBON_CHECK(timing_re_.ok(), "{0}", timing_re_.error()); } auto Run(const llvm::SmallVector& test_args, diff --git a/explorer/fuzzing/ast_to_proto.cpp b/explorer/fuzzing/ast_to_proto.cpp index 62e7ce0b6d1f..d02835936951 100644 --- a/explorer/fuzzing/ast_to_proto.cpp +++ b/explorer/fuzzing/ast_to_proto.cpp @@ -638,10 +638,10 @@ static auto DeclarationToProto(const Declaration& declaration) default: // Parser shouldn't allow self_pattern to be anything other than // AddrPattern or BindingPattern - CARBON_FATAL() - << "self_pattern in method declaration can be either " - "AddrPattern or BindingPattern. Actual pattern: " - << function.self_pattern(); + CARBON_FATAL( + "self_pattern in method declaration can be either AddrPattern " + "or BindingPattern. Actual pattern: {0}", + function.self_pattern()); break; } } @@ -674,10 +674,10 @@ static auto DeclarationToProto(const Declaration& declaration) default: // Parser shouldn't allow self_pattern to be anything other than // AddrPattern or BindingPattern - CARBON_FATAL() - << "self_pattern in method declaration can be either " - "AddrPattern or BindingPattern. Actual pattern: " - << function.self_pattern(); + CARBON_FATAL( + "self_pattern in method declaration can be either AddrPattern " + "or BindingPattern. Actual pattern: {0}", + function.self_pattern()); break; } } @@ -833,7 +833,7 @@ static auto DeclarationToProto(const Declaration& declaration) } case DeclarationKind::SelfDeclaration: { - CARBON_FATAL() << "Unreachable SelfDeclaration in DeclarationToProto()."; + CARBON_FATAL("Unreachable SelfDeclaration in DeclarationToProto()."); } case DeclarationKind::AliasDeclaration: { diff --git a/explorer/fuzzing/fuzzer_util.cpp b/explorer/fuzzing/fuzzer_util.cpp index 6f6fe713e360..13069e7acbc7 100644 --- a/explorer/fuzzing/fuzzer_util.cpp +++ b/explorer/fuzzing/fuzzer_util.cpp @@ -38,10 +38,10 @@ auto ParseAndExecuteProto(const Fuzzing::Carbon& carbon) -> ErrorOr { const ErrorOr prelude_path = GetRunfilesFile("carbon/explorer/data/prelude.carbon"); // Can't do anything without a prelude, so it's a fatal error. - CARBON_CHECK(prelude_path.ok()) << prelude_path.error(); + CARBON_CHECK(prelude_path.ok(), "{0}", prelude_path.error()); llvm::ErrorOr> prelude = llvm::MemoryBuffer::getFile(*prelude_path); - CARBON_CHECK(!prelude.getError()) << prelude.getError().message(); + CARBON_CHECK(!prelude.getError(), "{0}", prelude.getError().message()); CARBON_CHECK(fs.addFile("prelude.carbon", /*ModificationTime=*/0, std::move(*prelude))); diff --git a/explorer/interpreter/action.cpp b/explorer/interpreter/action.cpp index 0c0b0c2e3c2c..d29331116c54 100644 --- a/explorer/interpreter/action.cpp +++ b/explorer/interpreter/action.cpp @@ -56,19 +56,19 @@ void RuntimeScope::Bind(ValueNodeView value_node, Address address) { bool success = locals_.insert({value_node, heap_->arena().New(address)}) .second; - CARBON_CHECK(success) << "Duplicate definition of " << value_node.base(); + CARBON_CHECK(success, "Duplicate definition of {0}", value_node.base()); } void RuntimeScope::BindAndPin(ValueNodeView value_node, Address address) { Bind(value_node, address); bool success = bound_values_.insert(&value_node.base()).second; - CARBON_CHECK(success) << "Duplicate pinned node for " << value_node.base(); + CARBON_CHECK(success, "Duplicate pinned node for {0}", value_node.base()); heap_->BindValueToReference(value_node, address); } void RuntimeScope::BindLifetimeToScope(Address address) { - CARBON_CHECK(address.element_path_.IsEmpty()) - << "Cannot extend lifetime of a specific sub-element"; + CARBON_CHECK(address.element_path_.IsEmpty(), + "Cannot extend lifetime of a specific sub-element"); allocations_.push_back(address.allocation_); } @@ -77,7 +77,7 @@ void RuntimeScope::BindValue(ValueNodeView value_node, CARBON_CHECK(!value_node.constant_value().has_value()); CARBON_CHECK(value->kind() != Value::Kind::LocationValue); bool success = locals_.insert({value_node, value}).second; - CARBON_CHECK(success) << "Duplicate definition of " << value_node.base(); + CARBON_CHECK(success, "Duplicate definition of {0}", value_node.base()); } auto RuntimeScope::Initialize(ValueNodeView value_node, @@ -89,7 +89,7 @@ auto RuntimeScope::Initialize(ValueNodeView value_node, const auto* location = heap_->arena().New(Address(allocations_.back())); bool success = locals_.insert({value_node, location}).second; - CARBON_CHECK(success) << "Duplicate definition of " << value_node.base(); + CARBON_CHECK(success, "Duplicate definition of {0}", value_node.base()); return location; } @@ -97,11 +97,11 @@ void RuntimeScope::Merge(RuntimeScope other) { CARBON_CHECK(heap_ == other.heap_); for (auto& element : other.locals_) { bool success = locals_.insert(element).second; - CARBON_CHECK(success) << "Duplicate definition of " << element.first; + CARBON_CHECK(success, "Duplicate definition of {0}", element.first); } for (const auto* element : other.bound_values_) { bool success = bound_values_.insert(element).second; - CARBON_CHECK(success) << "Duplicate bound value."; + CARBON_CHECK(success, "Duplicate bound value."); } allocations_.insert(allocations_.end(), other.allocations_.begin(), other.allocations_.end()); diff --git a/explorer/interpreter/action.h b/explorer/interpreter/action.h index b6de1cf0c9cf..c826cd8e81ff 100644 --- a/explorer/interpreter/action.h +++ b/explorer/interpreter/action.h @@ -346,7 +346,7 @@ class StatementAction : public Action { // Sets the location provided to an initializing expression. auto set_location_created(AllocationId location_created) { - CARBON_CHECK(!location_created_) << "location created set twice"; + CARBON_CHECK(!location_created_, "location created set twice"); location_created_ = location_created; } // Returns the location provided to an initializing expression, if any. diff --git a/explorer/interpreter/action_stack.cpp b/explorer/interpreter/action_stack.cpp index c6ada2f77929..e60b81a43174 100644 --- a/explorer/interpreter/action_stack.cpp +++ b/explorer/interpreter/action_stack.cpp @@ -92,7 +92,7 @@ void ActionStack::MergeScope(RuntimeScope scope) { globals_->Merge(std::move(scope)); return; } - CARBON_FATAL() << "No current scope"; + CARBON_FATAL("No current scope"); } namespace { @@ -132,9 +132,9 @@ auto ActionStack::FinishAction() -> ErrorOr { std::unique_ptr act = Pop(); switch (FinishActionKindFor(act->kind())) { case FinishActionKind::Value: - CARBON_FATAL() << "This kind of action must produce a result: " << *act; + CARBON_FATAL("This kind of action must produce a result: {0}", *act); case FinishActionKind::NeverCalled: - CARBON_FATAL() << "Should not call FinishAction for: " << *act; + CARBON_FATAL("Should not call FinishAction for: {0}", *act); case FinishActionKind::NoValue: PopScopes(scopes_to_destroy); break; @@ -150,9 +150,9 @@ auto ActionStack::FinishAction(Nonnull result) std::unique_ptr act = Pop(); switch (FinishActionKindFor(act->kind())) { case FinishActionKind::NoValue: - CARBON_FATAL() << "This kind of action cannot produce results: " << *act; + CARBON_FATAL("This kind of action cannot produce results: {0}", *act); case FinishActionKind::NeverCalled: - CARBON_FATAL() << "Should not call FinishAction for: " << *act; + CARBON_FATAL("Should not call FinishAction for: {0}", *act); case FinishActionKind::Value: PopScopes(scopes_to_destroy); SetResult(result); @@ -183,8 +183,8 @@ auto ActionStack::ReplaceWith(std::unique_ptr replacement) -> ErrorOr { std::unique_ptr old = Pop(); CARBON_CHECK(FinishActionKindFor(old->kind()) == - FinishActionKindFor(replacement->kind())) - << "Can't replace action " << *old << " with " << *replacement; + FinishActionKindFor(replacement->kind()), + "Can't replace action {0} with {1}", *old, *replacement); Push(std::move(replacement)); return Success(); } diff --git a/explorer/interpreter/heap.cpp b/explorer/interpreter/heap.cpp index 2a35e8d59dab..1f8fad521e26 100644 --- a/explorer/interpreter/heap.cpp +++ b/explorer/interpreter/heap.cpp @@ -116,8 +116,8 @@ auto Heap::Deallocate(AllocationId allocation) -> ErrorOr { if (states_[allocation.index_] != ValueState::Dead) { states_[allocation.index_] = ValueState::Dead; } else { - CARBON_FATAL() << "deallocating an already dead value: " - << *values_[allocation.index_]; + CARBON_FATAL("deallocating an already dead value: {0}", + *values_[allocation.index_]); } if (trace_stream_->is_enabled()) { diff --git a/explorer/interpreter/impl_scope.cpp b/explorer/interpreter/impl_scope.cpp index e5e4e637cbd8..9d5b1c6559eb 100644 --- a/explorer/interpreter/impl_scope.cpp +++ b/explorer/interpreter/impl_scope.cpp @@ -28,8 +28,8 @@ void ImplScope::Add(Nonnull iface, const TypeChecker& type_checker, std::optional sort_key) { if (const auto* constraint = dyn_cast(iface)) { - CARBON_CHECK(!sort_key) - << "should only be given a sort key for an impl of an interface"; + CARBON_CHECK(!sort_key, + "should only be given a sort key for an impl of an interface"); // The caller should have substituted `.Self` for `type` already. Add(constraint->impls_constraints(), deduced, impl_bindings, witness, type_checker); @@ -85,8 +85,8 @@ static auto DiagnoseUnequalValues(SourceLocation source_loc, Nonnull b_evaluated, Nonnull equality_ctx) -> Error { - CARBON_CHECK(!ValueEqual(a_evaluated, b_evaluated, equality_ctx)) - << "expected unequal values"; + CARBON_CHECK(!ValueEqual(a_evaluated, b_evaluated, equality_ctx), + "expected unequal values"); auto error = ProgramError(source_loc); error << "constraint requires that " << *a_written; if (!ValueEqual(a_written, a_evaluated, std::nullopt)) { @@ -110,7 +110,7 @@ auto ImplScope::Resolve(Nonnull constraint_type, std::optional> witness, TryResolve(constraint_type, impl_type, source_loc, type_checker, bindings, /*diagnose_missing_impl=*/true)); - CARBON_CHECK(witness) << "should have diagnosed missing impl"; + CARBON_CHECK(witness, "should have diagnosed missing impl"); return *witness; } @@ -238,7 +238,7 @@ auto ImplScope::TryResolve(Nonnull constraint_type, } return {type_checker.MakeConstraintWitness(std::move(witnesses))}; } - CARBON_FATAL() << "expected a constraint, not " << *constraint_type; + CARBON_FATAL("expected a constraint, not {0}", *constraint_type); } auto ImplScope::VisitEqualValues( @@ -333,7 +333,7 @@ static auto CombineResults(Nonnull iface_type, return b; } } - CARBON_CHECK(impl_a && impl_b) << "non-final impl should not be symbolic"; + CARBON_CHECK(impl_a && impl_b, "non-final impl should not be symbolic"); // At this point, we're comparing two `impl` declarations, and either they're // both final or neither of them is. diff --git a/explorer/interpreter/interpreter.cpp b/explorer/interpreter/interpreter.cpp index bd3d057953d3..30d9f1d20405 100644 --- a/explorer/interpreter/interpreter.cpp +++ b/explorer/interpreter/interpreter.cpp @@ -292,8 +292,8 @@ auto Interpreter::EvalPrim(Operator op, Nonnull /*static_type*/, case Operator::BitShiftLeft: case Operator::BitShiftRight: case Operator::Complement: - CARBON_FATAL() << "operator " << OperatorToString(op) - << " should always be rewritten"; + CARBON_FATAL("operator {0} should always be rewritten", + OperatorToString(op)); } } @@ -320,7 +320,7 @@ auto Interpreter::StepLocation() -> ErrorOr { Nonnull value, todo_.ValueOfNode(cast(exp).value_node(), exp.source_loc())); - CARBON_CHECK(isa(value)) << *value; + CARBON_CHECK(isa(value), "{0}", *value); return todo_.FinishAction(value); } case ExpressionKind::SimpleMemberAccessExpression: { @@ -361,8 +361,8 @@ auto Interpreter::StepLocation() -> ErrorOr { if (constant_value) { return todo_.FinishAction(act.results().back()); } - CARBON_CHECK(!access.member().interface().has_value()) - << "unexpected location interface member"; + CARBON_CHECK(!access.member().interface().has_value(), + "unexpected location interface member"); CARBON_ASSIGN_OR_RETURN( Nonnull val, Convert(act.results()[0], *access.member().base_type(), @@ -411,8 +411,8 @@ auto Interpreter::StepLocation() -> ErrorOr { return todo_.ReplaceWith(std::make_unique(*rewrite)); } if (op.op() != Operator::Deref) { - CARBON_FATAL() - << "Can't treat primitive operator expression as location: " << exp; + CARBON_FATAL( + "Can't treat primitive operator expression as location: {0}", exp); } if (act.pos() == 0) { return todo_.Spawn( @@ -442,9 +442,9 @@ auto Interpreter::StepLocation() -> ErrorOr { case ExpressionKind::DotSelfExpression: case ExpressionKind::ArrayTypeLiteral: case ExpressionKind::BuiltinConvertExpression: - CARBON_FATAL() << "Can't treat expression as location: " << exp; + CARBON_FATAL("Can't treat expression as location: {0}", exp); case ExpressionKind::UnimplementedExpression: - CARBON_FATAL() << "Unimplemented: " << exp; + CARBON_FATAL("Unimplemented: {0}", exp); } } @@ -478,8 +478,8 @@ auto Interpreter::EvalAssociatedConstant( const auto* impl_witness = dyn_cast(witness); if (!impl_witness) { - CARBON_CHECK(phase() == Phase::CompileTime) - << "symbolic witnesses should only be formed at compile time"; + CARBON_CHECK(phase() == Phase::CompileTime, + "symbolic witnesses should only be formed at compile time"); CARBON_ASSIGN_OR_RETURN(Nonnull base, InstantiateType(&assoc->base(), source_loc)); return arena_->New(base, cast(interface), @@ -500,10 +500,11 @@ auto Interpreter::EvalAssociatedConstant( } } if (!result) { - CARBON_FATAL() << impl_witness->declaration() << " with constraint " - << *constraint - << " is missing value for associated constant " - << *interface << "." << assoc->constant().binding().name(); + CARBON_FATAL( + "{0} with constraint {1} is missing value for associated constant " + "{2}.{3}", + impl_witness->declaration(), *constraint, *interface, + assoc->constant().binding().name()); } return *result; } @@ -615,9 +616,9 @@ auto Interpreter::ConvertStructToClass( InstantiateType(class_type, source_loc)); for (const auto& field : init_struct->elements()) { if (field.name == NominalClassValue::BaseField) { - CARBON_CHECK(class_type->base().has_value()) - << "Invalid 'base' field for class '" - << class_type->declaration().name() << "' without base class."; + CARBON_CHECK(class_type->base().has_value(), + "Invalid 'base' field for class '{0}' without base class.", + class_type->declaration().name()); CARBON_ASSIGN_OR_RETURN( auto base, Convert(field.value, class_type->base().value(), source_loc)); @@ -626,8 +627,8 @@ auto Interpreter::ConvertStructToClass( struct_values.push_back(field); } } - CARBON_CHECK(!cast(inst_class)->base() || base_instance) - << "Invalid conversion for `" << *inst_class << "`: base class missing"; + CARBON_CHECK(!cast(inst_class)->base() || base_instance, + "Invalid conversion for `{0}`: base class missing", *inst_class); auto* converted_init_struct = arena_->New(std::move(struct_values)); Nonnull class_value_ptr = @@ -714,15 +715,15 @@ auto Interpreter::Convert(Nonnull value, case Value::Kind::ConstraintType: case Value::Kind::NamedConstraintType: case Value::Kind::InterfaceType: { - CARBON_CHECK(struct_val.elements().empty()) - << "only empty structs convert to `type`"; + CARBON_CHECK(struct_val.elements().empty(), + "only empty structs convert to `type`"); return arena_->New(); } default: { CARBON_CHECK(IsValueKindDependent(destination_type) || - isa(destination_type)) - << "Can't convert value " << *value << " to type " - << *destination_type; + (isa(destination_type)), + "Can't convert value {0} to type {1}", *value, + *destination_type); return value; } } @@ -757,9 +758,9 @@ auto Interpreter::Convert(Nonnull value, } default: { CARBON_CHECK(IsValueKindDependent(destination_type) || - isa(destination_type)) - << "Can't convert value " << *value << " to type " - << *destination_type; + (isa(destination_type)), + "Can't convert value {0} to type {1}", *value, + *destination_type); return value; } } @@ -832,8 +833,8 @@ auto Interpreter::Convert(Nonnull value, const auto* src_ptr = cast(value); CARBON_ASSIGN_OR_RETURN(const auto* pointee, heap_.Read(src_ptr->address(), source_loc)) - CARBON_CHECK(pointee->kind() == Value::Kind::NominalClassValue) - << "Unexpected pointer type"; + CARBON_CHECK(pointee->kind() == Value::Kind::NominalClassValue, + "Unexpected pointer type"); // Conversion logic for subtyping for function arguments only. // TODO: Drop when able to rewrite subtyping in TypeChecker for arguments. @@ -945,7 +946,7 @@ auto Interpreter::CallFunction(const CallExpression& call, ExpressionResult::Value(converted_args), call.source_loc(), &function_scope, generic_args, trace_stream_, this->arena_); - CARBON_CHECK(success) << "Failed to bind arguments to parameters"; + CARBON_CHECK(success, "Failed to bind arguments to parameters"); return todo_.Spawn(std::make_unique(*function.body(), location_received), std::move(function_scope)); @@ -977,7 +978,7 @@ auto Interpreter::CallFunction(const CallExpression& call, return todo_.FinishAction(arena_->New( &cast(decl), bindings)); default: - CARBON_FATAL() << "unknown kind of ParameterizedEntityName " << decl; + CARBON_FATAL("unknown kind of ParameterizedEntityName {0}", decl); } } default: @@ -997,8 +998,8 @@ auto Interpreter::CallDestructor(Nonnull fun, BindSelfIfPresent(fun, receiver, method_scope, generic_args, SourceLocation::DiagnosticsIgnored()); - CARBON_CHECK(method.body().has_value()) - << "Calling a method that's missing a body"; + CARBON_CHECK(method.body().has_value(), + "Calling a method that's missing a body"); auto act = std::make_unique(*method.body(), std::nullopt); return todo_.Spawn(std::unique_ptr(std::move(act)), @@ -1019,7 +1020,7 @@ void Interpreter::BindSelfIfPresent(Nonnull decl, bool success = PatternMatch(placeholder, receiver, source_location, &method_scope, generic_args, trace_stream_, this->arena_); - CARBON_CHECK(success) << "Failed to bind self"; + CARBON_CHECK(success, "Failed to bind self"); } } else { // Mutable self with `[addr self: Self*]` @@ -1036,7 +1037,7 @@ void Interpreter::BindSelfIfPresent(Nonnull decl, } bool success = PatternMatch(self_pattern, v, source_location, &method_scope, generic_args, trace_stream_, this->arena_); - CARBON_CHECK(success) << "Failed to bind addr self"; + CARBON_CHECK(success, "Failed to bind addr self"); } } @@ -1245,8 +1246,8 @@ auto Interpreter::StepExp() -> ErrorOr { dyn_cast(&access.static_type())) { // The result is a member name, such as in `Type.field_name`. Form a // suitable member name value. - CARBON_CHECK(phase() == Phase::CompileTime) - << "should not form MemberNames at runtime"; + CARBON_CHECK(phase() == Phase::CompileTime, + "should not form MemberNames at runtime"); auto found_in_interface = access.found_in_interface(); if (act.pos() == 1 && found_in_interface) { return todo_.Spawn(std::make_unique( @@ -1365,8 +1366,8 @@ auto Interpreter::StepExp() -> ErrorOr { return todo_.FinishAction(act.results().back()); } } else if (forming_member_name) { - CARBON_CHECK(phase() == Phase::CompileTime) - << "should not form MemberNames at runtime"; + CARBON_CHECK(phase() == Phase::CompileTime, + "should not form MemberNames at runtime"); if (auto found_in_interface = access.member().interface(); found_in_interface && act.pos() == 1) { return todo_.Spawn(std::make_unique( @@ -1378,9 +1379,9 @@ auto Interpreter::StepExp() -> ErrorOr { if (found_in_interface) { found_in_interface = cast(act.results().back()); } - CARBON_CHECK(!access.member().base_type().has_value()) - << "compound member access forming a member name should be " - "performing impl lookup"; + CARBON_CHECK(!access.member().base_type().has_value(), + "compound member access forming a member name should " + "be performing impl lookup"); auto* member_name = arena_->New(act.results()[0], found_in_interface, &access.member().member()); @@ -1427,8 +1428,8 @@ auto Interpreter::StepExp() -> ErrorOr { if (access.impl().has_value()) { witness = cast(act.results()[1]); } else { - CARBON_CHECK(access.member().base_type().has_value()) - << "compound access should have base type or impl"; + CARBON_CHECK(access.member().base_type().has_value(), + "compound access should have base type or impl"); CARBON_ASSIGN_OR_RETURN( object, Convert(object, *access.member().base_type(), exp.source_loc())); @@ -1582,7 +1583,7 @@ auto Interpreter::StepExp() -> ErrorOr { return todo_.FinishAction(act.results()[function_call_pos]); } } else { - CARBON_FATAL() << "in StepValueExp with Call pos " << act.pos(); + CARBON_FATAL("in StepValueExp with Call pos {0}", act.pos()); } } case ExpressionKind::IntrinsicExpression: { @@ -1622,7 +1623,7 @@ auto Interpreter::StepExp() -> ErrorOr { break; } default: - CARBON_FATAL() << "Too many format args: " << num_format_args; + CARBON_FATAL("Too many format args: {0}", num_format_args); } // Implicit newline; currently no way to disable it. *print_stream_ << "\n"; @@ -1712,9 +1713,9 @@ auto Interpreter::StepExp() -> ErrorOr { // reproducible across builds/platforms. int64_t r = (generator() % range) + low; CARBON_CHECK(r >= std::numeric_limits::min() && - r <= std::numeric_limits::max()) - << "Non-int32 result: " << r; - CARBON_CHECK(r >= low && r <= high) << "Out-of-range result: " << r; + r <= std::numeric_limits::max(), + "Non-int32 result: {0}", r); + CARBON_CHECK(r >= low && r <= high, "Out-of-range result: {0}", r); return todo_.FinishAction(arena_->New(r)); } case IntrinsicExpression::Intrinsic::ImplicitAs: { @@ -1747,8 +1748,8 @@ auto Interpreter::StepExp() -> ErrorOr { return todo_.FinishAction(result); } case IntrinsicExpression::Intrinsic::ImplicitAsConvert: { - CARBON_FATAL() - << "__intrinsic_implicit_as_convert should have been rewritten"; + CARBON_FATAL( + "__intrinsic_implicit_as_convert should have been rewritten"); } case IntrinsicExpression::Intrinsic::IntEq: { CARBON_CHECK(args.size() == 2); @@ -1891,7 +1892,7 @@ auto Interpreter::StepExp() -> ErrorOr { } case ExpressionKind::WhereExpression: { auto rewrite = cast(exp).rewritten_form(); - CARBON_CHECK(rewrite) << "where expression should be rewritten"; + CARBON_CHECK(rewrite, "where expression should be rewritten"); return todo_.ReplaceWith(std::make_unique( *rewrite, act.preserve_nested_categories(), act.location_received())); } @@ -1919,7 +1920,7 @@ auto Interpreter::StepExp() -> ErrorOr { } } case ExpressionKind::UnimplementedExpression: - CARBON_FATAL() << "Unimplemented: " << exp; + CARBON_FATAL("Unimplemented: {0}", exp); } // switch (exp->kind) } @@ -1982,7 +1983,7 @@ auto Interpreter::StepWitness() -> ErrorOr { } default: - CARBON_FATAL() << "unexpected kind of witness " << *witness; + CARBON_FATAL("unexpected kind of witness {0}", *witness); } } @@ -2183,11 +2184,12 @@ auto Interpreter::StepStmt() -> ErrorOr { const auto init_location = act.location_created(); v = v_expr ? (*v_expr)->value() : result; if (expr_category == ExpressionCategory::Reference) { - CARBON_CHECK(v_expr) << "Expecting ReferenceExpressionValue from " - "reference expression"; + CARBON_CHECK( + v_expr, + "Expecting ReferenceExpressionValue from reference expression"); v_location = (*v_expr)->address(); - CARBON_CHECK(v_location) - << "Expecting a valid address from reference expression"; + CARBON_CHECK(v_location, + "Expecting a valid address from reference expression"); } else if (has_initializing_expr && init_location && heap_.is_initialized(*init_location)) { // Bind even if a conversion is necessary. @@ -2228,9 +2230,10 @@ auto Interpreter::StepStmt() -> ErrorOr { PatternMatch(p, ExpressionResult(v, v_location, expr_category), stmt.source_loc(), &scope, generic_args, trace_stream_, this->arena_); - CARBON_CHECK(matched) - << stmt.source_loc() - << ": internal error in variable definition, match failed"; + CARBON_CHECK( + matched, + "{0}: internal error in variable definition, match failed", + stmt.source_loc()); } todo_.MergeScope(std::move(scope)); return todo_.FinishAction(); @@ -2435,9 +2438,8 @@ auto Interpreter::StepDestroy() -> ErrorOr { const Address var_addr = object.ElementAddress(arena_->New(var)); const auto v = heap_.Read(var_addr, var->source_loc()); - CARBON_CHECK(v.ok()) - << "Failed to read member `" << var->binding().name() - << "` from class `" << class_decl.name() << "`"; + CARBON_CHECK(v.ok(), "Failed to read member `{0}` from class `{1}`", + var->binding().name(), class_decl.name()); return todo_.Spawn(std::make_unique( arena_->New(var_addr), *v)); } else { @@ -2487,7 +2489,7 @@ auto Interpreter::StepDestroy() -> ErrorOr { todo_.Pop(); return Success(); } - CARBON_FATAL() << "Unreachable"; + CARBON_FATAL("Unreachable"); } auto Interpreter::StepCleanUp() -> ErrorOr { @@ -2577,9 +2579,9 @@ auto Interpreter::Step() -> ErrorOr { CARBON_RETURN_IF_ERROR(StepInstantiateType()); break; case Action::Kind::ScopeAction: - CARBON_FATAL() << "ScopeAction escaped ActionStack"; + CARBON_FATAL("ScopeAction escaped ActionStack"); case Action::Kind::RecursiveAction: - CARBON_FATAL() << "Tried to step a RecursiveAction"; + CARBON_FATAL("Tried to step a RecursiveAction"); } // switch return Success(); } diff --git a/explorer/interpreter/matching_impl_set.cpp b/explorer/interpreter/matching_impl_set.cpp index a3b2bf4dac2b..c27b29d27afd 100644 --- a/explorer/interpreter/matching_impl_set.cpp +++ b/explorer/interpreter/matching_impl_set.cpp @@ -118,7 +118,7 @@ MatchingImplSet::Match::Match(Nonnull parent, } MatchingImplSet::Match::~Match() { - CARBON_CHECK(parent_->matches_.back() == this) << "match stack broken"; + CARBON_CHECK(parent_->matches_.back() == this, "match stack broken"); parent_->matches_.pop_back(); } diff --git a/explorer/interpreter/pattern_match.cpp b/explorer/interpreter/pattern_match.cpp index 7fb6979034b2..ac6e68653060 100644 --- a/explorer/interpreter/pattern_match.cpp +++ b/explorer/interpreter/pattern_match.cpp @@ -30,8 +30,8 @@ static auto InitializePlaceholderValue(const ValueNodeView& value_node, } else { // Location initialized by initializing expression, bind node to // address. - CARBON_CHECK(v.address()) - << "Missing location from initializing expression"; + CARBON_CHECK(v.address(), + "Missing location from initializing expression"); bindings->Bind(value_node, *v.address()); } break; @@ -41,19 +41,18 @@ static auto InitializePlaceholderValue(const ValueNodeView& value_node, bindings->BindValue(value_node, v.value()); } else if (v.expression_category() == ExpressionCategory::Reference) { // Bind the reference expression value directly. - CARBON_CHECK(v.address()) - << "Missing location from reference expression"; + CARBON_CHECK(v.address(), "Missing location from reference expression"); bindings->BindAndPin(value_node, *v.address()); } else { // Location initialized by initializing expression, bind node to // address. - CARBON_CHECK(v.address()) - << "Missing location from initializing expression"; + CARBON_CHECK(v.address(), + "Missing location from initializing expression"); bindings->Bind(value_node, *v.address()); } break; case ExpressionCategory::Initializing: - CARBON_FATAL() << "Cannot pattern match an initializing expression"; + CARBON_FATAL("Cannot pattern match an initializing expression"); break; } } @@ -135,8 +134,8 @@ auto PatternMatch(Nonnull p, ExpressionResult v, return true; } default: - CARBON_FATAL() << "expected a tuple value in pattern, not " - << *v.value(); + CARBON_FATAL("expected a tuple value in pattern, not {0}", + *v.value()); } case Value::Kind::StructValue: { const auto& p_struct = cast(*p); @@ -172,12 +171,12 @@ auto PatternMatch(Nonnull p, ExpressionResult v, source_loc, bindings, generic_args, trace_stream, arena); } default: - CARBON_FATAL() << "expected a choice alternative in pattern, not " - << *v.value(); + CARBON_FATAL("expected a choice alternative in pattern, not {0}", + *v.value()); } case Value::Kind::UninitializedValue: - CARBON_FATAL() << "uninitialized value is not allowed in pattern " - << *v.value(); + CARBON_FATAL("uninitialized value is not allowed in pattern {0}", + *v.value()); case Value::Kind::FunctionType: switch (v.value()->kind()) { case Value::Kind::FunctionType: { diff --git a/explorer/interpreter/resolve_names.cpp b/explorer/interpreter/resolve_names.cpp index 9fbb2df592c7..0012c2ede61f 100644 --- a/explorer/interpreter/resolve_names.cpp +++ b/explorer/interpreter/resolve_names.cpp @@ -325,8 +325,8 @@ auto NameResolver::ResolveNamesImpl(Expression& expression, } if (const auto* namespace_decl = dyn_cast(base)) { auto ns_it = namespace_scopes_.find(namespace_decl); - CARBON_CHECK(ns_it != namespace_scopes_.end()) - << "name resolved to undeclared namespace"; + CARBON_CHECK(ns_it != namespace_scopes_.end(), + "name resolved to undeclared namespace"); CARBON_ASSIGN_OR_RETURN( const auto value_node, ns_it->second.ResolveHere(scope, access.member_name(), @@ -459,7 +459,7 @@ auto NameResolver::ResolveNamesImpl(Expression& expression, case ExpressionKind::ValueLiteral: case ExpressionKind::BuiltinConvertExpression: case ExpressionKind::BaseAccessExpression: - CARBON_FATAL() << "should not exist before type checking"; + CARBON_FATAL("should not exist before type checking"); case ExpressionKind::UnimplementedExpression: return ProgramError(expression.source_loc()) << "Unimplemented"; } @@ -603,9 +603,9 @@ auto NameResolver::ResolveNamesImpl(Statement& statement, } CARBON_RETURN_IF_ERROR(ResolveNames(def.pattern(), enclosing_scope)); if (def.is_returned()) { - CARBON_CHECK(def.pattern().kind() == PatternKind::BindingPattern) - << def.pattern().source_loc() - << "returned var definition can only be a binding pattern"; + CARBON_CHECK(def.pattern().kind() == PatternKind::BindingPattern, + "{0}returned var definition can only be a binding pattern", + def.pattern().source_loc()); CARBON_RETURN_IF_ERROR(enclosing_scope.AddReturnedVar( ValueNodeView(&cast(def.pattern())))); } @@ -924,7 +924,7 @@ auto NameResolver::ResolveNamesImpl(Declaration& declaration, } case DeclarationKind::SelfDeclaration: { - CARBON_FATAL() << "Unreachable: resolving names for `Self` declaration"; + CARBON_FATAL("Unreachable: resolving names for `Self` declaration"); } case DeclarationKind::AliasDeclaration: { diff --git a/explorer/interpreter/resolve_unformed.cpp b/explorer/interpreter/resolve_unformed.cpp index 9b091b5989d0..e5ee55f1ccce 100644 --- a/explorer/interpreter/resolve_unformed.cpp +++ b/explorer/interpreter/resolve_unformed.cpp @@ -140,8 +140,8 @@ static auto ResolveUnformedImpl(Nonnull trace_stream, case ExpressionKind::OperatorExpression: { const auto& opt_exp = cast(*expression); if (opt_exp.op() == Operator::AddressOf) { - CARBON_CHECK(opt_exp.arguments().size() == 1) - << "OperatorExpression with op & can only have 1 argument"; + CARBON_CHECK(opt_exp.arguments().size() == 1, + "OperatorExpression with op & can only have 1 argument"); CARBON_RETURN_IF_ERROR( // When a variable is taken address of, defer the unformed check to // runtime. A more sound analysis can be implemented when a diff --git a/explorer/interpreter/stack.h b/explorer/interpreter/stack.h index 79803a14bd63..3cc35810faad 100644 --- a/explorer/interpreter/stack.h +++ b/explorer/interpreter/stack.h @@ -32,7 +32,7 @@ struct Stack { // // - Requires: !this->IsEmpty() auto Pop() -> T { - CARBON_CHECK(!empty()) << "Can't pop from empty stack."; + CARBON_CHECK(!empty(), "Can't pop from empty stack."); auto r = std::move(elements_.back()); elements_.pop_back(); return r; @@ -42,9 +42,9 @@ struct Stack { // // - Requires: n >= 0 && n <= Count() void Pop(int n) { - CARBON_CHECK(n >= 0) << "Negative pop count disallowed."; - CARBON_CHECK(static_cast(n) <= elements_.size()) - << "Can only pop as many elements as stack has."; + CARBON_CHECK(n >= 0, "Negative pop count disallowed."); + CARBON_CHECK(static_cast(n) <= elements_.size(), + "Can only pop as many elements as stack has."); elements_.erase(elements_.end() - n, elements_.end()); } @@ -52,7 +52,7 @@ struct Stack { // // - Requires: !this->IsEmpty() auto Top() const -> const T& { - CARBON_CHECK(!empty()) << "Empty stack has no Top()."; + CARBON_CHECK(!empty(), "Empty stack has no Top()."); return elements_.back(); } diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index da09149cd843..fa2ab103d404 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -109,7 +109,7 @@ static auto ExpectCompleteType(SourceLocation source_loc, case Value::Kind::ParameterizedEntityName: case Value::Kind::MemberName: case Value::Kind::MixinPseudoType: - CARBON_FATAL() << "should not see non-type values"; + CARBON_FATAL("should not see non-type values"); case Value::Kind::IntType: case Value::Kind::BoolType: @@ -195,7 +195,7 @@ static auto ExpectConcreteType(SourceLocation source_loc, // Returns whether `type` is a placeholder type, which is a second-class type // that cannot be the type of a binding but can be the type of an expression. static auto IsPlaceholderType(Nonnull type) -> bool { - CARBON_CHECK(IsType(type)) << "expected a type, but found " << *type; + CARBON_CHECK(IsType(type), "expected a type, but found {0}", *type); return isa(type); } @@ -568,14 +568,14 @@ auto TypeChecker::BuildSubtypeConversion(Nonnull source, while (!TypeEqual(cur_class, dest_class, std::nullopt)) { const auto src = src_class->declaration().name(); const auto base_class = cur_class->base(); - CARBON_CHECK(base_class) << "Invalid subtyping conversion"; + CARBON_CHECK(base_class, "Invalid subtyping conversion"); auto* base_expr = arena_->New( source->source_loc(), last_expr, arena_->New(arena_->New(*base_class))); last_expr = base_expr; cur_class = *base_class; } - CARBON_CHECK(last_expr) << "Error, no conversion was needed"; + CARBON_CHECK(last_expr, "Error, no conversion was needed"); return last_expr; } @@ -758,7 +758,7 @@ auto TypeChecker::BuildBuiltinConversion(Nonnull source, return conversion_failed(); } - CARBON_FATAL() << "unreachable"; + CARBON_FATAL("unreachable"); } auto TypeChecker::ImplicitlyConvert(std::string_view context, @@ -892,8 +892,8 @@ auto TypeChecker::IsIntrinsicConstraintSatisfied( // TODO: Check to see if this constraint is known in the current impl scope. switch (constraint.kind) { case IntrinsicConstraint::ImplicitAs: - CARBON_CHECK(constraint.arguments.size() == 1) - << "wrong number of arguments for `__intrinsic_implicit_as`"; + CARBON_CHECK(constraint.arguments.size() == 1, + "wrong number of arguments for `__intrinsic_implicit_as`"); CARBON_ASSIGN_OR_RETURN( bool convertible, IsBuiltinConversion(source_loc, constraint.type, @@ -1007,7 +1007,7 @@ auto TypeChecker::ExpectNonPlaceholderType(SourceLocation source_loc, return ProgramError(source_loc) << "expected `.member_name` after name of " << *namespace_type; } - CARBON_FATAL() << "unknown kind of placeholder type " << *type; + CARBON_FATAL("unknown kind of placeholder type {0}", *type); } // Argument deduction matches two values and attempts to find a set of @@ -1204,8 +1204,9 @@ auto TypeChecker::ArgumentDeduction::Deduce(Nonnull param, return diagnose_missing_field(param_struct, arg_field, false); } } - CARBON_FATAL() << "field count mismatch but no missing field; " - << "duplicate field name?"; + CARBON_FATAL( + "field count mismatch but no missing field; duplicate field " + "name?"); } } else { for (const auto [param_field, arg_field] : @@ -1350,7 +1351,7 @@ auto TypeChecker::ArgumentDeduction::Deduce(Nonnull param, } case Value::Kind::MixinPseudoType: case Value::Kind::TypeOfMixinPseudoType: - CARBON_CHECK(false) << "Type expression must not contain Mixin types"; + CARBON_CHECK(false, "Type expression must not contain Mixin types"); } } @@ -2515,13 +2516,13 @@ auto TypeChecker::DeduceCallBindings( /*allow_implicit_conversion=*/true)); } } - CARBON_CHECK(generic_params.empty()) - << "did not find all generic parameters in parameter list"; + CARBON_CHECK(generic_params.empty(), + "did not find all generic parameters in parameter list"); CARBON_ASSIGN_OR_RETURN( std::optional bindings, deduction.Finish(*this, impl_scope, /*diagnose_deduction_failure=*/true)); - CARBON_CHECK(bindings) << "should have diagnosed deduction failure"; + CARBON_CHECK(bindings, "should have diagnosed deduction failure"); call.set_bindings(std::move(*bindings)); // Convert the arguments to the deduced and substituted parameter type. @@ -2791,8 +2792,9 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull e, case ExpressionKind::ValueLiteral: case ExpressionKind::BuiltinConvertExpression: case ExpressionKind::BaseAccessExpression: - CARBON_FATAL() << "attempting to type check node " << *e - << " generated during type checking"; + CARBON_FATAL( + "attempting to type check node {0} generated during type checking", + *e); case ExpressionKind::IndexExpression: { auto& index = cast(*e); CARBON_RETURN_IF_ERROR(TypeCheckExp(&index.object(), impl_scope)); @@ -2943,8 +2945,8 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull e, return ProgramError(access.source_loc()) << "Member access to aliases is not yet supported."; default: - CARBON_FATAL() << "member " << access.member_name() - << " is not a field or method"; + CARBON_FATAL("member {0} is not a field or method", + access.member_name()); break; } return Success(); @@ -3344,8 +3346,8 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull e, // This should not be possible: the name of a static member // function should have function type not member name type. CARBON_CHECK(!has_instance || is_instance_member || - !member_name.base_type().has_value()) - << "vacuous compound member access"; + !member_name.base_type().has_value(), + "vacuous compound member access"); // If this is instance access, remove self bound from function type if (has_instance && is_instance_member) { CARBON_RETURN_IF_ERROR(set_static_type_remove_self()); @@ -3365,8 +3367,7 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull e, access.set_expression_category(access.object().expression_category()); return Success(); default: - CARBON_FATAL() << "member " << member_name - << " is not a field or method"; + CARBON_FATAL("member {0} is not a field or method", member_name); break; } @@ -3674,10 +3675,11 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull e, // Currently the only kinds of parameterized entities we support are // types. - CARBON_CHECK( - isa(param_name.declaration())) - << "unknown type of ParameterizedEntityName for " << param_name; + CARBON_CHECK((isa( + param_name.declaration())), + "unknown type of ParameterizedEntityName for {0}", + param_name); call.set_static_type(arena_->New()); call.set_expression_category(ExpressionCategory::Value); return Success(); @@ -4109,7 +4111,7 @@ auto TypeChecker::TypeCheckExpImpl(Nonnull e, return Success(); } case ExpressionKind::UnimplementedExpression: - CARBON_FATAL() << "Unimplemented: " << *e; + CARBON_FATAL("Unimplemented: {0}", *e); case ExpressionKind::ArrayTypeLiteral: { auto& array_literal = cast(*e); CARBON_ASSIGN_OR_RETURN( @@ -4200,18 +4202,18 @@ auto TypeChecker::TypeCheckTypeExp(Nonnull type_expression, arena_->New())); CARBON_ASSIGN_OR_RETURN(Nonnull type, InterpExp(type_expression)); - CARBON_CHECK(IsType(type)) - << "type expression did not produce a type, got " << *type; + CARBON_CHECK(IsType(type), "type expression did not produce a type, got {0}", + *type); if (concrete) { if (TypeIsDeduceable(type)) { return ProgramError(type_expression->source_loc()) << "`auto` is not permitted in this context"; } - CARBON_CHECK(IsNonDeduceableType(type)) - << "unknown kind of non-concrete type " << *type; + CARBON_CHECK(IsNonDeduceableType(type), + "unknown kind of non-concrete type {0}", *type); } - CARBON_CHECK(!IsPlaceholderType(type)) - << "should be no way to write a placeholder type"; + CARBON_CHECK(!IsPlaceholderType(type), + "should be no way to write a placeholder type"); return type; } @@ -4325,9 +4327,10 @@ auto TypeChecker::TypeCheckPattern( arena_->New())); CARBON_ASSIGN_OR_RETURN(type, InterpExp(converted)); } - CARBON_CHECK(IsType(type)) - << "conversion to type succeeded but didn't produce a type, got " - << *type; + CARBON_CHECK( + IsType(type), + "conversion to type succeeded but didn't produce a type, got {0}", + *type); if (expected) { // TODO: Per proposal #2188, we should be performing conversions at // this level rather than on the overall initializer. @@ -4348,11 +4351,11 @@ auto TypeChecker::TypeCheckPattern( CARBON_RETURN_IF_ERROR(ExpectResolvedBindingType(binding, type)); } - CARBON_CHECK(IsNonDeduceableType(type)) - << "did not resolve " << binding << " to concrete type, got " - << *type; - CARBON_CHECK(!IsPlaceholderType(type)) - << "should be no way to write a placeholder type"; + CARBON_CHECK(IsNonDeduceableType(type), + "did not resolve {0} to concrete type, got {1}", binding, + *type); + CARBON_CHECK(!IsPlaceholderType(type), + "should be no way to write a placeholder type"); binding.set_static_type(type); binding.set_value(binding.name() != AnonymousName ? arena_->New(&binding) @@ -4897,7 +4900,7 @@ auto TypeChecker::DeclareCallableDeclaration(Nonnull f, const ScopeInfo& scope_info) -> ErrorOr { const auto name = GetName(*f); - CARBON_CHECK(name) << "Unexpected missing name for `" << *f << "`."; + CARBON_CHECK(name, "Unexpected missing name for `{0}`.", *f); if (trace_stream_->is_enabled()) { trace_stream_->Start() << "declaring function `" << *name << "` (" << f->source_loc() << ")\n"; @@ -4997,7 +5000,7 @@ auto TypeChecker::DeclareCallableDeclaration(Nonnull f, arena_->New(cast(f))); break; default: - CARBON_FATAL() << "f is not a callable declaration"; + CARBON_FATAL("f is not a callable declaration"); } if (name == "Main") { @@ -5027,7 +5030,7 @@ auto TypeChecker::TypeCheckCallableDeclaration(Nonnull f, const ImplScope& impl_scope) -> ErrorOr { auto name = GetName(*f); - CARBON_CHECK(name) << "Unexpected missing name for `" << *f << "`."; + CARBON_CHECK(name, "Unexpected missing name for `{0}`.", *f); if (trace_stream_->is_enabled()) { trace_stream_->Start() << "checking function `" << *name << "` (" << f->source_loc() << ")\n"; @@ -5165,8 +5168,8 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull class_decl, << "Error declaring `" << fun->name() << "`" << ": class functions cannot be virtual."; } - CARBON_CHECK(!fun->name().is_qualified()) - << "qualified function name not permitted in class scope"; + CARBON_CHECK(!fun->name().is_qualified(), + "qualified function name not permitted in class scope"); if (fun->virt_override() == VirtualOverride::Abstract && fun->body().has_value()) { @@ -5312,8 +5315,8 @@ auto TypeChecker::TypeCheckClassDeclaration( } auto [it, inserted] = collected_members_.insert({class_decl, CollectedMembersMap()}); - CARBON_CHECK(inserted) << "Adding class " << class_decl->name() - << " to collected_members_ must not fail"; + CARBON_CHECK(inserted, "Adding class {0} to collected_members_ must not fail", + class_decl->name()); for (Nonnull m : class_decl->members()) { CARBON_RETURN_IF_ERROR(TypeCheckDeclaration(m, class_scope, class_decl)); CARBON_RETURN_IF_ERROR(CollectMember(class_decl, m)); @@ -5459,8 +5462,8 @@ auto TypeChecker::DeclareConstraintTypeDeclaration( Nonnull constraint_decl, const ScopeInfo& scope_info) -> ErrorOr { CARBON_CHECK( - isa(constraint_decl)) - << "unexpected kind of constraint type declaration"; + (isa(constraint_decl)), + "unexpected kind of constraint type declaration"); bool is_interface = isa(constraint_decl); if (trace_stream_->is_enabled()) { @@ -5635,9 +5638,8 @@ auto TypeChecker::DeclareConstraintTypeDeclaration( } default: { - CARBON_FATAL() - << "unexpected declaration in constraint type declaration:\n" - << *m; + CARBON_FATAL( + "unexpected declaration in constraint type declaration:\n{0}", *m); break; } } @@ -5728,7 +5730,7 @@ auto TypeChecker::CheckImplIsComplete(Nonnull iface_type, } else { // Every member function must be declared. std::optional mem_name = GetName(*m); - CARBON_CHECK(mem_name.has_value()) << "unnamed interface member " << *m; + CARBON_CHECK(mem_name.has_value(), "unnamed interface member {0}", *m); std::optional> mem = FindMember(*mem_name, impl_decl->members()); @@ -6129,11 +6131,11 @@ static auto IsValidTypeForAliasTarget(Nonnull type) -> bool { case Value::Kind::AlternativeConstructorValue: case Value::Kind::StringValue: case Value::Kind::UninitializedValue: - CARBON_FATAL() << "type of alias target is not a type: " << *type; + CARBON_FATAL("type of alias target is not a type: {0}", *type); case Value::Kind::AutoType: case Value::Kind::VariableType: - CARBON_FATAL() << "pattern type in alias target: " << *type; + CARBON_FATAL("pattern type in alias target: {0}", *type); case Value::Kind::IntType: case Value::Kind::BoolType: @@ -6291,7 +6293,7 @@ auto TypeChecker::TypeCheckDeclaration( break; } case DeclarationKind::SelfDeclaration: { - CARBON_FATAL() << "Unreachable TypeChecker `Self` declaration"; + CARBON_FATAL("Unreachable TypeChecker `Self` declaration"); } case DeclarationKind::AliasDeclaration: { break; @@ -6418,7 +6420,7 @@ auto TypeChecker::DeclareDeclaration(Nonnull d, } case DeclarationKind::SelfDeclaration: { - CARBON_FATAL() << "Unreachable TypeChecker declare `Self` declaration"; + CARBON_FATAL("Unreachable TypeChecker declare `Self` declaration"); } case DeclarationKind::AliasDeclaration: { @@ -6490,8 +6492,8 @@ auto TypeChecker::CollectMember(Nonnull enclosing_decl, Nonnull member_decl) -> ErrorOr { CARBON_CHECK(isa(enclosing_decl) || - isa(enclosing_decl)) - << "Can't collect members for " << *enclosing_decl; + isa(enclosing_decl), + "Can't collect members for {0}", *enclosing_decl); auto member_name = GetName(*member_decl); if (!member_name.has_value()) { // No need to collect members without a name @@ -6532,7 +6534,7 @@ auto TypeChecker::FindCollectedMembers(Nonnull decl) return it->second; } default: - CARBON_FATAL() << "Can't collect members for " << *decl; + CARBON_FATAL("Can't collect members for {0}", *decl); } } @@ -6585,8 +6587,8 @@ auto TypeChecker::InstantiateImplDeclaration( std::optional> witness; if (auto impl = param->impl_binding()) { auto it = bindings->witnesses().find(*impl); - CARBON_CHECK(it != bindings->witnesses().end()) - << "no witness for generic binding"; + CARBON_CHECK(it != bindings->witnesses().end(), + "no witness for generic binding"); witness = it->second; } new_bindings.Add(clone, value, witness); @@ -6604,8 +6606,8 @@ auto TypeChecker::InstantiateImplDeclaration( // TODO: It's probably not correct to use the top-level impl scope here. It's // not obvious what we should use, though -- which impls are in scope in // template instantiation? - CARBON_CHECK(top_level_impl_scope_) - << "can't perform template instantiation with no top-level scope"; + CARBON_CHECK(top_level_impl_scope_, + "can't perform template instantiation with no top-level scope"); ImplScope scope(*top_level_impl_scope_); // Bring all impls from any checked generic bindings in the template diff --git a/explorer/interpreter/type_utils.cpp b/explorer/interpreter/type_utils.cpp index 2b7d731adc5c..456c57dde94f 100644 --- a/explorer/interpreter/type_utils.cpp +++ b/explorer/interpreter/type_utils.cpp @@ -81,7 +81,7 @@ auto IsType(Nonnull value) -> bool { } auto TypeIsDeduceable(Nonnull type) -> bool { - CARBON_CHECK(IsType(type)) << "expected a type, but found " << *type; + CARBON_CHECK(IsType(type), "expected a type, but found {0}", *type); switch (type->kind()) { case Value::Kind::IntValue: @@ -108,7 +108,7 @@ auto TypeIsDeduceable(Nonnull type) -> bool { case Value::Kind::ParameterizedEntityName: case Value::Kind::MemberName: case Value::Kind::MixinPseudoType: - CARBON_FATAL() << "non-type value"; + CARBON_FATAL("non-type value"); case Value::Kind::IntType: case Value::Kind::BoolType: case Value::Kind::TypeType: diff --git a/explorer/syntax/parse.cpp b/explorer/syntax/parse.cpp index 91882c63ec0a..0a20599a7358 100644 --- a/explorer/syntax/parse.cpp +++ b/explorer/syntax/parse.cpp @@ -36,8 +36,8 @@ static auto ParseImpl(yyscan_t scanner, Nonnull arena, } // Return parse results. - CARBON_CHECK(ast != std::nullopt) - << "parser validated syntax yet didn't produce an AST."; + CARBON_CHECK(ast != std::nullopt, + "parser validated syntax yet didn't produce an AST."); return *ast; } diff --git a/explorer/syntax/prelude.cpp b/explorer/syntax/prelude.cpp index 1ab9cd08194b..d815c0dbf3c6 100644 --- a/explorer/syntax/prelude.cpp +++ b/explorer/syntax/prelude.cpp @@ -19,8 +19,7 @@ void AddPrelude(llvm::vfs::FileSystem& fs, std::string_view prelude_file_name, // Try again with tracing, to help diagnose the problem. ErrorOr trace_parse_result = Parse(fs, arena, prelude_file_name, FileKind::Prelude, true); - CARBON_FATAL() << "Failed to parse prelude:\n" - << trace_parse_result.error(); + CARBON_FATAL("Failed to parse prelude:\n{0}", trace_parse_result.error()); } const auto& prelude = *parse_result; declarations->insert(declarations->begin(), prelude.declarations.begin(), diff --git a/migrate_cpp/rewriter_test.cpp b/migrate_cpp/rewriter_test.cpp index e4dcbb8e76f2..f60569f4cc10 100644 --- a/migrate_cpp/rewriter_test.cpp +++ b/migrate_cpp/rewriter_test.cpp @@ -27,8 +27,8 @@ class Annotations { } start_ = index; end_ = annotated_source.find("]]$", index); - CARBON_CHECK(end_ != llvm::StringRef::npos) - << "Found `$[[` but no matching `]]$`"; + CARBON_CHECK(end_ != llvm::StringRef::npos, + "Found `$[[` but no matching `]]$`"); source_code_ = (llvm::Twine(annotated_source.substr(0, start_)) + annotated_source.substr(start_ + 3, end_ - start_ - 3) + annotated_source.substr(end_ + 3)) diff --git a/testing/base/global_exe_path.cpp b/testing/base/global_exe_path.cpp index ebeb0d99c5c2..1a0349e7156f 100644 --- a/testing/base/global_exe_path.cpp +++ b/testing/base/global_exe_path.cpp @@ -14,13 +14,14 @@ static constinit std::optional exe_path = {}; namespace Carbon::Testing { auto GetExePath() -> llvm::StringRef { - CARBON_CHECK(exe_path) - << "Must not query the executable path until after it has been set!"; + CARBON_CHECK( + exe_path, + "Must not query the executable path until after it has been set!"); return *exe_path; } auto SetExePath(const char* argv_zero) -> void { - CARBON_CHECK(!exe_path) << "Must not call `SetExePath` more than once!"; + CARBON_CHECK(!exe_path, "Must not call `SetExePath` more than once!"); exe_path.emplace(Carbon::FindExecutablePath(argv_zero)); } diff --git a/testing/base/source_gen.cpp b/testing/base/source_gen.cpp index 5fcba45afb08..673225320d81 100644 --- a/testing/base/source_gen.cpp +++ b/testing/base/source_gen.cpp @@ -152,10 +152,11 @@ auto SourceGen::ClassGenState::GetValidTypeName() -> llvm::StringRef { return type_names_.pop_back_val(); } - CARBON_CHECK(last_type_name_index_ != initial_last_type_name_index) - << "Failed to find a valid type name with " << type_names_.size() - << " candidates, an initial index of " << initial_last_type_name_index - << ", and with " << class_names_.size() << " classes left to emit!"; + CARBON_CHECK(last_type_name_index_ != initial_last_type_name_index, + "Failed to find a valid type name with {0} candidates, an " + "initial index of {1}, and with {2} classes left to emit!", + type_names_.size(), initial_last_type_name_index, + class_names_.size()); } } @@ -319,8 +320,8 @@ auto SourceGen::GenAPIFileDenseDecls(int target_lines, // needs a blank line. constexpr int NumFileCommentLines = 4; double avg_class_lines = EstimateAvgClassDefLines(params.class_params); - CARBON_CHECK(target_lines > NumFileCommentLines + avg_class_lines) - << "Not enough target lines to generate a single class!"; + CARBON_CHECK(target_lines > NumFileCommentLines + avg_class_lines, + "Not enough target lines to generate a single class!"); int num_classes = static_cast(target_lines - NumFileCommentLines) / (avg_class_lines + 1); int expected_lines = @@ -372,9 +373,9 @@ auto SourceGen::GetShuffledIdentifiers(int number, int min_length, auto SourceGen::GetShuffledUniqueIdentifiers(int number, int min_length, int max_length, bool uniform) -> llvm::SmallVector { - CARBON_CHECK(min_length >= 4) - << "Cannot trivially guarantee enough distinct, unique identifiers for " - "lengths <= 3"; + CARBON_CHECK(min_length >= 4, + "Cannot trivially guarantee enough distinct, unique identifiers " + "for lengths <= 3"); llvm::SmallVector idents = GetUniqueIdentifiers(number, min_length, max_length, uniform); std::shuffle(idents.begin(), idents.end(), rng_); @@ -398,9 +399,9 @@ auto SourceGen::GetIdentifiers(int number, int min_length, int max_length, auto SourceGen::GetUniqueIdentifiers(int number, int min_length, int max_length, bool uniform) -> llvm::SmallVector { - CARBON_CHECK(min_length >= 4) - << "Cannot trivially guarantee enough distinct, unique identifiers for " - "lengths <= 3"; + CARBON_CHECK(min_length >= 4, + "Cannot trivially guarantee enough distinct, unique identifiers " + "for lengths <= 3"); llvm::SmallVector idents = GetIdentifiersImpl(number, min_length, max_length, uniform, [this](int length, int length_count, @@ -634,10 +635,10 @@ auto SourceGen::GetIdentifiersImpl(int number, int min_length, int max_length, llvm::function_ref append) -> llvm::SmallVector { CARBON_CHECK(min_length <= max_length); - CARBON_CHECK(uniform || max_length <= 64) - << "Cannot produce a meaningful non-uniform distribution of lengths " - "longer than 64 as those are exceedingly rare in our observed data " - "sets."; + CARBON_CHECK( + uniform || max_length <= 64, + "Cannot produce a meaningful non-uniform distribution of lengths longer " + "than 64 as those are exceedingly rare in our observed data sets."); llvm::SmallVector idents; idents.reserve(number); @@ -667,11 +668,10 @@ auto SourceGen::GetIdentifiersImpl(int number, int min_length, int max_length, } append(length, length_count, idents); } - CARBON_CHECK(number_rem == 0) - << "Unexpected number remaining: " << number_rem; - CARBON_CHECK(static_cast(idents.size()) == number) - << "Ended up with " << idents.size() - << " identifiers instead of the requested " << number; + CARBON_CHECK(number_rem == 0, "Unexpected number remaining: {0}", number_rem); + CARBON_CHECK(static_cast(idents.size()) == number, + "Ended up with {0} identifiers instead of the requested {1}", + idents.size(), number); return idents; } diff --git a/testing/file_test/autoupdate.cpp b/testing/file_test/autoupdate.cpp index e5eff253ce21..34b7c50e46a5 100644 --- a/testing/file_test/autoupdate.cpp +++ b/testing/file_test/autoupdate.cpp @@ -21,8 +21,8 @@ static auto ParseLineNumber(absl::string_view matched_line_number) -> int { trimmed = trimmed.trim(); // NOLINTNEXTLINE(google-runtime-int): API requirement. long long val; - CARBON_CHECK(!llvm::getAsSignedInteger(trimmed, 10, val)) - << matched_line_number; + CARBON_CHECK(!llvm::getAsSignedInteger(trimmed, 10, val), "{0}", + matched_line_number); return val; } @@ -60,7 +60,7 @@ auto FileTestAutoupdater::CheckLine::RemapLineNumbers( RE2::PartialMatch(line_cursor, *replacement_->re, &matched_line_number); } if (matched_line_number.empty()) { - CARBON_CHECK(found_one) << line_; + CARBON_CHECK(found_one, "{0}", line_); return; } found_one = true; @@ -195,9 +195,9 @@ auto FileTestAutoupdater::BuildCheckLines(llvm::StringRef output, absl::string_view filename; if (RE2::PartialMatch(line, *default_file_re_, &filename)) { auto it = file_to_number_map.find(filename); - CARBON_CHECK(it != file_to_number_map.end()) - << "default_file_re had unexpected match in '" << line << "' (`" - << default_file_re_->pattern() << "`)"; + CARBON_CHECK(it != file_to_number_map.end(), + "default_file_re had unexpected match in '{0}' (`{1}`)", + line, default_file_re_->pattern()); default_file_number = it->second; } } @@ -218,7 +218,7 @@ auto FileTestAutoupdater::AddRemappedNonCheckLine() -> void { } auto FileTestAutoupdater::AddTips() -> void { - CARBON_CHECK(tips_.empty()) << "Should only add tips once"; + CARBON_CHECK(tips_.empty(), "Should only add tips once"); tips_.reserve(4); // This puts commands on a single line so that they can be easily copied. @@ -278,12 +278,12 @@ auto FileTestAutoupdater::StartSplitFile() -> void { // Advance the file. ++output_file_number_; output_line_number_ = 0; - CARBON_CHECK(output_file_number_ == non_check_line_->file_number()) - << "Non-sequential file: " << non_check_line_->file_number(); + CARBON_CHECK(output_file_number_ == non_check_line_->file_number(), + "Non-sequential file: {0}", non_check_line_->file_number()); // Each following file has precisely one split line. - CARBON_CHECK(non_check_line_->line_number() < 1) - << "Expected a split line, got " << *non_check_line_; + CARBON_CHECK(non_check_line_->line_number() < 1, + "Expected a split line, got {0}", *non_check_line_); // The split line is ignored when calculating line counts. new_lines_.push_back(non_check_line_); @@ -300,8 +300,8 @@ auto FileTestAutoupdater::Run(bool dry_run) -> bool { // Print everything until the autoupdate line. while (non_check_line_->line_number() != autoupdate_line_number_) { CARBON_CHECK(non_check_line_ != non_check_lines_.end() && - non_check_line_->file_number() == 0) - << "Missed autoupdate?"; + non_check_line_->file_number() == 0, + "Missed autoupdate?"); AddRemappedNonCheckLine(); ++non_check_line_; } diff --git a/testing/file_test/autoupdate.h b/testing/file_test/autoupdate.h index 4c5d00f1746a..15ad07c769f4 100644 --- a/testing/file_test/autoupdate.h +++ b/testing/file_test/autoupdate.h @@ -62,11 +62,12 @@ class FileTestAutoupdater { [&](const CheckLine& line) { return line.line_number() != -1; })), non_check_line_(non_check_lines_.begin()) { for (const auto& replacement : line_number_replacements_) { - CARBON_CHECK(replacement.has_file || default_file_re_) - << "For replacement with pattern `" << replacement.re->pattern() - << "` to have has_file=false, override GetDefaultFileRE."; - CARBON_CHECK(replacement.re->ok()) - << "Invalid line replacement RE2: " << replacement.re->error(); + CARBON_CHECK(replacement.has_file || default_file_re_, + "For replacement with pattern `{0}` to have has_file=false, " + "override GetDefaultFileRE.", + replacement.re->pattern()); + CARBON_CHECK(replacement.re->ok(), "Invalid line replacement RE2: {0}", + replacement.re->error()); } } diff --git a/testing/file_test/file_test_base.cpp b/testing/file_test/file_test_base.cpp index d6777b483e7b..a12588eb525d 100644 --- a/testing/file_test/file_test_base.cpp +++ b/testing/file_test/file_test_base.cpp @@ -900,10 +900,10 @@ static auto GetTests() -> llvm::SmallVector { } // Extracts tests from the target file. - CARBON_CHECK(!absl::GetFlag(FLAGS_test_targets_file).empty()) - << "Missing --test_targets_file."; + CARBON_CHECK(!absl::GetFlag(FLAGS_test_targets_file).empty(), + "Missing --test_targets_file."); auto content = ReadFile(absl::GetFlag(FLAGS_test_targets_file)); - CARBON_CHECK(content.ok()) << content.error(); + CARBON_CHECK(content.ok(), "{0}", content.error()); llvm::SmallVector all_tests; for (llvm::StringRef file_ref : llvm::split(*content, "\n")) { if (file_ref.empty()) { diff --git a/toolchain/base/value_store.h b/toolchain/base/value_store.h index 5c0a5c1e209e..31c7008a26e5 100644 --- a/toolchain/base/value_store.h +++ b/toolchain/base/value_store.h @@ -151,7 +151,7 @@ class ValueStore // Stores the value and returns an ID to reference it. auto Add(ValueType value) -> IdT { IdT id(values_.size()); - CARBON_CHECK(id.index >= 0) << "Id overflow"; + CARBON_CHECK(id.index >= 0, "Id overflow"); values_.push_back(std::move(value)); return id; } @@ -165,13 +165,13 @@ class ValueStore // Returns a mutable value for an ID. auto Get(IdT id) -> RefType { - CARBON_DCHECK(id.index >= 0) << id; + CARBON_DCHECK(id.index >= 0, "{0}", id); return values_[id.index]; } // Returns the value for an ID. auto Get(IdT id) const -> ConstRefType { - CARBON_DCHECK(id.index >= 0) << id; + CARBON_DCHECK(id.index >= 0, "{0}", id); return values_[id.index]; } diff --git a/toolchain/base/yaml.h b/toolchain/base/yaml.h index 86496836a4d9..0e4997970366 100644 --- a/toolchain/base/yaml.h +++ b/toolchain/base/yaml.h @@ -94,7 +94,7 @@ struct llvm::yaml::ScalarTraits { } static auto input(StringRef /*scalar*/, void* /*ctxt*/, Carbon::Yaml::OutputScalar& /*value*/) -> StringRef { - CARBON_FATAL() << "Input is unsupported."; + CARBON_FATAL("Input is unsupported."); } static auto mustQuote(StringRef /*value*/) -> QuotingType { return QuotingType::None; diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index 0aede2417540..2d25b0a263a3 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -555,8 +555,8 @@ class DeferredDefinitionWorklist { // CHECK that the work list has no further work. auto VerifyEmpty() { - CARBON_CHECK(worklist_.empty() && entered_scopes_.empty()) - << "Tasks left behind on worklist."; + CARBON_CHECK(worklist_.empty() && entered_scopes_.empty(), + "Tasks left behind on worklist."); } private: @@ -627,8 +627,8 @@ auto DeferredDefinitionWorklist::SuspendFinishedScopeAndPush(Context& context) // worklist. We stay in that scope rather than suspending then immediately // resuming it. CARBON_CHECK( - holds_alternative(worklist_.back())) - << "Unexpected task in worklist."; + holds_alternative(worklist_.back()), + "Unexpected task in worklist."); worklist_.pop_back(); CARBON_VLOG("{0}Handle EnterDeferredDefinitionScope (non-nested)\n", VlogPrefix); @@ -690,8 +690,8 @@ class NodeIdTraversal { auto PerformTask( DeferredDefinitionWorklist::EnterDeferredDefinitionScope&& enter) -> void { - CARBON_CHECK(enter.suspended_name) - << "Entering a scope with no suspension information."; + CARBON_CHECK(enter.suspended_name, + "Entering a scope with no suspension information."); context_.decl_name_stack().Restore(std::move(*enter.suspended_name)); } @@ -815,12 +815,10 @@ static auto DiagnoseMissingDefinitions(Context& context, case SemIR::InterfaceDecl::Kind: { // TODO: handle `interface` as well, once we can test it without // triggering https://github.com/carbon-language/carbon-lang/issues/4071 - CARBON_FATAL() - << "TODO: Support interfaces in DiagnoseMissingDefinitions"; + CARBON_FATAL("TODO: Support interfaces in DiagnoseMissingDefinitions"); } default: { - CARBON_FATAL() << "Unexpected inst in definitions_required: " - << decl_inst; + CARBON_FATAL("Unexpected inst in definitions_required: {0}", decl_inst); } } } @@ -851,14 +849,15 @@ static auto ProcessNodeIds(Context& context, llvm::raw_ostream* vlog_stream, auto parse_kind = context.parse_tree().node_kind(node_id); switch (parse_kind) { -#define CARBON_PARSE_NODE_KIND(Name) \ - case Parse::NodeKind::Name: { \ - if (!HandleParseNode(context, Parse::Name##Id(node_id))) { \ - CARBON_CHECK(err_tracker.seen_error()) \ - << "Handle" #Name " returned false without printing a diagnostic"; \ - return false; \ - } \ - break; \ +#define CARBON_PARSE_NODE_KIND(Name) \ + case Parse::NodeKind::Name: { \ + if (!HandleParseNode(context, Parse::Name##Id(node_id))) { \ + CARBON_CHECK(err_tracker.seen_error(), \ + "Handle" #Name \ + " returned false without printing a diagnostic"); \ + return false; \ + } \ + break; \ } #include "toolchain/parse/node_kind.def" } @@ -919,8 +918,8 @@ static auto CheckParseTree( #ifndef NDEBUG if (auto verify = sem_ir.Verify(); !verify.ok()) { - CARBON_FATAL() << sem_ir << "Built invalid semantics IR: " << verify.error() - << "\n"; + CARBON_FATAL("{0}Built invalid semantics IR: {1}\n", sem_ir, + verify.error()); } #endif } diff --git a/toolchain/check/check_fuzzer.cpp b/toolchain/check/check_fuzzer.cpp index fd435f80bc66..0921c901c344 100644 --- a/toolchain/check/check_fuzzer.cpp +++ b/toolchain/check/check_fuzzer.cpp @@ -15,7 +15,7 @@ static const InstallPaths* install_paths = nullptr; // NOLINTNEXTLINE(readability-non-const-parameter): External API required types. extern "C" auto LLVMFuzzerInitialize(int* argc, char*** argv) -> int { - CARBON_CHECK(*argc >= 1) << "Need the `argv[0]` value to initialize!"; + CARBON_CHECK(*argc >= 1, "Need the `argv[0]` value to initialize!"); install_paths = new InstallPaths( InstallPaths::MakeForBazelRunfiles(FindExecutablePath((*argv)[0]))); return 0; diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index f706aa19ef95..0d8e8e191c45 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -142,9 +142,10 @@ auto Context::CheckCompatibleImportedNodeKind( auto& import_ir_inst = import_ir_insts().Get(imported_loc_id); const auto* import_ir = import_irs().Get(import_ir_inst.ir_id).sem_ir; auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id).kind(); - CARBON_CHECK(HasCompatibleImportedNodeKind(imported_kind, kind)) - << "Node of kind " << kind - << " created with location of imported node of kind " << imported_kind; + CARBON_CHECK( + HasCompatibleImportedNodeKind(imported_kind, kind), + "Node of kind {0} created with location of imported node of kind {1}", + kind, imported_kind); } auto Context::AddInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst) @@ -218,7 +219,7 @@ auto Context::DiagnoseNameNotFound(SemIRLoc loc, SemIR::NameId name_id) auto Context::NoteIncompleteClass(SemIR::ClassId class_id, DiagnosticBuilder& builder) -> void { const auto& class_info = classes().Get(class_id); - CARBON_CHECK(!class_info.is_defined()) << "Class is not incomplete"; + CARBON_CHECK(!class_info.is_defined(), "Class is not incomplete"); if (class_info.definition_id.is_valid()) { CARBON_DIAGNOSTIC(ClassIncompleteWithinDefinition, Note, "Class is incomplete within its definition."); @@ -233,7 +234,7 @@ auto Context::NoteIncompleteClass(SemIR::ClassId class_id, auto Context::NoteUndefinedInterface(SemIR::InterfaceId interface_id, DiagnosticBuilder& builder) -> void { const auto& interface_info = interfaces().Get(interface_id); - CARBON_CHECK(!interface_info.is_defined()) << "Interface is not incomplete"; + CARBON_CHECK(!interface_info.is_defined(), "Interface is not incomplete"); if (interface_info.is_being_defined()) { CARBON_DIAGNOSTIC(InterfaceUndefinedWithinDefinition, Note, "Interface is currently being defined."); @@ -389,7 +390,7 @@ static auto DiagnoseInvalidQualifiedNameAccess(Context& context, SemIRLoc loc, class_info.adapt_id)) { parent_type_id = adapt_decl->adapted_type_id; } else { - CARBON_FATAL() << "Expected parent for parent access"; + CARBON_FATAL("Expected parent for parent access"); } } @@ -615,7 +616,7 @@ auto Context::AddDominatedBlockAndBranchIf(Parse::NodeId node_id, auto Context::AddConvergenceBlockAndPush(Parse::NodeId node_id, int num_blocks) -> void { - CARBON_CHECK(num_blocks >= 2) << "no convergence"; + CARBON_CHECK(num_blocks >= 2, "no convergence"); SemIR::InstBlockId new_block_id = SemIR::InstBlockId::Unreachable; for ([[maybe_unused]] auto _ : llvm::seq(num_blocks)) { @@ -633,7 +634,7 @@ auto Context::AddConvergenceBlockAndPush(Parse::NodeId node_id, int num_blocks) auto Context::AddConvergenceBlockWithArgAndPush( Parse::NodeId node_id, std::initializer_list block_args) -> SemIR::InstId { - CARBON_CHECK(block_args.size() >= 2) << "no convergence"; + CARBON_CHECK(block_args.size() >= 2, "no convergence"); SemIR::InstBlockId new_block_id = SemIR::InstBlockId::Unreachable; for (auto arg_id : block_args) { @@ -671,8 +672,8 @@ auto Context::SetBlockArgResultBeforeConstantUse(SemIR::InstId select_id, const_id = constant_values().Get(literal.value().value.ToBool() ? if_true : if_false); } else { - CARBON_CHECK(cond_const_id == SemIR::ConstantId::Error) - << "Unexpected constant branch condition."; + CARBON_CHECK(cond_const_id == SemIR::ConstantId::Error, + "Unexpected constant branch condition."); const_id = SemIR::ConstantId::Error; } @@ -684,11 +685,11 @@ auto Context::SetBlockArgResultBeforeConstantUse(SemIR::InstId select_id, } auto Context::AddCurrentCodeBlockToFunction(Parse::NodeId node_id) -> void { - CARBON_CHECK(!inst_block_stack().empty()) << "no current code block"; + CARBON_CHECK(!inst_block_stack().empty(), "no current code block"); if (return_scope_stack().empty()) { - CARBON_CHECK(node_id.is_valid()) - << "No current function, but node_id not provided"; + CARBON_CHECK(node_id.is_valid(), + "No current function, but node_id not provided"); TODO(node_id, "Control flow expressions are currently only supported inside " "functions."); @@ -798,16 +799,16 @@ class TypeCompleter { if (!AddNestedIncompleteTypes(inst)) { return false; } - CARBON_CHECK(work_list_.size() >= old_work_list_size) - << "AddNestedIncompleteTypes should not remove work items"; + CARBON_CHECK(work_list_.size() >= old_work_list_size, + "AddNestedIncompleteTypes should not remove work items"); work_list_[old_work_list_size - 1].phase = Phase::BuildValueRepr; break; case Phase::BuildValueRepr: { auto value_rep = BuildValueRepr(type_id, inst); context_.types().SetValueRepr(type_id, value_rep); - CARBON_CHECK(old_work_list_size == work_list_.size()) - << "BuildValueRepr should not change work items"; + CARBON_CHECK(old_work_list_size == work_list_.size(), + "BuildValueRepr should not change work items"); work_list_.pop_back(); // Also complete the value representation type, if necessary. This @@ -919,11 +920,11 @@ class TypeCompleter { // Gets the value representation of a nested type, which should already be // complete. auto GetNestedValueRepr(SemIR::TypeId nested_type_id) const { - CARBON_CHECK(context_.types().IsComplete(nested_type_id)) - << "Nested type should already be complete"; + CARBON_CHECK(context_.types().IsComplete(nested_type_id), + "Nested type should already be complete"); auto value_rep = context_.types().GetValueRepr(nested_type_id); - CARBON_CHECK(value_rep.kind != SemIR::ValueRepr::Unknown) - << "Complete type should have a value representation"; + CARBON_CHECK(value_rep.kind != SemIR::ValueRepr::Unknown, + "Complete type should have a value representation"); return value_rep; } @@ -1105,7 +1106,7 @@ class TypeCompleter { requires(InstT::Kind.is_type() == SemIR::InstIsType::Never) auto BuildValueReprForInst(SemIR::TypeId /*type_id*/, InstT inst) const -> SemIR::ValueRepr { - CARBON_FATAL() << "Type refers to non-type inst " << inst; + CARBON_FATAL("Type refers to non-type inst {0}", inst); } // Builds and returns the value representation for the given type. All nested @@ -1173,16 +1174,16 @@ auto Context::TryToDefineType(SemIR::TypeId type_id, auto Context::GetTypeIdForTypeConstant(SemIR::ConstantId constant_id) -> SemIR::TypeId { - CARBON_CHECK(constant_id.is_constant()) - << "Canonicalizing non-constant type: " << constant_id; + CARBON_CHECK(constant_id.is_constant(), + "Canonicalizing non-constant type: {0}", constant_id); auto type_id = insts().Get(constant_values().GetInstId(constant_id)).type_id(); // TODO: For now, we allow values of facet type to be used as types. CARBON_CHECK(type_id == SemIR::TypeId::TypeType || - types().Is(type_id) || - constant_id == SemIR::ConstantId::Error) - << "Forming type ID for non-type constant of type " - << types().GetAsInst(type_id); + types().Is(type_id) || + constant_id == SemIR::ConstantId::Error, + "Forming type ID for non-type constant of type {0}", + types().GetAsInst(type_id)); return SemIR::TypeId::ForTypeConstant(constant_id); } @@ -1205,7 +1206,7 @@ static auto GetCompleteTypeImpl(Context& context, EachArgT... each_arg) -> SemIR::TypeId { auto type_id = GetTypeImpl(context, each_arg...); bool complete = context.TryToCompleteType(type_id); - CARBON_CHECK(complete) << "Type completion should not fail"; + CARBON_CHECK(complete, "Type completion should not fail"); return type_id; } @@ -1231,7 +1232,7 @@ auto Context::GetBuiltinType(SemIR::BuiltinInstKind kind) -> SemIR::TypeId { auto type_id = GetTypeIdForTypeInst(SemIR::InstId::ForBuiltin(kind)); // To keep client code simpler, complete builtin types before returning them. bool complete = TryToCompleteType(type_id); - CARBON_CHECK(complete) << "Failed to complete builtin type"; + CARBON_CHECK(complete, "Failed to complete builtin type"); return type_id; } diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 0ad0c2752475..557846d796c5 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -363,8 +363,7 @@ class Context { // Sets the total number of IRs which exist. This is used to prepare a map // from IR to imported IR. auto SetTotalIRCount(int num_irs) -> void { - CARBON_CHECK(check_ir_map_.empty()) - << "SetTotalIRCount is only called once"; + CARBON_CHECK(check_ir_map_.empty(), "SetTotalIRCount is only called once"); check_ir_map_.resize(num_irs, SemIR::ImportIRId::Invalid); } diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 4351885df105..37e7f85277f9 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -66,8 +66,7 @@ static auto FindReturnSlotForInitializer(SemIR::File& sem_ir, return sem_ir.inst_blocks().Get(call.args_id).back(); } default: - CARBON_FATAL() << "Initialization from unexpected inst " - << init_untyped; + CARBON_FATAL("Initialization from unexpected inst {0}", init_untyped); } } } @@ -80,10 +79,10 @@ static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::InstId init_id, if (return_slot_id.is_valid()) { // Replace the temporary in the return slot with a reference to our target. CARBON_CHECK(sem_ir.insts().Get(return_slot_id).kind() == - SemIR::TemporaryStorage::Kind) - << "Return slot for initializer does not contain a temporary; " - << "initialized multiple times? Have " - << sem_ir.insts().Get(return_slot_id); + SemIR::TemporaryStorage::Kind, + "Return slot for initializer does not contain a temporary; " + "initialized multiple times? Have {0}", + sem_ir.insts().Get(return_slot_id)); target_block.MergeReplacing(return_slot_id, target_id); } } @@ -100,10 +99,10 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id, if (return_slot_id.is_valid()) { // The return slot should already have a materialized temporary in it. CARBON_CHECK(sem_ir.insts().Get(return_slot_id).kind() == - SemIR::TemporaryStorage::Kind) - << "Return slot for initializer does not contain a temporary; " - << "initialized multiple times? Have " - << sem_ir.insts().Get(return_slot_id); + SemIR::TemporaryStorage::Kind, + "Return slot for initializer does not contain a temporary; " + "initialized multiple times? Have {0}", + sem_ir.insts().Get(return_slot_id)); auto init = sem_ir.insts().Get(init_id); return context.AddInst(sem_ir.insts().GetLocId(init_id), {.type_id = init.type_id(), @@ -423,8 +422,7 @@ static auto ConvertStructToStructOrClass(Context& context, for (auto [i, field_id] : llvm::enumerate(src_elem_fields)) { auto result = src_field_indexes.Insert( context.insts().GetAs(field_id).name_id, i); - CARBON_CHECK(result.is_inserted()) - << "Duplicate field in source structure"; + CARBON_CHECK(result.is_inserted(), "Duplicate field in source structure"); } } @@ -496,8 +494,8 @@ static auto ConvertStructToStructOrClass(Context& context, if (is_class) { target.init_block->InsertHere(); - CARBON_CHECK(is_init) - << "Converting directly to a class value is not supported"; + CARBON_CHECK(is_init, + "Converting directly to a class value is not supported"); return context.AddInst(value_loc_id, {.type_id = target.type_id, .elements_id = new_block.id(), @@ -1004,8 +1002,7 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, switch (SemIR::GetExprCategory(sem_ir, expr_id)) { case SemIR::ExprCategory::NotExpr: case SemIR::ExprCategory::Mixed: - CARBON_FATAL() << "Unexpected expression " << expr - << " after builtin conversions"; + CARBON_FATAL("Unexpected expression {0} after builtin conversions", expr); case SemIR::ExprCategory::Error: return SemIR::InstId::BuiltinError; diff --git a/toolchain/check/decl_introducer_state.h b/toolchain/check/decl_introducer_state.h index 193223a5126c..6e4e3728c593 100644 --- a/toolchain/check/decl_introducer_state.h +++ b/toolchain/check/decl_introducer_state.h @@ -74,9 +74,8 @@ class DeclIntroducerStateStack { template requires(IsDeclIntroducer()) auto Pop() -> DeclIntroducerState { - CARBON_CHECK(stack_.back().kind == Kind) - << "Found: " << stack_.back().kind - << " expected: " << Lex::TokenKind::Make(Kind); + CARBON_CHECK(stack_.back().kind == Kind, "Found: {0} expected: {1}", + stack_.back().kind, Lex::TokenKind::Make(Kind)); return stack_.pop_back_val(); } diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index 1bff4f3398e7..cb8eeeed51dd 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/toolchain/check/decl_name_stack.cpp @@ -23,9 +23,9 @@ auto DeclNameStack::NameContext::prev_inst_id() -> SemIR::InstId { return SemIR::InstId::Invalid; case NameContext::State::Empty: - CARBON_FATAL() - << "Name is missing, not expected to call existing_inst_id (but " - "that may change based on error handling)."; + CARBON_FATAL( + "Name is missing, not expected to call existing_inst_id (but that " + "may change based on error handling)."); case NameContext::State::Resolved: return resolved_inst_id; @@ -34,7 +34,7 @@ auto DeclNameStack::NameContext::prev_inst_id() -> SemIR::InstId { return SemIR::InstId::Invalid; case NameContext::State::Finished: - CARBON_FATAL() << "Finished state should only be used internally"; + CARBON_FATAL("Finished state should only be used internally"); } } @@ -59,8 +59,8 @@ auto DeclNameStack::PushScopeAndStartName() -> void { } auto DeclNameStack::FinishName(const NameComponent& name) -> NameContext { - CARBON_CHECK(decl_name_stack_.back().state != NameContext::State::Finished) - << "Finished name twice"; + CARBON_CHECK(decl_name_stack_.back().state != NameContext::State::Finished, + "Finished name twice"); ApplyAndLookupName(decl_name_stack_.back(), name.name_loc_id, name.name_id); @@ -70,8 +70,8 @@ auto DeclNameStack::FinishName(const NameComponent& name) -> NameContext { } auto DeclNameStack::FinishImplName() -> NameContext { - CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Empty) - << "Impl has a name"; + CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Empty, + "Impl has a name"); NameContext result = decl_name_stack_.back(); decl_name_stack_.back().state = NameContext::State::Finished; @@ -79,15 +79,15 @@ auto DeclNameStack::FinishImplName() -> NameContext { } auto DeclNameStack::PopScope() -> void { - CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished) - << "Missing call to FinishName before PopScope"; + CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished, + "Missing call to FinishName before PopScope"); context_->scope_stack().PopTo(decl_name_stack_.back().initial_scope_index); decl_name_stack_.pop_back(); } auto DeclNameStack::Suspend() -> SuspendedName { - CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished) - << "Missing call to FinishName before Suspend"; + CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished, + "Missing call to FinishName before Suspend"); SuspendedName result = {.name_context = decl_name_stack_.pop_back_val(), .scopes = {}}; auto scope_index = result.name_context.initial_scope_index; @@ -95,17 +95,17 @@ auto DeclNameStack::Suspend() -> SuspendedName { while (scope_stack.PeekIndex() > scope_index) { result.scopes.push_back(scope_stack.Suspend()); } - CARBON_CHECK(scope_stack.PeekIndex() == scope_index) - << "Scope index " << scope_index << " does not enclose the current scope " - << scope_stack.PeekIndex(); + CARBON_CHECK(scope_stack.PeekIndex() == scope_index, + "Scope index {0} does not enclose the current scope {1}", + scope_index, scope_stack.PeekIndex()); return result; } auto DeclNameStack::Restore(SuspendedName sus) -> void { // The parent state must be the same when a name is restored. CARBON_CHECK(context_->scope_stack().PeekIndex() == - sus.name_context.initial_scope_index) - << "Name restored at the wrong position in the name stack."; + sus.name_context.initial_scope_index, + "Name restored at the wrong position in the name stack."); // clang-tidy warns that the `std::move` below has no effect. While that's // true, this `move` defends against `NameContext` growing more state later. @@ -164,15 +164,15 @@ auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id, }; auto result = name_scope.name_map.Insert( name_context.unresolved_name_id, add_scope); - CARBON_CHECK(result.is_inserted()) - << "Duplicate names should have been resolved previously: " - << name_context.unresolved_name_id << " in " - << name_context.parent_scope_id; + CARBON_CHECK( + result.is_inserted(), + "Duplicate names should have been resolved previously: {0} in {1}", + name_context.unresolved_name_id, name_context.parent_scope_id); } break; default: - CARBON_FATAL() << "Should not be calling AddName"; + CARBON_FATAL("Should not be calling AddName"); break; } } @@ -284,7 +284,7 @@ static auto CheckQualifierIsResolved( Context& context, const DeclNameStack::NameContext& name_context) -> bool { switch (name_context.state) { case DeclNameStack::NameContext::State::Empty: - CARBON_FATAL() << "No qualifier to resolve"; + CARBON_FATAL("No qualifier to resolve"); case DeclNameStack::NameContext::State::Resolved: return true; @@ -297,7 +297,7 @@ static auto CheckQualifierIsResolved( return false; case DeclNameStack::NameContext::State::Finished: - CARBON_FATAL() << "Added a qualifier after calling FinishName"; + CARBON_FATAL("Added a qualifier after calling FinishName"); case DeclNameStack::NameContext::State::Error: // Already in an error state, so return without examining. diff --git a/toolchain/check/deduce.cpp b/toolchain/check/deduce.cpp index e2887d4557af..44ac3c8c1f52 100644 --- a/toolchain/check/deduce.cpp +++ b/toolchain/check/deduce.cpp @@ -156,10 +156,10 @@ auto DeduceGenericCallArguments( auto& entity_name = context.entity_names().Get(bind.entity_name_id); auto index = entity_name.bind_index; if (index.is_valid() && index >= first_deduced_index) { - CARBON_CHECK(static_cast(index.index) < result_arg_ids.size()) - << "Deduced value for unexpected index " << index - << "; expected to deduce " << result_arg_ids.size() - << " arguments."; + CARBON_CHECK(static_cast(index.index) < result_arg_ids.size(), + "Deduced value for unexpected index {0}; expected to " + "deduce {1} arguments.", + index, result_arg_ids.size()); auto arg_const_inst_id = context.constant_values().GetConstantInstId(arg_id); if (arg_const_inst_id.is_valid()) { diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index c48bc18b05e0..6b1d6e41be54 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -77,9 +77,10 @@ class EvalContext { specifics().Get(specific_id_).generic_id && symbolic_info.index.region() == specific_eval_info_->region) { auto inst_id = specific_eval_info_->values[symbolic_info.index.index()]; - CARBON_CHECK(inst_id.is_valid()) - << "Forward reference in eval block: index " - << symbolic_info.index.index() << " referenced before evaluation"; + CARBON_CHECK(inst_id.is_valid(), + "Forward reference in eval block: index {0} referenced " + "before evaluation", + symbolic_info.index.index()); return constant_values().Get(inst_id); } } @@ -464,14 +465,14 @@ static auto PerformAggregateAccess(EvalContext& eval_context, SemIR::Inst inst) aggregate_id)) { auto elements = eval_context.inst_blocks().Get(aggregate->elements_id); auto index = static_cast(access_inst.index.index); - CARBON_CHECK(index < elements.size()) << "Access out of bounds."; + CARBON_CHECK(index < elements.size(), "Access out of bounds."); // `Phase` is not used here. If this element is a template constant, then // so is the result of indexing, even if the aggregate also contains a // symbolic context. return eval_context.GetConstantValue(elements[index]); } else { - CARBON_CHECK(phase != Phase::Template) - << "Failed to evaluate template constant " << inst; + CARBON_CHECK(phase != Phase::Template, + "Failed to evaluate template constant {0}", inst); } } return MakeNonConstantResult(phase); @@ -490,8 +491,8 @@ static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst) } auto index = eval_context.insts().TryGetAs(index_id); if (!index) { - CARBON_CHECK(phase != Phase::Template) - << "Template constant integer should be a literal"; + CARBON_CHECK(phase != Phase::Template, + "Template constant integer should be a literal"); return MakeNonConstantResult(phase); } @@ -529,15 +530,15 @@ static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst) auto aggregate = eval_context.insts().TryGetAs(aggregate_id); if (!aggregate) { - CARBON_CHECK(phase != Phase::Template) - << "Unexpected representation for template constant aggregate"; + CARBON_CHECK(phase != Phase::Template, + "Unexpected representation for template constant aggregate"); return MakeNonConstantResult(phase); } auto elements = eval_context.inst_blocks().Get(aggregate->elements_id); // We checked this for the array case above. - CARBON_CHECK(index_val.ult(elements.size())) - << "Index out of bounds in tuple indexing"; + CARBON_CHECK(index_val.ult(elements.size()), + "Index out of bounds in tuple indexing"); return eval_context.GetConstantValue(elements[index_val.getZExtValue()]); } @@ -649,7 +650,7 @@ static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc, op_val.flipAllBits(); break; default: - CARBON_FATAL() << "Unexpected builtin kind"; + CARBON_FATAL("Unexpected builtin kind"); } return MakeIntResult(context, op.type_id, std::move(op_val)); @@ -774,7 +775,7 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc, break; default: - CARBON_FATAL() << "Unexpected operation kind."; + CARBON_FATAL("Unexpected operation kind."); } if (overflow) { @@ -823,7 +824,7 @@ static auto PerformBuiltinIntComparison(Context& context, result = is_signed ? lhs_val.sge(rhs_val) : lhs_val.sge(rhs_val); break; default: - CARBON_FATAL() << "Unexpected operation kind."; + CARBON_FATAL("Unexpected operation kind."); } return MakeBoolResult(context, bool_type_id, result); @@ -842,7 +843,7 @@ static auto PerformBuiltinUnaryFloatOp(Context& context, op_val.changeSign(); break; default: - CARBON_FATAL() << "Unexpected builtin kind"; + CARBON_FATAL("Unexpected builtin kind"); } return MakeFloatResult(context, op.type_id, std::move(op_val)); @@ -875,7 +876,7 @@ static auto PerformBuiltinBinaryFloatOp(Context& context, result_val = lhs_val / rhs_val; break; default: - CARBON_FATAL() << "Unexpected operation kind."; + CARBON_FATAL("Unexpected operation kind."); } return MakeFloatResult(context, lhs.type_id, std::move(result_val)); @@ -912,7 +913,7 @@ static auto PerformBuiltinFloatComparison( result = lhs_val >= rhs_val; break; default: - CARBON_FATAL() << "Unexpected operation kind."; + CARBON_FATAL("Unexpected operation kind."); } return MakeBoolResult(context, bool_type_id, result); @@ -926,7 +927,7 @@ static auto MakeConstantForBuiltinCall(Context& context, SemIRLoc loc, Phase phase) -> SemIR::ConstantId { switch (builtin_kind) { case SemIR::BuiltinFunctionKind::None: - CARBON_FATAL() << "Not a builtin function."; + CARBON_FATAL("Not a builtin function."); case SemIR::BuiltinFunctionKind::PrintInt: { // Providing a constant result would allow eliding the function call. @@ -1483,8 +1484,8 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, break; case SemIR::ImportRefUnloaded::Kind: - CARBON_FATAL() - << "ImportRefUnloaded should be loaded before TryEvalInst: " << inst; + CARBON_FATAL("ImportRefUnloaded should be loaded before TryEvalInst: {0}", + inst); } return SemIR::ConstantId::NotConstant; } diff --git a/toolchain/check/generic.cpp b/toolchain/check/generic.cpp index 594b8d558209..5ef082aa7c4a 100644 --- a/toolchain/check/generic.cpp +++ b/toolchain/check/generic.cpp @@ -73,9 +73,10 @@ class RebuildGenericConstantInEvalBlockCallbacks final if (!const_id.is_valid()) { // An unloaded import ref should never contain anything we need to // substitute into. Don't trigger loading it here. - CARBON_CHECK(context_.insts().Is(inst_id)) - << "Substituting into instruction with invalid constant ID: " - << context_.insts().Get(inst_id); + CARBON_CHECK( + context_.insts().Is(inst_id), + "Substituting into instruction with invalid constant ID: {0}", + context_.insts().Get(inst_id)); return true; } if (!const_id.is_symbolic()) { @@ -174,9 +175,9 @@ static auto AddGenericConstantToEvalBlock( SubstInst(context, const_inst_id, RebuildGenericConstantInEvalBlockCallbacks( context, generic_id, region, constants_in_generic)); - CARBON_CHECK(new_inst_id != const_inst_id) - << "Did not apply any substitutions to symbolic constant " - << context.insts().Get(const_inst_id); + CARBON_CHECK(new_inst_id != const_inst_id, + "Did not apply any substitutions to symbolic constant {0}", + context.insts().Get(const_inst_id)); return context.constant_values().Get(new_inst_id); } @@ -192,9 +193,9 @@ static auto PopulateConstantsFromDeclaration( for (auto inst_id : decl_eval_block) { auto const_inst_id = context.constant_values().GetConstantInstId(inst_id); auto result = constants_in_generic.Insert(const_inst_id, inst_id); - CARBON_CHECK(result.is_inserted()) - << "Duplicate constant in generic decl eval block: " - << context.insts().Get(const_inst_id); + CARBON_CHECK(result.is_inserted(), + "Duplicate constant in generic decl eval block: {0}", + context.insts().Get(const_inst_id)); } } @@ -252,12 +253,13 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id, } } - CARBON_CHECK(num_dependent_insts == - context.generic_region_stack().PeekDependentInsts().size()) - << "Building eval block added new dependent insts, for example " - << context.insts().Get(context.generic_region_stack() - .PeekDependentInsts()[num_dependent_insts] - .inst_id); + CARBON_CHECK( + num_dependent_insts == + context.generic_region_stack().PeekDependentInsts().size(), + "Building eval block added new dependent insts, for example {0}", + context.insts().Get(context.generic_region_stack() + .PeekDependentInsts()[num_dependent_insts] + .inst_id)); return context.inst_block_stack().Pop(); } @@ -283,11 +285,11 @@ auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id, // Build a constant in the inst block. AddGenericConstantToEvalBlock(context, generic_id, region, constants_in_generic, inst_id); - CARBON_CHECK(context.inst_block_stack().PeekCurrentBlockContents().size() == - i + 1) - << "Produced " - << (context.inst_block_stack().PeekCurrentBlockContents().size() - i) - << " instructions when importing " << context.insts().Get(inst_id); + CARBON_CHECK( + context.inst_block_stack().PeekCurrentBlockContents().size() == i + 1, + "Produced {0} instructions when importing {1}", + (context.inst_block_stack().PeekCurrentBlockContents().size() - i), + context.insts().Get(inst_id)); } return context.inst_block_stack().Pop(); @@ -299,9 +301,9 @@ auto FinishGenericDecl(Context& context, SemIR::InstId decl_id) context.scope_stack().compile_time_bindings_stack().PeekAllValues(); if (all_bindings.empty()) { - CARBON_CHECK(context.generic_region_stack().PeekDependentInsts().empty()) - << "Have dependent instructions but no compile time bindings are in " - "scope."; + CARBON_CHECK(context.generic_region_stack().PeekDependentInsts().empty(), + "Have dependent instructions but no compile time bindings are " + "in scope."); context.generic_region_stack().Pop(); return SemIR::GenericId::Invalid; } @@ -396,7 +398,7 @@ auto ResolveSpecificDefinition(Context& context, SemIR::SpecificId specific_id) -> bool { auto& specific = context.specifics().Get(specific_id); auto generic_id = specific.generic_id; - CARBON_CHECK(generic_id.is_valid()) << "Specific with no generic ID"; + CARBON_CHECK(generic_id.is_valid(), "Specific with no generic ID"); if (!specific.definition_block_id.is_valid()) { // Evaluate the eval block for the definition of the generic. diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 3843e9cc09df..d69395a0d73e 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -108,8 +108,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, cast_type_id); }); if (parent_class_decl) { - CARBON_CHECK(context_node_kind == Parse::NodeKind::VariableIntroducer) - << "`returned var` at class scope"; + CARBON_CHECK(context_node_kind == Parse::NodeKind::VariableIntroducer, + "`returned var` at class scope"); auto& class_info = context.classes().Get(parent_class_decl->class_id); auto field_type_id = context.GetUnboundElementType( class_info.self_type_id, cast_type_id); @@ -185,8 +185,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, } default: - CARBON_FATAL() << "Found a pattern binding in unexpected context " - << context_node_kind; + CARBON_FATAL("Found a pattern binding in unexpected context {0}", + context_node_kind); } return true; } diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index e6e6f505c8dd..c532817d277b 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -408,8 +408,8 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool { } else if (auto* adapted_class_info = TryGetAsClass(context, adapted_type_id)) { extended_scope_id = adapted_class_info->scope_id; - CARBON_CHECK(adapted_class_info->scope_id.is_valid()) - << "Complete class should have a scope"; + CARBON_CHECK(adapted_class_info->scope_id.is_valid(), + "Complete class should have a scope"); } else { // TODO: Accept any type that has a scope. context.TODO(node_id, "extending non-class type"); @@ -489,8 +489,8 @@ static auto CheckBaseType(Context& context, Parse::NodeId node_id, DiagnoseBaseIsFinal(context, node_id, base_type_id); } - CARBON_CHECK(base_class_info->scope_id.is_valid()) - << "Complete class should have a scope"; + CARBON_CHECK(base_class_info->scope_id.is_valid(), + "Complete class should have a scope"); return {.type_id = base_type_id, .scope_id = base_class_info->scope_id}; } diff --git a/toolchain/check/handle_if_statement.cpp b/toolchain/check/handle_if_statement.cpp index 2db260a31921..f1f034f74614 100644 --- a/toolchain/check/handle_if_statement.cpp +++ b/toolchain/check/handle_if_statement.cpp @@ -68,7 +68,7 @@ auto HandleParseNode(Context& context, Parse::IfStatementId node_id) -> bool { } default: { - CARBON_FATAL() << "Unexpected parse node at start of `if`: " << kind; + CARBON_FATAL("Unexpected parse node at start of `if`: {0}", kind); } } diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index dfd6e2019df1..ce338e9d36fd 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -137,8 +137,8 @@ auto HandleParseNode(Context& context, auto& interface_info = context.interfaces().Get(interface_id); // Track that this declaration is the definition. - CARBON_CHECK(!interface_info.is_defined()) - << "Can't merge with defined interfaces."; + CARBON_CHECK(!interface_info.is_defined(), + "Can't merge with defined interfaces."); interface_info.definition_id = interface_decl_id; interface_info.scope_id = context.name_scopes().Add(interface_decl_id, SemIR::NameId::Invalid, diff --git a/toolchain/check/handle_let_and_var.cpp b/toolchain/check/handle_let_and_var.cpp index 3d9c8f024959..5b35f07daff2 100644 --- a/toolchain/check/handle_let_and_var.cpp +++ b/toolchain/check/handle_let_and_var.cpp @@ -237,8 +237,8 @@ auto HandleParseNode(Context& context, Parse::LetDeclId node_id) -> bool { // the computation of the value. // TODO: Support other kinds of pattern here. auto bind_name = pattern.inst.As(); - CARBON_CHECK(!bind_name.value_id.is_valid()) - << "Binding should not already have a value!"; + CARBON_CHECK(!bind_name.value_id.is_valid(), + "Binding should not already have a value!"); bind_name.value_id = decl_info->init_id ? *decl_info->init_id : SemIR::InstId::BuiltinError; context.ReplaceInstBeforeConstantUse(decl_info->pattern_id, bind_name); diff --git a/toolchain/check/handle_name.cpp b/toolchain/check/handle_name.cpp index a3f679185755..2e6057166b94 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -104,7 +104,7 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id, auto value = context.insts().Get(result.inst_id); auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id, value.type_id()); - CARBON_CHECK(type_id.is_valid()) << "Missing type for " << value; + CARBON_CHECK(type_id.is_valid(), "Missing type for {0}", value); // If the named entity has a constant value that depends on its specific, // store the specific too. diff --git a/toolchain/check/handle_noop.cpp b/toolchain/check/handle_noop.cpp index 48ff804a34e5..251db60e7ab2 100644 --- a/toolchain/check/handle_noop.cpp +++ b/toolchain/check/handle_noop.cpp @@ -29,8 +29,8 @@ auto HandleParseNode(Context& context, Parse::InvalidParseSubtreeId node_id) auto HandleParseNode(Context& /*context*/, Parse::PlaceholderId /*node_id*/) -> bool { - CARBON_FATAL() - << "Placeholder node should always be replaced before parse completes"; + CARBON_FATAL( + "Placeholder node should always be replaced before parse completes"); } } // namespace Carbon::Check diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index 63788b7e662f..fa1583445124 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -125,8 +125,8 @@ auto HandleParseNode(Context& context, Parse::StructTypeLiteralId node_id) context.node_stack() .PopAndDiscardSoloNodeId(); - CARBON_CHECK(refs_id != SemIR::InstBlockId::Empty) - << "{} is handled by StructLiteral."; + CARBON_CHECK(refs_id != SemIR::InstBlockId::Empty, + "{{}} is handled by StructLiteral."); if (DiagnoseDuplicateNames(context, refs_id, "struct type literal")) { context.node_stack().Push(node_id, SemIR::InstId::BuiltinError); diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 9c5a9e4c4dc7..bc1844349b77 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -54,12 +54,12 @@ static auto GetSelfSpecificForInterfaceMemberWithSelfType( // Add the `Self` argument. CARBON_CHECK( context.entity_names() - .Get(context.insts() - .GetAs(bindings[arg_ids.size()]) - .entity_name_id) - .name_id == SemIR::NameId::SelfType) - << "Expected a Self binding, found " - << context.insts().Get(bindings[arg_ids.size()]); + .Get(context.insts() + .GetAs(bindings[arg_ids.size()]) + .entity_name_id) + .name_id == SemIR::NameId::SelfType, + "Expected a Self binding, found {0}", + context.insts().Get(bindings[arg_ids.size()])); arg_ids.push_back(context.types().GetInstId(self_type_id)); // Take any trailing argument values from the self specific. @@ -150,7 +150,7 @@ static auto BuildInterfaceWitness( decl_id = context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific( context.sem_ir(), interface_type.specific_id, decl_id)); - CARBON_CHECK(decl_id.is_valid()) << "Non-constant associated entity"; + CARBON_CHECK(decl_id.is_valid(), "Non-constant associated entity"); auto decl = context.insts().Get(decl_id); CARBON_KIND_SWITCH(decl) { case CARBON_KIND(SemIR::StructValue struct_value): { @@ -160,7 +160,7 @@ static auto BuildInterfaceWitness( auto type_inst = context.types().GetAsInst(struct_value.type_id); auto fn_type = type_inst.TryAs(); if (!fn_type) { - CARBON_FATAL() << "Unexpected type: " << type_inst; + CARBON_FATAL("Unexpected type: {0}", type_inst); } auto& fn = context.functions().Get(fn_type->function_id); auto [impl_decl_id, _] = context.LookupNameInExactScope( @@ -190,8 +190,8 @@ static auto BuildInterfaceWitness( "impl of interface with associated constant"); return SemIR::InstId::BuiltinError; default: - CARBON_CHECK(decl_id == SemIR::InstId::BuiltinError) - << "Unexpected kind of associated entity " << decl; + CARBON_CHECK(decl_id == SemIR::InstId::BuiltinError, + "Unexpected kind of associated entity {0}", decl); table.push_back(SemIR::InstId::BuiltinError); break; } diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index b5fe10812a26..7429968f32fd 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -63,7 +63,7 @@ static auto GetImportName(const SemIR::File& import_sem_ir, } default: - CARBON_FATAL() << "Unsupported export kind: " << import_inst; + CARBON_FATAL("Unsupported export kind: {0}", import_inst); } } @@ -152,9 +152,9 @@ static auto CacheCopiedNamespace( SemIR::NameScopeId import_scope_id, SemIR::NameScopeId to_scope_id) -> void { auto result = copied_namespaces.Insert(import_scope_id, to_scope_id); - CARBON_CHECK(result.is_inserted() || result.value() == to_scope_id) - << "Copy result for namespace changed from " << import_scope_id << " to " - << to_scope_id; + CARBON_CHECK(result.is_inserted() || result.value() == to_scope_id, + "Copy result for namespace changed from {0} to {1}", + import_scope_id, to_scope_id); } // Copies a namespace from the import IR, returning its ID. This may diagnose @@ -431,8 +431,8 @@ auto ImportLibrariesFromOtherPackage(Context& context, IdentifierId package_id, llvm::ArrayRef import_irs, bool has_load_error) -> void { - CARBON_CHECK(has_load_error || !import_irs.empty()) - << "There should be either a load error or at least one IR."; + CARBON_CHECK(has_load_error || !import_irs.empty(), + "There should be either a load error or at least one IR."); auto name_id = SemIR::NameId::ForIdentifier(package_id); diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index ece423c882e2..8f83579a25e0 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -36,8 +36,8 @@ auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void { // We don't have a check_ir_id, so add without touching check_ir_map. ir_id = InternalAddImportIR(context, import_ir); } - CARBON_CHECK(ir_id == SemIR::ImportIRId::ApiForImpl) - << "ApiForImpl must be the first IR"; + CARBON_CHECK(ir_id == SemIR::ImportIRId::ApiForImpl, + "ApiForImpl must be the first IR"); } auto AddImportIR(Context& context, SemIR::ImportIR import_ir) @@ -244,9 +244,9 @@ class ImportRefResolver { auto [new_const_id, retry] = TryResolveInst(work.inst_id, existing.const_id); - CARBON_CHECK(!existing.const_id.is_valid() || - existing.const_id == new_const_id) - << "Constant value changed in third phase."; + CARBON_CHECK( + !existing.const_id.is_valid() || existing.const_id == new_const_id, + "Constant value changed in third phase."); if (!existing.const_id.is_valid()) { SetResolvedConstId(work.inst_id, existing.indirect_insts, new_const_id); } @@ -394,8 +394,8 @@ class ImportRefResolver { } cursor_inst_id = ir_inst.inst_id; - CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id) - << cursor_ir->insts().Get(cursor_inst_id); + CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id, + "{0}", cursor_ir->insts().Get(cursor_inst_id)); if (auto const_id = context_.import_ir_constant_values()[cursor_ir_id.index].Get( @@ -426,8 +426,8 @@ class ImportRefResolver { // Returns true if new unresolved constants were found as part of this // `Resolve` step. auto HasNewWork() -> bool { - CARBON_CHECK(initial_work_ <= work_stack_.size()) - << "Work shouldn't decrease"; + CARBON_CHECK(initial_work_ <= work_stack_.size(), + "Work shouldn't decrease"); return initial_work_ < work_stack_.size(); } @@ -586,7 +586,7 @@ class ImportRefResolver { .generic_id; } default: { - CARBON_FATAL() << "Unexpected type for generic declaration: " << type; + CARBON_FATAL("Unexpected type for generic declaration: {0}", type); } } } @@ -736,7 +736,7 @@ class ImportRefResolver { break; } default: { - CARBON_FATAL() << "Unexpected kind: " << bind_inst->kind; + CARBON_FATAL("Unexpected kind: {0}", bind_inst->kind); } } } @@ -829,8 +829,8 @@ class ImportRefResolver { break; } } - CARBON_FATAL() << "Unexpected instruction kind for name scope: " - << name_scope_inst; + CARBON_FATAL("Unexpected instruction kind for name scope: {0}", + name_scope_inst); } // Given an imported entity base, returns an incomplete, local version of it. @@ -961,8 +961,8 @@ class ImportRefResolver { } else { // Third phase: perform a consistency check and produce the constant we // created in the second phase. - CARBON_CHECK(result.const_id == inner_const_id) - << "Constant value changed in third phase."; + CARBON_CHECK(result.const_id == inner_const_id, + "Constant value changed in third phase."); result.const_id = const_id; } @@ -1104,7 +1104,7 @@ class ImportRefResolver { auto ResolveAsUntyped(SemIR::Inst inst) -> ResolveResult { CARBON_CHECK(!HasNewWork()); auto result = TryEvalInst(context_, SemIR::InstId::Invalid, inst); - CARBON_CHECK(result.is_constant()) << inst << " is not constant"; + CARBON_CHECK(result.is_constant(), "{0} is not constant", inst); return {.const_id = result}; } @@ -1602,8 +1602,8 @@ class ImportRefResolver { new_interface.body_block_id = context_.inst_block_stack().Pop(); new_interface.self_param_id = self_param_id; - CARBON_CHECK(import_scope.extended_scopes.empty()) - << "Interfaces don't currently have extended scopes to support."; + CARBON_CHECK(import_scope.extended_scopes.empty(), + "Interfaces don't currently have extended scopes to support."); } auto TryResolveTypedInst(SemIR::InterfaceDecl inst, diff --git a/toolchain/check/inst_block_stack.cpp b/toolchain/check/inst_block_stack.cpp index b9b7edbb662b..d225c05383cb 100644 --- a/toolchain/check/inst_block_stack.cpp +++ b/toolchain/check/inst_block_stack.cpp @@ -12,8 +12,8 @@ namespace Carbon::Check { auto InstBlockStack::Push(SemIR::InstBlockId id) -> void { CARBON_VLOG("{0} Push {1}\n", name_, id_stack_.size()); - CARBON_CHECK(id_stack_.size() < (1 << 20)) - << "Excessive stack size: likely infinite loop"; + CARBON_CHECK(id_stack_.size() < (1 << 20), + "Excessive stack size: likely infinite loop"); id_stack_.push_back(id); insts_stack_.PushArray(); } @@ -25,7 +25,7 @@ auto InstBlockStack::Push(SemIR::InstBlockId id, } auto InstBlockStack::PeekOrAdd(int depth) -> SemIR::InstBlockId { - CARBON_CHECK(static_cast(id_stack_.size()) > depth) << "no such block"; + CARBON_CHECK(static_cast(id_stack_.size()) > depth, "no such block"); int index = id_stack_.size() - depth - 1; auto& slot = id_stack_[index]; if (!slot.is_valid()) { @@ -35,7 +35,7 @@ auto InstBlockStack::PeekOrAdd(int depth) -> SemIR::InstBlockId { } auto InstBlockStack::Pop() -> SemIR::InstBlockId { - CARBON_CHECK(!empty()) << "no current block"; + CARBON_CHECK(!empty(), "no current block"); auto id = id_stack_.pop_back_val(); auto insts = insts_stack_.PeekArray(); @@ -55,7 +55,7 @@ auto InstBlockStack::Pop() -> SemIR::InstBlockId { } auto InstBlockStack::PopAndDiscard() -> void { - CARBON_CHECK(!empty()) << "no current block"; + CARBON_CHECK(!empty(), "no current block"); id_stack_.pop_back(); insts_stack_.PopArray(); CARBON_VLOG("{0} PopAndDiscard {1}\n", name_, id_stack_.size()); diff --git a/toolchain/check/inst_block_stack.h b/toolchain/check/inst_block_stack.h index 0115861d4bcf..df718a099a92 100644 --- a/toolchain/check/inst_block_stack.h +++ b/toolchain/check/inst_block_stack.h @@ -54,7 +54,7 @@ class InstBlockStack { // Adds the given instruction ID to the block at the top of the stack. auto AddInstId(SemIR::InstId inst_id) -> void { - CARBON_CHECK(!empty()) << "no current block"; + CARBON_CHECK(!empty(), "no current block"); insts_stack_.AppendToTop(inst_id); } @@ -65,7 +65,7 @@ class InstBlockStack { // Returns a view of the contents of the top instruction block on the stack. auto PeekCurrentBlockContents() const -> llvm::ArrayRef { - CARBON_CHECK(!empty()) << "no current block"; + CARBON_CHECK(!empty(), "no current block"); return insts_stack_.PeekArray(); } @@ -75,7 +75,7 @@ class InstBlockStack { // Runs verification that the processing cleanly finished. auto VerifyOnFinish() const -> void { - CARBON_CHECK(empty()) << id_stack_.size(); + CARBON_CHECK(empty(), "{0}", id_stack_.size()); } auto empty() const -> bool { return id_stack_.empty(); } diff --git a/toolchain/check/lexical_lookup.h b/toolchain/check/lexical_lookup.h index 60ce5a94e8d6..3a0ee1cc691f 100644 --- a/toolchain/check/lexical_lookup.h +++ b/toolchain/check/lexical_lookup.h @@ -43,13 +43,14 @@ class LexicalLookup { // Returns the lexical lookup results for a name. auto Get(SemIR::NameId name_id) -> llvm::SmallVector& { auto index = GetLookupIndex(name_id); - CARBON_CHECK(index < lookup_.size()) - << "An identifier was added after the Context was initialized. " - "Currently, we expect that new identifiers will never be used with " - "lexical lookup (they're added for things like detecting name " - "collisions in imports). That might change with metaprogramming: if " - "it does, we may need to start resizing `lookup_`, either on each " - "identifier addition or in Get` where this CHECK currently fires."; + CARBON_CHECK( + index < lookup_.size(), + "An identifier was added after the Context was initialized. Currently, " + "we expect that new identifiers will never be used with lexical lookup " + "(they're added for things like detecting name collisions in imports). " + "That might change with metaprogramming: if it does, we may need to " + "start resizing `lookup_`, either on each identifier addition or in " + "Get` where this CHECK currently fires."); return lookup_[index]; } @@ -57,10 +58,10 @@ class LexicalLookup { auto Suspend(SemIR::NameId name_id) -> SuspendedResult { auto index = GetLookupIndex(name_id); auto& results = lookup_[index]; - CARBON_CHECK(!results.empty()) - << "Suspending a nonexistent result for " << name_id << "."; - CARBON_CHECK(index <= std::numeric_limits::max()) - << "Unexpectedly large index " << index << " for name ID"; + CARBON_CHECK(!results.empty(), "Suspending a nonexistent result for {0}.", + name_id); + CARBON_CHECK(index <= std::numeric_limits::max(), + "Unexpectedly large index {0} for name ID", index); return {.index = static_cast(index), .inst_id = results.pop_back_val().inst_id}; } diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 7020fabf6578..d6e5a5f5cad9 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -80,8 +80,7 @@ static auto GetClassElementIndex(Context& context, SemIR::InstId element_id) if (auto base = element_inst.TryAs()) { return base->index; } - CARBON_FATAL() << "Unexpected value " << element_inst - << " in class element name"; + CARBON_FATAL("Unexpected value {0} in class element name", element_inst); } // Returns whether `function_id` is an instance method, that is, whether it has @@ -321,7 +320,7 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id, auto inst = context.insts().Get(result.inst_id); auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id, inst.type_id()); - CARBON_CHECK(type_id.is_valid()) << "Missing type for member " << inst; + CARBON_CHECK(type_id.is_valid(), "Missing type for member {0}", inst); // If the named entity has a constant value that depends on its specific, // store the specific too. @@ -372,9 +371,9 @@ static auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id, // Find the specified element, which could be either a field or a base // class, and build an element access expression. auto element_id = context.constant_values().GetConstantInstId(member_id); - CARBON_CHECK(element_id.is_valid()) - << "Non-constant value " << context.insts().Get(member_id) - << " of unbound element type"; + CARBON_CHECK(element_id.is_valid(), + "Non-constant value {0} of unbound element type", + context.insts().Get(member_id)); auto index = GetClassElementIndex(context, element_id); auto access_id = context.AddInst( loc_id, {.type_id = unbound_element_type.element_type_id, diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index a93059a3fa47..ae00a8f7b5f4 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -348,12 +348,12 @@ static auto CheckRedeclParamSyntax(Context& context, !prev_first_param_node_id.is_valid()) { return true; } - CARBON_CHECK(new_last_param_node_id.is_valid()) - << "new_last_param_node_id.is_valid should match " - "new_first_param_node_id.is_valid"; - CARBON_CHECK(prev_last_param_node_id.is_valid()) - << "prev_last_param_node_id.is_valid should match " - "prev_first_param_node_id.is_valid"; + CARBON_CHECK(new_last_param_node_id.is_valid(), + "new_last_param_node_id.is_valid should match " + "new_first_param_node_id.is_valid"); + CARBON_CHECK(prev_last_param_node_id.is_valid(), + "prev_last_param_node_id.is_valid should match " + "prev_first_param_node_id.is_valid"); auto new_range = Parse::Tree::PostorderIterator::MakeRange( new_first_param_node_id, new_last_param_node_id); diff --git a/toolchain/check/node_stack.cpp b/toolchain/check/node_stack.cpp index 8b28e0707d78..3d7ca19cecdd 100644 --- a/toolchain/check/node_stack.cpp +++ b/toolchain/check/node_stack.cpp @@ -14,7 +14,7 @@ auto NodeStack::PrintForStackDump(SemIR::Formatter& formatter, int indent, if constexpr (Kind == Id::Kind::None) { output << "no value\n"; } else if constexpr (Kind == Id::Kind::Invalid) { - CARBON_FATAL() << "Should not be in node stack"; + CARBON_FATAL("Should not be in node stack"); } else if constexpr (Kind == Id::KindFor()) { output << "\n"; formatter.PrintInst(id.As()>(), indent + 4, diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index fd1db507e030..02c68da70583 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -79,11 +79,11 @@ class NodeStack { // IR generated by the node. auto Push(Parse::NodeId node_id) -> void { auto kind = parse_tree_->node_kind(node_id); - CARBON_CHECK(NodeKindToIdKind(kind) == Id::Kind::None) - << "Parse kind expects an Id: " << kind; + CARBON_CHECK(NodeKindToIdKind(kind) == Id::Kind::None, + "Parse kind expects an Id: {0}", kind); CARBON_VLOG("Node Push {0}: {1} -> \n", stack_.size(), kind); - CARBON_CHECK(stack_.size() < (1 << 20)) - << "Excessive stack size: likely infinite loop"; + CARBON_CHECK(stack_.size() < (1 << 20), + "Excessive stack size: likely infinite loop"); stack_.push_back({.node_id = node_id, .id = Id()}); } @@ -91,14 +91,13 @@ class NodeStack { template auto Push(Parse::NodeId node_id, IdT id) -> void { auto kind = parse_tree_->node_kind(node_id); - CARBON_CHECK(NodeKindToIdKind(kind) == Id::KindFor()) - << "Parse kind expected a different IdT: " << kind << " -> " << id - << "\n"; - CARBON_CHECK(id.is_valid()) - << "Push called with invalid id: " << parse_tree_->node_kind(node_id); + CARBON_CHECK(NodeKindToIdKind(kind) == Id::KindFor(), + "Parse kind expected a different IdT: {0} -> {1}\n", kind, id); + CARBON_CHECK(id.is_valid(), "Push called with invalid id: {0}", + parse_tree_->node_kind(node_id)); CARBON_VLOG("Node Push {0}: {1} -> {2}\n", stack_.size(), kind, id); - CARBON_CHECK(stack_.size() < (1 << 20)) - << "Excessive stack size: likely infinite loop"; + CARBON_CHECK(stack_.size() < (1 << 20), + "Excessive stack size: likely infinite loop"); stack_.push_back({.node_id = node_id, .id = Id(id)}); } @@ -690,27 +689,27 @@ class NodeStack { // Require a Parse::NodeKind be mapped to a particular Id::Kind. auto RequireIdKind(Parse::NodeKind parse_kind, Id::Kind id_kind) const -> void { - CARBON_CHECK(NodeKindToIdKind(parse_kind) == id_kind) - << "Unexpected Id::Kind mapping for " << parse_kind << ": expected " - << static_cast(id_kind) << ", found " - << static_cast(NodeKindToIdKind(parse_kind)); + CARBON_CHECK(NodeKindToIdKind(parse_kind) == id_kind, + "Unexpected Id::Kind mapping for {0}: expected {1}, found {2}", + parse_kind, static_cast(id_kind), + static_cast(NodeKindToIdKind(parse_kind))); } // Require an entry to have the given Parse::NodeKind. template auto RequireParseKind(Parse::NodeId node_id) const -> void { auto actual_kind = parse_tree_->node_kind(node_id); - CARBON_CHECK(RequiredParseKind == actual_kind) - << "Expected " << RequiredParseKind << ", found " << actual_kind; + CARBON_CHECK(RequiredParseKind == actual_kind, "Expected {0}, found {1}", + RequiredParseKind, actual_kind); } // Require an entry to have the given Parse::NodeCategory. template auto RequireParseCategory(Parse::NodeId node_id) const -> void { auto kind = parse_tree_->node_kind(node_id); - CARBON_CHECK(kind.category().HasAnyOf(RequiredParseCategory)) - << "Expected " << RequiredParseCategory << ", found " << kind - << " with category " << kind.category(); + CARBON_CHECK(kind.category().HasAnyOf(RequiredParseCategory), + "Expected {0}, found {1} with category {2}", + RequiredParseCategory, kind, kind.category()); } // The file's parse tree. diff --git a/toolchain/check/return.cpp b/toolchain/check/return.cpp index b12adf40067b..aa3c495efea8 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -11,8 +11,8 @@ namespace Carbon::Check { // Gets the function that lexically encloses the current location. static auto GetCurrentFunction(Context& context) -> SemIR::Function& { - CARBON_CHECK(!context.return_scope_stack().empty()) - << "Handling return but not in a function"; + CARBON_CHECK(!context.return_scope_stack().empty(), + "Handling return but not in a function"); auto function_id = context.insts() .GetAs( context.return_scope_stack().back().decl_id) @@ -23,8 +23,8 @@ static auto GetCurrentFunction(Context& context) -> SemIR::Function& { // Gets the currently in scope `returned var`, if any, that would be returned // by a `return var;`. static auto GetCurrentReturnedVar(Context& context) -> SemIR::InstId { - CARBON_CHECK(!context.return_scope_stack().empty()) - << "Handling return but not in a function"; + CARBON_CHECK(!context.return_scope_stack().empty(), + "Handling return but not in a function"); return context.return_scope_stack().back().returned_var; } diff --git a/toolchain/check/scope_stack.cpp b/toolchain/check/scope_stack.cpp index 8df737f512e3..a7a1119e2a1e 100644 --- a/toolchain/check/scope_stack.cpp +++ b/toolchain/check/scope_stack.cpp @@ -10,7 +10,7 @@ namespace Carbon::Check { auto ScopeStack::VerifyOnFinish() -> void { - CARBON_CHECK(scope_stack_.empty()) << scope_stack_.size(); + CARBON_CHECK(scope_stack_.empty(), "{0}", scope_stack_.size()); } auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id, @@ -41,13 +41,13 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id, // For lexical lookups, unqualified lookup doesn't know how to find the // associated specific, so if we start adding lexical scopes associated with // specifics, we'll need to somehow track them in lookup. - CARBON_CHECK(!specific_id.is_valid()) - << "Lexical scope should not have an associated specific."; + CARBON_CHECK(!specific_id.is_valid(), + "Lexical scope should not have an associated specific."); } // TODO: Handle this case more gracefully. - CARBON_CHECK(next_scope_index_.index != std::numeric_limits::max()) - << "Ran out of scopes"; + CARBON_CHECK(next_scope_index_.index != std::numeric_limits::max(), + "Ran out of scopes"); ++next_scope_index_.index; } @@ -56,8 +56,8 @@ auto ScopeStack::Pop() -> void { scope.names.ForEach([&](SemIR::NameId str_id) { auto& lexical_results = lexical_lookup_.Get(str_id); - CARBON_CHECK(lexical_results.back().scope_index == scope.index) - << "Inconsistent scope index for name " << str_id; + CARBON_CHECK(lexical_results.back().scope_index == scope.index, + "Inconsistent scope index for name {0}", str_id); lexical_results.pop_back(); }); @@ -74,10 +74,11 @@ auto ScopeStack::Pop() -> void { CARBON_CHECK( scope.next_compile_time_bind_index.index == - static_cast(compile_time_binding_stack_.all_values_size())) - << "Wrong number of entries in compile-time binding stack, have " - << compile_time_binding_stack_.all_values_size() << ", expected " - << scope.next_compile_time_bind_index.index; + static_cast(compile_time_binding_stack_.all_values_size()), + "Wrong number of entries in compile-time binding stack, have {0}, " + "expected {1}", + compile_time_binding_stack_.all_values_size(), + scope.next_compile_time_bind_index.index); compile_time_binding_stack_.PopArray(); } @@ -85,9 +86,9 @@ auto ScopeStack::PopTo(ScopeIndex index) -> void { while (PeekIndex() > index) { Pop(); } - CARBON_CHECK(PeekIndex() == index) - << "Scope index " << index << " does not enclose the current scope " - << PeekIndex(); + CARBON_CHECK(PeekIndex() == index, + "Scope index {0} does not enclose the current scope {1}", index, + PeekIndex()); } auto ScopeStack::LookupInCurrentScope(SemIR::NameId name_id) -> SemIR::InstId { @@ -135,8 +136,8 @@ auto ScopeStack::LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id) -> SemIR::InstId { if (!scope_stack_.back().names.Insert(name_id).is_inserted()) { auto existing = lexical_lookup_.Get(name_id).back().inst_id; - CARBON_CHECK(existing.is_valid()) - << "Name in scope but not in lexical lookups"; + CARBON_CHECK(existing.is_valid(), + "Name in scope but not in lexical lookups"); return existing; } ++scope_stack_.back().num_names; @@ -144,24 +145,25 @@ auto ScopeStack::LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id) // TODO: Reject if we previously performed a failed lookup for this name // in this scope or a scope nested within it. auto& lexical_results = lexical_lookup_.Get(name_id); - CARBON_CHECK(lexical_results.empty() || - lexical_results.back().scope_index < PeekIndex()) - << "Failed to clean up after scope nested within the current scope"; + CARBON_CHECK( + lexical_results.empty() || + lexical_results.back().scope_index < PeekIndex(), + "Failed to clean up after scope nested within the current scope"); lexical_results.push_back({.inst_id = target_id, .scope_index = PeekIndex()}); return SemIR::InstId::Invalid; } auto ScopeStack::SetReturnedVarOrGetExisting(SemIR::InstId inst_id) -> SemIR::InstId { - CARBON_CHECK(!return_scope_stack_.empty()) << "`returned var` in no function"; + CARBON_CHECK(!return_scope_stack_.empty(), "`returned var` in no function"); auto& returned_var = return_scope_stack_.back().returned_var; if (returned_var.is_valid()) { return returned_var; } returned_var = inst_id; - CARBON_CHECK(!scope_stack_.back().has_returned_var) - << "Scope has returned var but none is set"; + CARBON_CHECK(!scope_stack_.back().has_returned_var, + "Scope has returned var but none is set"); if (inst_id.is_valid()) { scope_stack_.back().has_returned_var = true; } @@ -169,7 +171,7 @@ auto ScopeStack::SetReturnedVarOrGetExisting(SemIR::InstId inst_id) } auto ScopeStack::Suspend() -> SuspendedScope { - CARBON_CHECK(!scope_stack_.empty()) << "No scope to suspend"; + CARBON_CHECK(!scope_stack_.empty(), "No scope to suspend"); SuspendedScope result = {.entry = scope_stack_.pop_back_val(), .suspended_items = {}}; if (result.entry.scope_id.is_valid()) { @@ -198,8 +200,8 @@ auto ScopeStack::Suspend() -> SuspendedScope { compile_time_binding_stack_.PopArray(); // This would be easy to support if we had a need, but currently we do not. - CARBON_CHECK(!result.entry.has_returned_var) - << "Should not suspend a scope with a returned var."; + CARBON_CHECK(!result.entry.has_returned_var, + "Should not suspend a scope with a returned var."); return result; } @@ -216,11 +218,11 @@ auto ScopeStack::Restore(SuspendedScope scope) -> void { CARBON_CHECK( scope.entry.next_compile_time_bind_index.index == - static_cast(compile_time_binding_stack_.all_values_size())) - << "Wrong number of entries in compile-time binding stack " - "when restoring, have " - << compile_time_binding_stack_.all_values_size() << ", expected " - << scope.entry.next_compile_time_bind_index.index; + static_cast(compile_time_binding_stack_.all_values_size()), + "Wrong number of entries in compile-time binding stack when restoring, " + "have {0}, expected {1}", + compile_time_binding_stack_.all_values_size(), + scope.entry.next_compile_time_bind_index.index); if (scope.entry.scope_id.is_valid()) { non_lexical_scope_stack_.push_back( diff --git a/toolchain/check/sem_ir_diagnostic_converter.cpp b/toolchain/check/sem_ir_diagnostic_converter.cpp index 4a029665276e..74c2be1d5456 100644 --- a/toolchain/check/sem_ir_diagnostic_converter.cpp +++ b/toolchain/check/sem_ir_diagnostic_converter.cpp @@ -18,9 +18,9 @@ auto SemIRDiagnosticConverter::ConvertLoc(SemIRLoc loc, auto follow_import_ref = [&](SemIR::ImportIRInstId import_ir_inst_id) { auto import_ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id); const auto& import_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id); - CARBON_CHECK(import_ir.decl_id.is_valid()) - << "If we get invalid locations here, we may need to more thoroughly " - "track ImportDecls."; + CARBON_CHECK(import_ir.decl_id.is_valid(), + "If we get invalid locations here, we may need to more " + "thoroughly track ImportDecls."); DiagnosticLoc in_import_loc; auto import_loc_id = cursor_ir->insts().GetLocId(import_ir.decl_id); @@ -37,8 +37,8 @@ auto SemIRDiagnosticConverter::ConvertLoc(SemIRLoc loc, cursor_ir->import_irs().Get(implicit_import_ir_inst.ir_id); auto implicit_loc_id = implicit_ir.sem_ir->insts().GetLocId(implicit_import_ir_inst.inst_id); - CARBON_CHECK(implicit_loc_id.is_node_id()) - << "Should only be one layer of implicit imports"; + CARBON_CHECK(implicit_loc_id.is_node_id(), + "Should only be one layer of implicit imports"); in_import_loc = ConvertLocInFile(implicit_ir.sem_ir, implicit_loc_id.node_id(), loc.token_only, context_fn); @@ -75,7 +75,7 @@ auto SemIRDiagnosticConverter::ConvertLoc(SemIRLoc loc, if (auto diag_loc = handle_loc(loc.loc_id)) { return *diag_loc; } - CARBON_CHECK(cursor_inst_id.is_valid()) << "Should have been set"; + CARBON_CHECK(cursor_inst_id.is_valid(), "Should have been set"); } while (true) { diff --git a/toolchain/check/subst.cpp b/toolchain/check/subst.cpp index adff7307b9f0..ffa32d74a117 100644 --- a/toolchain/check/subst.cpp +++ b/toolchain/check/subst.cpp @@ -45,7 +45,7 @@ class Worklist { worklist_.push_back({.inst_id = inst_id, .is_expanded = false, .next_index = static_cast(worklist_.size() + 1)}); - CARBON_CHECK(worklist_.back().next_index > 0) << "Constant too large."; + CARBON_CHECK(worklist_.back().next_index > 0, "Constant too large."); } auto Pop() -> SemIR::InstId { return worklist_.pop_back_val().inst_id; } @@ -240,8 +240,8 @@ auto SubstInst(Context& context, SemIR::InstId inst_id, } } - CARBON_CHECK(worklist.size() == 1) - << "Unexpected data left behind in work list"; + CARBON_CHECK(worklist.size() == 1, + "Unexpected data left behind in work list"); return worklist.back().inst_id; } @@ -288,8 +288,8 @@ class SubstConstantCallbacks final : public SubstInstCallbacks { auto Rebuild(SemIR::InstId /*old_inst_id*/, SemIR::Inst new_inst) const -> SemIR::InstId override { auto result_id = TryEvalInst(context_, SemIR::InstId::Invalid, new_inst); - CARBON_CHECK(result_id.is_constant()) - << "Substitution into constant produced non-constant"; + CARBON_CHECK(result_id.is_constant(), + "Substitution into constant produced non-constant"); return context_.constant_values().GetInstId(result_id); } @@ -301,7 +301,7 @@ class SubstConstantCallbacks final : public SubstInstCallbacks { auto SubstConstant(Context& context, SemIR::ConstantId const_id, Substitutions substitutions) -> SemIR::ConstantId { - CARBON_CHECK(const_id.is_constant()) << "Substituting into non-constant"; + CARBON_CHECK(const_id.is_constant(), "Substituting into non-constant"); if (substitutions.empty()) { // Nothing to substitute. diff --git a/toolchain/diagnostics/diagnostic_emitter.h b/toolchain/diagnostics/diagnostic_emitter.h index 6cfaf6e147be..8222678dcefd 100644 --- a/toolchain/diagnostics/diagnostic_emitter.h +++ b/toolchain/diagnostics/diagnostic_emitter.h @@ -63,8 +63,8 @@ class DiagnosticEmitter { auto Note(LocT loc, const Internal::DiagnosticBase& diagnostic_base, Internal::NoTypeDeduction... args) -> DiagnosticBuilder& { - CARBON_CHECK(diagnostic_base.Level == DiagnosticLevel::Note) - << static_cast(diagnostic_base.Level); + CARBON_CHECK(diagnostic_base.Level == DiagnosticLevel::Note, "{0}", + static_cast(diagnostic_base.Level)); AddMessage(loc, diagnostic_base, {emitter_->MakeAny(args)...}); return *this; } @@ -137,9 +137,9 @@ class DiagnosticEmitter { static auto FormatFn(const DiagnosticMessage& message, std::index_sequence /*indices*/) -> std::string { static_assert(sizeof...(Args) == sizeof...(N), "Invalid template args"); - CARBON_CHECK(message.format_args.size() == sizeof...(Args)) - << "Argument count mismatch on " << message.kind << ": " - << message.format_args.size() << " != " << sizeof...(Args); + CARBON_CHECK(message.format_args.size() == sizeof...(Args), + "Argument count mismatch on {0}: {1} != {2}", message.kind, + message.format_args.size(), sizeof...(Args)); return llvm::formatv( message.format.data(), llvm::any_cast< @@ -189,9 +189,10 @@ class DiagnosticEmitter { auto MakeAny(Arg arg) -> llvm::Any { llvm::Any converted = converter_->ConvertArg(arg); using Storage = Internal::DiagnosticTypeForArg::StorageType; - CARBON_CHECK(llvm::any_cast(&converted)) - << "Failed to convert argument of type " << typeid(Arg).name() - << " to its storage type " << typeid(Storage).name(); + CARBON_CHECK( + llvm::any_cast(&converted), + "Failed to convert argument of type {0} to its storage type {1}", + typeid(Arg).name(), typeid(Storage).name()); return converted; } diff --git a/toolchain/diagnostics/sorting_diagnostic_consumer.h b/toolchain/diagnostics/sorting_diagnostic_consumer.h index 35a307a97b74..9aa6c00c42ef 100644 --- a/toolchain/diagnostics/sorting_diagnostic_consumer.h +++ b/toolchain/diagnostics/sorting_diagnostic_consumer.h @@ -22,8 +22,8 @@ class SortingDiagnosticConsumer : public DiagnosticConsumer { // likely to refer to data that gets destroyed before the diagnostics // consumer is destroyed, because the diagnostics consumer is typically // created before the objects that diagnostics refer into are created. - CARBON_CHECK(diagnostics_.empty()) - << "Must flush diagnostics consumer before destroying it"; + CARBON_CHECK(diagnostics_.empty(), + "Must flush diagnostics consumer before destroying it"); } // Buffers the diagnostic. diff --git a/toolchain/docs/idioms.md b/toolchain/docs/idioms.md index a8d6fb9bbe4b..cf93efb1f61f 100644 --- a/toolchain/docs/idioms.md +++ b/toolchain/docs/idioms.md @@ -289,7 +289,7 @@ CARBON_DCHECK([&] { return complicated && multiple_parts; // finish defining the lambda, and then immediately invoke it -}()) << "Complicated things went wrong"; +}(), "Complicated things went wrong"); ``` See a description of this technique on diff --git a/toolchain/driver/clang_runner.cpp b/toolchain/driver/clang_runner.cpp index df33d6e6d937..5c1b3a2c92db 100644 --- a/toolchain/driver/clang_runner.cpp +++ b/toolchain/driver/clang_runner.cpp @@ -118,7 +118,7 @@ auto ClangRunner::Run(llvm::ArrayRef args) -> bool { // driver.CC1Main = [](llvm::SmallVectorImpl& argv) {}; std::unique_ptr compilation( driver.BuildCompilation(cstr_args)); - CARBON_CHECK(compilation) << "Should always successfully allocate!"; + CARBON_CHECK(compilation, "Should always successfully allocate!"); if (compilation->containsError()) { // These should have been diagnosed by the driver. return false; diff --git a/toolchain/driver/clang_runner_test.cpp b/toolchain/driver/clang_runner_test.cpp index 09d6a4b42c14..edaa951e5b7d 100644 --- a/toolchain/driver/clang_runner_test.cpp +++ b/toolchain/driver/clang_runner_test.cpp @@ -106,7 +106,7 @@ static auto WriteTestFile(llvm::StringRef name_suffix, llvm::Twine contents) { std::error_code ec; llvm::raw_fd_ostream test_file_stream(test_file.string(), ec); - CARBON_CHECK(!ec) << "Test file error: " << ec.message(); + CARBON_CHECK(!ec, "Test file error: {0}", ec.message()); test_file_stream << contents; } return test_file; diff --git a/toolchain/driver/driver.cpp b/toolchain/driver/driver.cpp index b2e4ba8d1003..3f27f77611a9 100644 --- a/toolchain/driver/driver.cpp +++ b/toolchain/driver/driver.cpp @@ -946,8 +946,8 @@ auto Driver::Compile(const CompileOptions& options, if (options.phase == CompileOptions::Phase::Lower) { return make_result(); } - CARBON_CHECK(options.phase == CompileOptions::Phase::CodeGen) - << "CodeGen should be the last stage"; + CARBON_CHECK(options.phase == CompileOptions::Phase::CodeGen, + "CodeGen should be the last stage"); // Codegen. for (auto& unit : units) { diff --git a/toolchain/driver/driver_fuzzer.cpp b/toolchain/driver/driver_fuzzer.cpp index 9f8deb5abf3f..4cb9b7b6a252 100644 --- a/toolchain/driver/driver_fuzzer.cpp +++ b/toolchain/driver/driver_fuzzer.cpp @@ -20,7 +20,7 @@ static const InstallPaths* install_paths = nullptr; // NOLINTNEXTLINE(readability-non-const-parameter): External API required types. extern "C" auto LLVMFuzzerInitialize(int* argc, char*** argv) -> int { - CARBON_CHECK(*argc >= 1) << "Need the `argv[0]` value to initialize!"; + CARBON_CHECK(*argc >= 1, "Need the `argv[0]` value to initialize!"); install_paths = new InstallPaths( InstallPaths::MakeForBazelRunfiles(FindExecutablePath((*argv)[0]))); return 0; diff --git a/toolchain/driver/driver_test.cpp b/toolchain/driver/driver_test.cpp index 009835081fce..2fbe05cdf046 100644 --- a/toolchain/driver/driver_test.cpp +++ b/toolchain/driver/driver_test.cpp @@ -65,7 +65,7 @@ class DriverTest : public testing::Test { // Save our current working directory. std::error_code ec; auto original_dir = std::filesystem::current_path(ec); - CARBON_CHECK(!ec) << ec.message(); + CARBON_CHECK(!ec, "{0}", ec.message()); const auto* unit_test = ::testing::UnitTest::GetInstance(); const auto* test_info = unit_test->current_test_info(); @@ -74,19 +74,20 @@ class DriverTest : public testing::Test { test_info->name()) .str()); std::filesystem::create_directory(test_dir, ec); - CARBON_CHECK(!ec) << "Could not create test working dir '" << test_dir - << "': " << ec.message(); + CARBON_CHECK(!ec, "Could not create test working dir '{0}': {1}", test_dir, + ec.message()); std::filesystem::current_path(test_dir, ec); - CARBON_CHECK(!ec) << "Could not change the current working dir to '" - << test_dir << "': " << ec.message(); + CARBON_CHECK(!ec, "Could not change the current working dir to '{0}': {1}", + test_dir, ec.message()); return llvm::make_scope_exit([original_dir, test_dir] { std::error_code ec; std::filesystem::current_path(original_dir, ec); - CARBON_CHECK(!ec) << "Could not change the current working dir to '" - << original_dir << "': " << ec.message(); + CARBON_CHECK(!ec, + "Could not change the current working dir to '{0}': {1}", + original_dir, ec.message()); std::filesystem::remove_all(test_dir, ec); - CARBON_CHECK(!ec) << "Could not remove the test working dir '" << test_dir - << "': " << ec.message(); + CARBON_CHECK(!ec, "Could not remove the test working dir '{0}': {1}", + test_dir, ec.message()); }); } diff --git a/toolchain/install/install_paths.cpp b/toolchain/install/install_paths.cpp index 820d4d164625..7e8e88dc87a3 100644 --- a/toolchain/install/install_paths.cpp +++ b/toolchain/install/install_paths.cpp @@ -54,8 +54,8 @@ auto InstallPaths::MakeForBazelRunfiles(llvm::StringRef exe_path) std::string runtimes_error; std::unique_ptr runfiles( Runfiles::Create(exe_path.str(), &runtimes_error)); - CARBON_CHECK(runfiles != nullptr) - << "Failed to find runtimes tree: " << runtimes_error; + CARBON_CHECK(runfiles != nullptr, "Failed to find runtimes tree: {0}", + runtimes_error); std::string relative_marker_path = (PrefixRoot.str() + MarkerPath).str(); std::string runtimes_marker_path = runfiles->Rlocation(relative_marker_path); @@ -68,7 +68,7 @@ auto InstallPaths::MakeForBazelRunfiles(llvm::StringRef exe_path) "../../"); paths.CheckMarkerFile(); - CARBON_CHECK(!paths.error()) << *paths.error(); + CARBON_CHECK(!paths.error(), "{0}", *paths.error()); return paths; } diff --git a/toolchain/install/install_paths_test.cpp b/toolchain/install/install_paths_test.cpp index b3c980417bc5..79668fae0489 100644 --- a/toolchain/install/install_paths_test.cpp +++ b/toolchain/install/install_paths_test.cpp @@ -29,7 +29,7 @@ class InstallPathsTest : public ::testing::Test { InstallPathsTest() { std::string error; test_runfiles_.reset(Runfiles::Create(Testing::GetExePath().str(), &error)); - CARBON_CHECK(test_runfiles_ != nullptr) << error; + CARBON_CHECK(test_runfiles_ != nullptr, "{0}", error); } // Test the install paths found with the given `exe_path`. Will check that @@ -92,8 +92,8 @@ TEST_F(InstallPathsTest, PrefixRootExplicit) { "carbon/toolchain/install/prefix_root/lib/carbon/carbon_install.txt"); llvm::StringRef prefix_path = marker_path; - CARBON_CHECK(prefix_path.consume_back("lib/carbon/carbon_install.txt")) - << "Unexpected suffix of the marker path: " << marker_path; + CARBON_CHECK(prefix_path.consume_back("lib/carbon/carbon_install.txt"), + "Unexpected suffix of the marker path: {0}", marker_path); auto paths = InstallPaths::Make(prefix_path); ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error(); @@ -109,8 +109,8 @@ TEST_F(InstallPathsTest, TestRunfiles) { TEST_F(InstallPathsTest, BinaryRunfiles) { std::string test_binary_path = test_runfiles_->Rlocation("carbon/toolchain/install/test_binary"); - CARBON_CHECK(llvm::sys::fs::can_execute(test_binary_path)) - << test_binary_path; + CARBON_CHECK(llvm::sys::fs::can_execute(test_binary_path), "{0}", + test_binary_path); auto paths = InstallPaths::MakeForBazelRunfiles(test_binary_path); ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error(); diff --git a/toolchain/install/install_paths_test_helpers.cpp b/toolchain/install/install_paths_test_helpers.cpp index acdda8a6050e..30a1e7506f19 100644 --- a/toolchain/install/install_paths_test_helpers.cpp +++ b/toolchain/install/install_paths_test_helpers.cpp @@ -15,14 +15,14 @@ auto AddPreludeFilesToVfs(InstallPaths install_paths, // Load the prelude into the test VFS. auto real_fs = llvm::vfs::getRealFileSystem(); auto prelude = install_paths.ReadPreludeManifest(); - CARBON_CHECK(prelude.ok()) << prelude.error(); + CARBON_CHECK(prelude.ok(), "{0}", prelude.error()); for (const auto& path : *prelude) { llvm::ErrorOr> file = real_fs->getBufferForFile(path); - CARBON_CHECK(file) << "Error getting file: " << file.getError().message(); + CARBON_CHECK(file, "Error getting file: {0}", file.getError().message()); bool added = vfs->addFile(path, /*ModificationTime=*/0, std::move(*file)); - CARBON_CHECK(added) << "Duplicate file: " << path; + CARBON_CHECK(added, "Duplicate file: {0}", path); } } diff --git a/toolchain/lex/lex.cpp b/toolchain/lex/lex.cpp index a04a77813fd5..c7461d8817c3 100644 --- a/toolchain/lex/lex.cpp +++ b/toolchain/lex/lex.cpp @@ -508,7 +508,7 @@ static auto DispatchNext(Lexer& lexer, llvm::StringRef source_text, static auto Dispatch##LexMethod(Lexer& lexer, llvm::StringRef source_text, \ ssize_t position) -> void { \ Lexer::LexResult result = lexer.LexMethod(source_text, position); \ - CARBON_CHECK(result) << "Failed to form a token!"; \ + CARBON_CHECK(result, "Failed to form a token!"); \ [[clang::musttail]] return DispatchNext(lexer, source_text, position); \ } CARBON_DISPATCH_LEX_TOKEN(LexError) @@ -527,7 +527,7 @@ CARBON_DISPATCH_LEX_TOKEN(LexStringLiteral) OneCharTokenKindTable[static_cast( \ source_text[position])], \ position); \ - CARBON_CHECK(result) << "Failed to form a token!"; \ + CARBON_CHECK(result, "Failed to form a token!"); \ [[clang::musttail]] return DispatchNext(lexer, source_text, position); \ } CARBON_DISPATCH_LEX_SYMBOL_TOKEN(LexOneChar) @@ -855,7 +855,7 @@ auto Lexer::LexCommentOrSlash(llvm::StringRef source_text, ssize_t& position) // This code path should produce a token, make sure that happens. LexResult result = LexSymbolToken(source_text, position); - CARBON_CHECK(result) << "Failed to form a token!"; + CARBON_CHECK(result, "Failed to form a token!"); } auto Lexer::LexComment(llvm::StringRef source_text, ssize_t& position) -> void { @@ -1063,10 +1063,10 @@ auto Lexer::LexOneCharSymbolToken(llvm::StringRef source_text, TokenKind kind, // Verify in a debug build that the incoming token kind is correct. CARBON_DCHECK(kind != TokenKind::Error); CARBON_DCHECK(kind.fixed_spelling().size() == 1); - CARBON_DCHECK(source_text[position] == kind.fixed_spelling().front()) - << "Source text starts with '" << source_text[position] - << "' instead of the spelling '" << kind.fixed_spelling() - << "' of the incoming token kind '" << kind << "'"; + CARBON_DCHECK(source_text[position] == kind.fixed_spelling().front(), + "Source text starts with '{0}' instead of the spelling '{1}' " + "of the incoming token kind '{2}'", + source_text[position], kind.fixed_spelling(), kind); TokenIndex token = LexToken(kind, position); ++position; @@ -1077,10 +1077,10 @@ auto Lexer::LexOpeningSymbolToken(llvm::StringRef source_text, TokenKind kind, ssize_t& position) -> LexResult { CARBON_DCHECK(kind.is_opening_symbol()); CARBON_DCHECK(kind.fixed_spelling().size() == 1); - CARBON_DCHECK(source_text[position] == kind.fixed_spelling().front()) - << "Source text starts with '" << source_text[position] - << "' instead of the spelling '" << kind.fixed_spelling() - << "' of the incoming token kind '" << kind << "'"; + CARBON_DCHECK(source_text[position] == kind.fixed_spelling().front(), + "Source text starts with '{0}' instead of the spelling '{1}' " + "of the incoming token kind '{2}'", + source_text[position], kind.fixed_spelling(), kind); int32_t byte_offset = position; ++position; @@ -1096,10 +1096,10 @@ auto Lexer::LexClosingSymbolToken(llvm::StringRef source_text, TokenKind kind, ssize_t& position) -> LexResult { CARBON_DCHECK(kind.is_closing_symbol()); CARBON_DCHECK(kind.fixed_spelling().size() == 1); - CARBON_DCHECK(source_text[position] == kind.fixed_spelling().front()) - << "Source text starts with '" << source_text[position] - << "' instead of the spelling '" << kind.fixed_spelling() - << "' of the incoming token kind '" << kind << "'"; + CARBON_DCHECK(source_text[position] == kind.fixed_spelling().front(), + "Source text starts with '{0}' instead of the spelling '{1}' " + "of the incoming token kind '{2}'", + source_text[position], kind.fixed_spelling(), kind); int32_t byte_offset = position; ++position; @@ -1204,7 +1204,7 @@ auto Lexer::LexKeywordOrIdentifier(llvm::StringRef source_text, // Take the valid characters off the front of the source buffer. llvm::StringRef identifier_text = ScanForIdentifierPrefix(source_text.substr(position)); - CARBON_CHECK(!identifier_text.empty()) << "Must have at least one character!"; + CARBON_CHECK(!identifier_text.empty(), "Must have at least one character!"); position += identifier_text.size(); // Check if the text is a type literal, and if so form such a literal. @@ -1255,7 +1255,7 @@ auto Lexer::LexHash(llvm::StringRef source_text, ssize_t& position) // Take the valid characters off the front of the source buffer. llvm::StringRef identifier_text = ScanForIdentifierPrefix(source_text.substr(position + 1)); - CARBON_CHECK(!identifier_text.empty()) << "Must have at least one character!"; + CARBON_CHECK(!identifier_text.empty(), "Must have at least one character!"); position += 1 + identifier_text.size(); // Replace the `r` identifier's value with the raw identifier. @@ -1359,14 +1359,14 @@ class Lexer::ErrorRecoveryBuffer { // currently require insertions to be specified in source order, but this // restriction would be easy to relax. auto InsertBefore(TokenIndex insert_before, TokenKind kind) -> void { - CARBON_CHECK(insert_before.index > 0) - << "Cannot insert before the start of file token."; - CARBON_CHECK(insert_before.index < - static_cast(buffer_.token_infos_.size())) - << "Cannot insert after the end of file token."; - CARBON_CHECK(new_tokens_.empty() || - new_tokens_.back().first <= insert_before) - << "Insertions performed out of order."; + CARBON_CHECK(insert_before.index > 0, + "Cannot insert before the start of file token."); + CARBON_CHECK( + insert_before.index < static_cast(buffer_.token_infos_.size()), + "Cannot insert after the end of file token."); + CARBON_CHECK( + new_tokens_.empty() || new_tokens_.back().first <= insert_before, + "Insertions performed out of order."); // If the `insert_before` token has leading whitespace, mark the // inserted token as also having leading whitespace. This avoids changing @@ -1423,12 +1423,12 @@ class Lexer::ErrorRecoveryBuffer { if (kind.is_opening_symbol()) { open_groups.push_back(token); } else if (kind.is_closing_symbol()) { - CARBON_CHECK(!open_groups.empty()) << "Failed to balance brackets"; + CARBON_CHECK(!open_groups.empty(), "Failed to balance brackets"); auto opening_token = open_groups.pop_back_val(); CARBON_CHECK( - kind == buffer_.GetTokenInfo(opening_token).kind().closing_symbol()) - << "Failed to balance brackets"; + kind == buffer_.GetTokenInfo(opening_token).kind().closing_symbol(), + "Failed to balance brackets"); auto& opening_token_info = buffer_.GetTokenInfo(opening_token); auto& closing_token_info = buffer_.GetTokenInfo(token); opening_token_info.set_closing_token_index(token); @@ -1530,7 +1530,7 @@ auto Lexer::DiagnoseAndFixMismatchedBrackets() -> void { fixes.ReplaceWithError(token); } - CARBON_CHECK(!fixes.empty()) << "Didn't find anything to fix"; + CARBON_CHECK(!fixes.empty(), "Didn't find anything to fix"); fixes.Apply(); fixes.FixTokenCrossReferences(); } diff --git a/toolchain/lex/numeric_literal.cpp b/toolchain/lex/numeric_literal.cpp index 88f452d2dc0f..8b78e2b01a68 100644 --- a/toolchain/lex/numeric_literal.cpp +++ b/toolchain/lex/numeric_literal.cpp @@ -82,7 +82,7 @@ auto NumericLiteral::Lex(llvm::StringRef source_text) IsAlnum(source_text[i + 1])) { // This is not possible because we don't update result.exponent after we // see a '+' or '-'. - CARBON_CHECK(!seen_plus_minus) << "should only consume one + or -"; + CARBON_CHECK(!seen_plus_minus, "should only consume one + or -"); seen_plus_minus = true; continue; } diff --git a/toolchain/lex/string_literal.cpp b/toolchain/lex/string_literal.cpp index 718e578980b8..f32ff8b5c31f 100644 --- a/toolchain/lex/string_literal.cpp +++ b/toolchain/lex/string_literal.cpp @@ -282,7 +282,7 @@ static auto AppendFrontOfContents(char*& buffer_cursor, static auto ExpandAndConsumeEscapeSequence(LexerDiagnosticEmitter& emitter, llvm::StringRef& content, char*& buffer_cursor) -> void { - CARBON_CHECK(!content.empty()) << "should have escaped closing delimiter"; + CARBON_CHECK(!content.empty(), "should have escaped closing delimiter"); char first = content.front(); content = content.drop_front(1); @@ -424,8 +424,8 @@ static auto ExpandEscapeSequencesAndRemoveIndent( if (IsHorizontalWhitespace(contents.front())) { // Horizontal whitespace other than ` ` is valid only at the end of a // line. - CARBON_CHECK(contents.front() != ' ') - << "should not have stopped at a plain space"; + CARBON_CHECK(contents.front() != ' ', + "should not have stopped at a plain space"); auto after_space = contents.find_if_not(IsHorizontalWhitespace); if (after_space == llvm::StringRef::npos || contents[after_space] != '\n') { @@ -487,9 +487,9 @@ auto StringLiteral::ComputeValue(llvm::BumpPtrAllocator& allocator, auto result = ExpandEscapeSequencesAndRemoveIndent( emitter, content_, hash_level_, indent, allocator.Allocate(content_.size())); - CARBON_CHECK(result.size() <= content_.size()) - << "Content grew from " << content_.size() << " to " << result.size() - << ": `" << content_ << "`"; + CARBON_CHECK(result.size() <= content_.size(), + "Content grew from {0} to {1}: `{2}`", content_.size(), + result.size(), content_); return result; } diff --git a/toolchain/lex/test_helpers.h b/toolchain/lex/test_helpers.h index b1eae9238d53..88bfa4f9d18c 100644 --- a/toolchain/lex/test_helpers.h +++ b/toolchain/lex/test_helpers.h @@ -26,8 +26,8 @@ class SingleTokenDiagnosticConverter : public DiagnosticConverter { auto ConvertLoc(const char* pos, ContextFnT /*context_fn*/) const -> DiagnosticLoc override { - CARBON_CHECK(StringRefContainsPointer(token_, pos)) - << "invalid diagnostic location"; + CARBON_CHECK(StringRefContainsPointer(token_, pos), + "invalid diagnostic location"); llvm::StringRef prefix = token_.take_front(pos - token_.begin()); auto [before_last_newline, this_line] = prefix.rsplit('\n'); if (before_last_newline.size() == prefix.size()) { diff --git a/toolchain/lex/token_kind.h b/toolchain/lex/token_kind.h index abe69dfd0c4f..bfe1a49fcebf 100644 --- a/toolchain/lex/token_kind.h +++ b/toolchain/lex/token_kind.h @@ -56,7 +56,7 @@ class TokenKind : public CARBON_ENUM_BASE(TokenKind) { // The token kind must be an opening symbol. auto closing_symbol() const -> TokenKind { auto result = ClosingSymbol[AsInt()]; - CARBON_DCHECK(result != Error) << "Only opening symbols are valid!"; + CARBON_DCHECK(result != Error, "Only opening symbols are valid!"); return result; } @@ -68,7 +68,7 @@ class TokenKind : public CARBON_ENUM_BASE(TokenKind) { // The token kind must be a closing symbol. auto opening_symbol() const -> TokenKind { auto result = OpeningSymbol[AsInt()]; - CARBON_DCHECK(result != Error) << "Only closing symbols are valid!"; + CARBON_DCHECK(result != Error, "Only closing symbols are valid!"); return result; } diff --git a/toolchain/lex/tokenized_buffer.cpp b/toolchain/lex/tokenized_buffer.cpp index 66c3d8ad3f33..d6eccc6fdcae 100644 --- a/toolchain/lex/tokenized_buffer.cpp +++ b/toolchain/lex/tokenized_buffer.cpp @@ -75,7 +75,7 @@ auto TokenizedBuffer::GetTokenText(TokenIndex token) const -> llvm::StringRef { token_info.kind() == TokenKind::RealLiteral) { std::optional relexed_token = NumericLiteral::Lex(source_->text().substr(token_info.byte_offset())); - CARBON_CHECK(relexed_token) << "Could not reform numeric literal token."; + CARBON_CHECK(relexed_token, "Could not reform numeric literal token."); return relexed_token->text(); } @@ -84,7 +84,7 @@ auto TokenizedBuffer::GetTokenText(TokenIndex token) const -> llvm::StringRef { if (token_info.kind() == TokenKind::StringLiteral) { std::optional relexed_token = StringLiteral::Lex(source_->text().substr(token_info.byte_offset())); - CARBON_CHECK(relexed_token) << "Could not reform string literal token."; + CARBON_CHECK(relexed_token, "Could not reform string literal token."); return relexed_token->text(); } @@ -102,56 +102,60 @@ auto TokenizedBuffer::GetTokenText(TokenIndex token) const -> llvm::StringRef { return llvm::StringRef(); } - CARBON_CHECK(token_info.kind() == TokenKind::Identifier) << token_info.kind(); + CARBON_CHECK(token_info.kind() == TokenKind::Identifier, "{0}", + token_info.kind()); return value_stores_->identifiers().Get(token_info.ident_id()); } auto TokenizedBuffer::GetIdentifier(TokenIndex token) const -> IdentifierId { const auto& token_info = GetTokenInfo(token); - CARBON_CHECK(token_info.kind() == TokenKind::Identifier) << token_info.kind(); + CARBON_CHECK(token_info.kind() == TokenKind::Identifier, "{0}", + token_info.kind()); return token_info.ident_id(); } auto TokenizedBuffer::GetIntLiteral(TokenIndex token) const -> IntId { const auto& token_info = GetTokenInfo(token); - CARBON_CHECK(token_info.kind() == TokenKind::IntLiteral) << token_info.kind(); + CARBON_CHECK(token_info.kind() == TokenKind::IntLiteral, "{0}", + token_info.kind()); return token_info.int_id(); } auto TokenizedBuffer::GetRealLiteral(TokenIndex token) const -> RealId { const auto& token_info = GetTokenInfo(token); - CARBON_CHECK(token_info.kind() == TokenKind::RealLiteral) - << token_info.kind(); + CARBON_CHECK(token_info.kind() == TokenKind::RealLiteral, "{0}", + token_info.kind()); return token_info.real_id(); } auto TokenizedBuffer::GetStringLiteralValue(TokenIndex token) const -> StringLiteralValueId { const auto& token_info = GetTokenInfo(token); - CARBON_CHECK(token_info.kind() == TokenKind::StringLiteral) - << token_info.kind(); + CARBON_CHECK(token_info.kind() == TokenKind::StringLiteral, "{0}", + token_info.kind()); return token_info.string_literal_id(); } auto TokenizedBuffer::GetTypeLiteralSize(TokenIndex token) const -> IntId { const auto& token_info = GetTokenInfo(token); - CARBON_CHECK(token_info.kind().is_sized_type_literal()) << token_info.kind(); + CARBON_CHECK(token_info.kind().is_sized_type_literal(), "{0}", + token_info.kind()); return token_info.int_id(); } auto TokenizedBuffer::GetMatchedClosingToken(TokenIndex opening_token) const -> TokenIndex { const auto& opening_token_info = GetTokenInfo(opening_token); - CARBON_CHECK(opening_token_info.kind().is_opening_symbol()) - << opening_token_info.kind(); + CARBON_CHECK(opening_token_info.kind().is_opening_symbol(), "{0}", + opening_token_info.kind()); return opening_token_info.closing_token_index(); } auto TokenizedBuffer::GetMatchedOpeningToken(TokenIndex closing_token) const -> TokenIndex { const auto& closing_token_info = GetTokenInfo(closing_token); - CARBON_CHECK(closing_token_info.kind().is_closing_symbol()) - << closing_token_info.kind(); + CARBON_CHECK(closing_token_info.kind().is_closing_symbol(), "{0}", + closing_token_info.kind()); return closing_token_info.opening_token_index(); } @@ -205,7 +209,7 @@ auto TokenizedBuffer::PrintWidths::Widen(const PrintWidths& widths) -> void { // // This routine requires its argument to be *non-negative*. static auto ComputeDecimalPrintedWidth(int number) -> int { - CARBON_CHECK(number >= 0) << "Negative numbers are not supported."; + CARBON_CHECK(number >= 0, "Negative numbers are not supported."); if (number == 0) { return 1; } @@ -382,8 +386,8 @@ auto TokenIterator::Print(llvm::raw_ostream& output) const -> void { auto TokenizedBuffer::SourceBufferDiagnosticConverter::ConvertLoc( const char* loc, ContextFnT /*context_fn*/) const -> DiagnosticLoc { - CARBON_CHECK(StringRefContainsPointer(buffer_->source_->text(), loc)) - << "location not within buffer"; + CARBON_CHECK(StringRefContainsPointer(buffer_->source_->text(), loc), + "location not within buffer"); int32_t offset = loc - buffer_->source_->text().begin(); // Find the first line starting after the given location. @@ -392,8 +396,8 @@ auto TokenizedBuffer::SourceBufferDiagnosticConverter::ConvertLoc( [offset](const LineInfo& line) { return line.start <= offset; }); // Step back one line to find the line containing the given position. - CARBON_CHECK(next_line_it != buffer_->line_infos_.begin()) - << "location precedes the start of the first line"; + CARBON_CHECK(next_line_it != buffer_->line_infos_.begin(), + "location precedes the start of the first line"); const auto* line_it = std::prev(next_line_it); int line_number = line_it - buffer_->line_infos_.begin(); int column_number = offset - line_it->start; diff --git a/toolchain/lex/tokenized_buffer.h b/toolchain/lex/tokenized_buffer.h index ebf12855d772..da2ca1d1f18a 100644 --- a/toolchain/lex/tokenized_buffer.h +++ b/toolchain/lex/tokenized_buffer.h @@ -399,8 +399,8 @@ class TokenizedBuffer : public Printable { has_leading_space_(has_leading_space), token_payload_(payload), byte_offset_(byte_offset) { - CARBON_DCHECK(payload >= 0 && payload < (2 << PayloadBits)) - << "Payload won't fit into unsigned bit pack: " << payload; + CARBON_DCHECK(payload >= 0 && payload < (2 << PayloadBits), + "Payload won't fit into unsigned bit pack: {0}", payload); } // A bitfield that encodes the token's kind, the leading space flag, and the diff --git a/toolchain/lex/tokenized_buffer_benchmark.cpp b/toolchain/lex/tokenized_buffer_benchmark.cpp index 37252ee7a989..7e9d5099c1a6 100644 --- a/toolchain/lex/tokenized_buffer_benchmark.cpp +++ b/toolchain/lex/tokenized_buffer_benchmark.cpp @@ -85,9 +85,10 @@ struct RandomSourceOptions { string_literal_percent)); CARBON_CHECK(tokens_per_line <= NumTokens); - CARBON_CHECK(NumTokens % tokens_per_line == 0) - << "Tokens per line of " << tokens_per_line - << " does not divide the number of tokens " << NumTokens; + CARBON_CHECK( + NumTokens % tokens_per_line == 0, + "Tokens per line of {0} does not divide the number of tokens {1}", + tokens_per_line, NumTokens); CARBON_CHECK(is_percentage(comment_line_percent)); CARBON_CHECK(is_percentage(blank_line_percent)); @@ -142,10 +143,10 @@ auto RandomSource(RandomSourceOptions options) -> std::string { int num_symbols = (NumTokens / 100) * options.symbol_percent; int num_keywords = (NumTokens / 100) * options.keyword_percent; int num_identifiers = NumTokens - num_symbols - num_keywords; - CARBON_CHECK(num_identifiers == 0 || num_identifiers > 500) - << "We require at least 500 identifiers as we need to collect a " - "reasonable number of samples to end up with a reasonable " - "distribution of lengths."; + CARBON_CHECK( + num_identifiers == 0 || num_identifiers > 500, + "We require at least 500 identifiers as we need to collect a reasonable " + "number of samples to end up with a reasonable distribution of lengths."); llvm::SmallVector ids = Testing::SourceGen::Global().GetIdentifiers(num_identifiers); @@ -221,8 +222,8 @@ class LexerBenchHelper { StreamDiagnosticConsumer consumer(out); auto buffer = Lex::Lex(value_stores_, source_, consumer); consumer.Flush(); - CARBON_CHECK(buffer.has_errors()) - << "Asked to diagnose errors but none found!"; + CARBON_CHECK(buffer.has_errors(), + "Asked to diagnose errors but none found!"); return result; } @@ -332,7 +333,7 @@ void BM_ValidIdentifiers(benchmark::State& state) { LexerBenchHelper helper(source); for (auto _ : state) { TokenizedBuffer buffer = helper.Lex(); - CARBON_CHECK(!buffer.has_errors()) << helper.DiagnoseErrors(); + CARBON_CHECK(!buffer.has_errors(), "{0}", helper.DiagnoseErrors()); } state.SetBytesProcessed(state.iterations() * source.size()); @@ -370,7 +371,7 @@ void BM_HorizontalWhitespace(benchmark::State& state) { // Ensure that lexing actually occurs for benchmarking and that it doesn't // hit errors that would skew the benchmark results. - CARBON_CHECK(!buffer.has_errors()) << helper.DiagnoseErrors(); + CARBON_CHECK(!buffer.has_errors(), "{0}", helper.DiagnoseErrors()); } state.SetBytesProcessed(state.iterations() * source.size()); @@ -388,7 +389,7 @@ void BM_RandomSource(benchmark::State& state) { // Ensure that lexing actually occurs for benchmarking and that it doesn't // hit errors that would skew the benchmark results. - CARBON_CHECK(!buffer.has_errors()) << helper.DiagnoseErrors(); + CARBON_CHECK(!buffer.has_errors(), "{0}", helper.DiagnoseErrors()); } state.SetBytesProcessed(state.iterations() * source.size()); @@ -454,7 +455,7 @@ void BM_GroupingSymbols(benchmark::State& state) { // Ensure that lexing actually occurs for benchmarking and that it doesn't // hit errors that would skew the benchmark results. - CARBON_CHECK(!buffer.has_errors()) << helper.DiagnoseErrors(); + CARBON_CHECK(!buffer.has_errors(), "{0}", helper.DiagnoseErrors()); } state.SetBytesProcessed(state.iterations() * source.size()); @@ -504,7 +505,7 @@ void BM_BlankLines(benchmark::State& state) { // Ensure that lexing actually occurs for benchmarking and that it doesn't // hit errors that would skew the benchmark results. - CARBON_CHECK(!buffer.has_errors()) << helper.DiagnoseErrors(); + CARBON_CHECK(!buffer.has_errors(), "{0}", helper.DiagnoseErrors()); } state.SetBytesProcessed(state.iterations() * source.size()); @@ -539,7 +540,7 @@ void BM_CommentLines(benchmark::State& state) { // Ensure that lexing actually occurs for benchmarking and that it doesn't // hit errors that would skew the benchmark results. - CARBON_CHECK(!buffer.has_errors()) << helper.DiagnoseErrors(); + CARBON_CHECK(!buffer.has_errors(), "{0}", helper.DiagnoseErrors()); } state.SetBytesProcessed(state.iterations() * source.size()); diff --git a/toolchain/lex/tokenized_buffer_fuzzer.cpp b/toolchain/lex/tokenized_buffer_fuzzer.cpp index 56fa689a91a1..986b69e7a1bb 100644 --- a/toolchain/lex/tokenized_buffer_fuzzer.cpp +++ b/toolchain/lex/tokenized_buffer_fuzzer.cpp @@ -47,11 +47,11 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, // token stream. for (Lex::TokenIndex token : buffer.tokens()) { int line_number = buffer.GetLineNumber(token); - CARBON_CHECK(line_number > 0) << "Invalid line number!"; - CARBON_CHECK(line_number < INT_MAX) << "Invalid line number!"; + CARBON_CHECK(line_number > 0, "Invalid line number!"); + CARBON_CHECK(line_number < INT_MAX, "Invalid line number!"); int column_number = buffer.GetColumnNumber(token); - CARBON_CHECK(column_number > 0) << "Invalid line number!"; - CARBON_CHECK(column_number < INT_MAX) << "Invalid line number!"; + CARBON_CHECK(column_number > 0, "Invalid line number!"); + CARBON_CHECK(column_number < INT_MAX, "Invalid line number!"); } return 0; diff --git a/toolchain/lower/constant.cpp b/toolchain/lower/constant.cpp index 13376fe8cd5e..26238f2d7598 100644 --- a/toolchain/lower/constant.cpp +++ b/toolchain/lower/constant.cpp @@ -30,14 +30,15 @@ class ConstantContext { // Gets the lowered constant value for a constant that has already been // lowered. auto GetConstant(SemIR::ConstantId const_id) const -> llvm::Constant* { - CARBON_CHECK(const_id.is_template()) - << "Unexpected constant ID " << const_id; + CARBON_CHECK(const_id.is_template(), "Unexpected constant ID {0}", + const_id); auto inst_id = file_context_->sem_ir().constant_values().GetInstId(const_id); - CARBON_CHECK(inst_id.index >= 0 && - inst_id.index <= last_lowered_constant_index_) - << "Queried constant " << const_id << " with instruction " << inst_id - << " that has not been lowered yet"; + CARBON_CHECK( + inst_id.index >= 0 && inst_id.index <= last_lowered_constant_index_, + "Queried constant {0} with instruction {1} that has not been lowered " + "yet", + const_id, inst_id); return constants_[inst_id.index]; } @@ -109,7 +110,7 @@ template InstT::Kind.constant_kind() == SemIR::InstConstantKind::SymbolicOnly) static auto EmitAsConstant(ConstantContext& /*context*/, InstT inst) -> llvm::Constant* { - CARBON_FATAL() << "Unexpected constant instruction kind " << inst; + CARBON_FATAL("Unexpected constant instruction kind {0}", inst); } // For constants that are always of type `type`, produce the trivial runtime @@ -147,7 +148,7 @@ static auto EmitAsConstant(ConstantContext& /*context*/, SemIR::AddrOf /*inst*/) -> llvm::Constant* { // TODO: Constant lvalue support. For now we have no constant lvalues, so we // should never form a constant AddrOf. - CARBON_FATAL() << "AddrOf constants not supported yet"; + CARBON_FATAL("AddrOf constants not supported yet"); } static auto EmitAsConstant(ConstantContext& context, @@ -204,7 +205,7 @@ static auto EmitAsConstant(ConstantContext& context, SemIR::Namespace inst) static auto EmitAsConstant(ConstantContext& /*context*/, SemIR::StringLiteral inst) -> llvm::Constant* { - CARBON_FATAL() << "TODO: Add support: " << inst; + CARBON_FATAL("TODO: Add support: {0}", inst); } static auto EmitAsConstant(ConstantContext& /*context*/, diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index a4adbbb340f9..a78464fc8ca8 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -38,13 +38,13 @@ FileContext::FileContext(llvm::LLVMContext& llvm_context, sem_ir_(&sem_ir), inst_namer_(inst_namer), vlog_stream_(vlog_stream) { - CARBON_CHECK(!sem_ir.has_errors()) - << "Generating LLVM IR from invalid SemIR::File is unsupported."; + CARBON_CHECK(!sem_ir.has_errors(), + "Generating LLVM IR from invalid SemIR::File is unsupported."); } // TODO: Move this to lower.cpp. auto FileContext::Run() -> std::unique_ptr { - CARBON_CHECK(llvm_module_) << "Run can only be called once."; + CARBON_CHECK(llvm_module_, "Run can only be called once."); // Lower all types that were required to be complete. types_.resize(sem_ir_->insts().size()); @@ -157,8 +157,8 @@ auto FileContext::GetGlobal(SemIR::InstId inst_id) -> llvm::Value* { // TODO: For generics, handle references to symbolic constants. - CARBON_FATAL() << "Missing value: " << inst_id << " " - << sem_ir().insts().Get(inst_id); + CARBON_FATAL("Missing value: {0} {1}", inst_id, + sem_ir().insts().Get(inst_id)); } auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id) @@ -187,7 +187,7 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id) const auto return_info = SemIR::ReturnTypeInfo::ForFunction(sem_ir(), function, specific_id); - CARBON_CHECK(return_info.is_valid()) << "Should not lower invalid functions."; + CARBON_CHECK(return_info.is_valid(), "Should not lower invalid functions."); auto implicit_param_refs = sem_ir().inst_blocks().GetOrEmpty(function.implicit_param_refs_id); @@ -219,8 +219,7 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id) switch (auto value_rep = SemIR::ValueRepr::ForType(sem_ir(), param_type_id); value_rep.kind) { case SemIR::ValueRepr::Unknown: - CARBON_FATAL() - << "Incomplete parameter type lowering function declaration"; + CARBON_FATAL("Incomplete parameter type lowering function declaration"); case SemIR::ValueRepr::None: break; case SemIR::ValueRepr::Copy: @@ -364,8 +363,8 @@ auto FileContext::BuildDISubprogram(const SemIR::Function& function, return nullptr; } auto name = sem_ir().names().GetAsStringIfIdentifier(function.name_id); - CARBON_CHECK(name) << "Unexpected special name for function: " - << function.name_id; + CARBON_CHECK(name, "Unexpected special name for function: {0}", + function.name_id); auto loc = GetLocForDI(function.definition_id); // FIXME: Add more details here, including real subroutine type (once type // information is built), etc. @@ -390,7 +389,7 @@ static auto BuildTypeForInst(FileContext& context, SemIR::BuiltinInst inst) -> llvm::Type* { switch (inst.builtin_inst_kind) { case SemIR::BuiltinInstKind::Invalid: - CARBON_FATAL() << "Unexpected builtin type in lowering."; + CARBON_FATAL("Unexpected builtin type in lowering."); case SemIR::BuiltinInstKind::Error: // This is a complete type but uses of it should never be lowered. return nullptr; @@ -423,7 +422,7 @@ template requires(InstT::Kind.is_type() == SemIR::InstIsType::Never) static auto BuildTypeForInst(FileContext& /*context*/, InstT inst) -> llvm::Type* { - CARBON_FATAL() << "Cannot use inst as type: " << inst; + CARBON_FATAL("Cannot use inst as type: {0}", inst); } static auto BuildTypeForInst(FileContext& context, SemIR::ClassType inst) @@ -448,7 +447,7 @@ static auto BuildTypeForInst(FileContext& context, SemIR::IntType inst) -> llvm::Type* { auto width = context.sem_ir().insts().TryGetAs(inst.bit_width_id); - CARBON_CHECK(width) << "Can't lower int type with symbolic width"; + CARBON_CHECK(width, "Can't lower int type with symbolic width"); return llvm::IntegerType::get( context.llvm_context(), context.sem_ir().ints().Get(width->int_id).getZExtValue()); diff --git a/toolchain/lower/file_context.h b/toolchain/lower/file_context.h index 989a7ebfe154..644602ef4086 100644 --- a/toolchain/lower/file_context.h +++ b/toolchain/lower/file_context.h @@ -50,8 +50,8 @@ class FileContext { // Returns a lowered type for the given type_id. auto GetType(SemIR::TypeId type_id) -> llvm::Type* { // InvalidType should not be passed in. - CARBON_CHECK(type_id.index >= 0) << type_id; - CARBON_CHECK(types_[type_id.index]) << "Missing type " << type_id; + CARBON_CHECK(type_id.index >= 0, "{0}", type_id); + CARBON_CHECK(types_[type_id.index], "Missing type {0}", type_id); return types_[type_id.index]; } diff --git a/toolchain/lower/function_context.cpp b/toolchain/lower/function_context.cpp index 8cfa1f606096..3a9df72e6577 100644 --- a/toolchain/lower/function_context.cpp +++ b/toolchain/lower/function_context.cpp @@ -66,15 +66,14 @@ template static auto LowerInstHelper(FunctionContext& context, SemIR::InstId inst_id, InstT inst) { if constexpr (!InstT::Kind.is_lowered()) { - CARBON_FATAL() - << "Encountered an instruction that isn't expected to lower. It's " - "possible that logic needs to be changed in order to stop " - "showing this instruction in lowered contexts. Instruction: " - << inst; + CARBON_FATAL( + "Encountered an instruction that isn't expected to lower. It's " + "possible that logic needs to be changed in order to stop showing this " + "instruction in lowered contexts. Instruction: {0}", + inst); } else if constexpr (InstT::Kind.constant_kind() == SemIR::InstConstantKind::Always) { - CARBON_FATAL() << "Missing constant value for constant instruction " - << inst; + CARBON_FATAL("Missing constant value for constant instruction {0}", inst); } else if constexpr (InstT::Kind.is_type() == SemIR::InstIsType::Always) { // For instructions that are always of type `type`, produce the trivial // runtime representation of type `type`. @@ -99,9 +98,9 @@ auto FunctionContext::LowerInst(SemIR::InstId inst_id) -> void { builder_.getInserter().SetCurrentInstId(inst_id); if (di_subprogram_) { auto loc = file_context_->GetLocForDI(inst_id); - CARBON_CHECK(loc.filename == di_subprogram_->getFile()->getFilename()) - << "Instructions located in a different file from their enclosing " - "function aren't handled yet"; + CARBON_CHECK(loc.filename == di_subprogram_->getFile()->getFilename(), + "Instructions located in a different file from their " + "enclosing function aren't handled yet"); builder_.SetCurrentDebugLocation( llvm::DILocation::get(builder_.getContext(), loc.line_number, loc.column_number, di_subprogram_)); @@ -129,9 +128,9 @@ auto FunctionContext::GetBlockArg(SemIR::InstBlockId block_id, // Find the existing phi, if any. auto phis = block->phis(); if (!phis.empty()) { - CARBON_CHECK(std::next(phis.begin()) == phis.end()) - << "Expected at most one phi, found " - << std::distance(phis.begin(), phis.end()); + CARBON_CHECK(std::next(phis.begin()) == phis.end(), + "Expected at most one phi, found {0}", + std::distance(phis.begin(), phis.end())); return &*phis.begin(); } @@ -163,8 +162,8 @@ auto FunctionContext::FinishInit(SemIR::TypeId type_id, SemIR::InstId dest_id, CopyValue(type_id, source_id, dest_id); break; case SemIR::InitRepr::Incomplete: - CARBON_FATAL() << "Lowering aggregate initialization of incomplete type " - << sem_ir().types().GetAsInst(type_id); + CARBON_FATAL("Lowering aggregate initialization of incomplete type {0}", + sem_ir().types().GetAsInst(type_id)); } } @@ -172,7 +171,7 @@ auto FunctionContext::CopyValue(SemIR::TypeId type_id, SemIR::InstId source_id, SemIR::InstId dest_id) -> void { switch (auto rep = SemIR::ValueRepr::ForType(sem_ir(), type_id); rep.kind) { case SemIR::ValueRepr::Unknown: - CARBON_FATAL() << "Attempt to copy incomplete type"; + CARBON_FATAL("Attempt to copy incomplete type"); case SemIR::ValueRepr::None: break; case SemIR::ValueRepr::Copy: @@ -182,7 +181,7 @@ auto FunctionContext::CopyValue(SemIR::TypeId type_id, SemIR::InstId source_id, CopyObject(type_id, source_id, dest_id); break; case SemIR::ValueRepr::Custom: - CARBON_FATAL() << "TODO: Add support for CopyValue with custom value rep"; + CARBON_FATAL("TODO: Add support for CopyValue with custom value rep"); } } diff --git a/toolchain/lower/function_context.h b/toolchain/lower/function_context.h index 0440ec0ee45c..8bdd6d73bf49 100644 --- a/toolchain/lower/function_context.h +++ b/toolchain/lower/function_context.h @@ -63,8 +63,8 @@ class FunctionContext { // Sets the value for the given instruction. auto SetLocal(SemIR::InstId inst_id, llvm::Value* value) { bool added = locals_.Insert(inst_id, value).is_inserted(); - CARBON_CHECK(added) << "Duplicate local insert: " << inst_id << " " - << sem_ir().insts().Get(inst_id); + CARBON_CHECK(added, "Duplicate local insert: {0} {1}", inst_id, + sem_ir().insts().Get(inst_id)); } // Gets a callable's function. diff --git a/toolchain/lower/handle.cpp b/toolchain/lower/handle.cpp index f24cb6dcfcbb..f06ab81a3a5f 100644 --- a/toolchain/lower/handle.cpp +++ b/toolchain/lower/handle.cpp @@ -26,7 +26,7 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/, SemIR::AddrPattern /*inst*/) -> void { - CARBON_FATAL() << "`addr` should be lowered by `BuildFunctionDefinition`"; + CARBON_FATAL("`addr` should be lowered by `BuildFunctionDefinition`"); } auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, @@ -140,8 +140,8 @@ auto HandleInst(FunctionContext& context, SemIR::InstId /*inst_id*/, context.TryToReuseBlock(inst.target_id, block)) { // Reuse this block as the branch target. phi_predecessor = block->getSinglePredecessor(); - CARBON_CHECK(phi_predecessor) - << "Synthetic block did not have a single predecessor"; + CARBON_CHECK(phi_predecessor, + "Synthetic block did not have a single predecessor"); } else { context.builder().CreateBr(context.GetBlock(inst.target_id)); } @@ -184,7 +184,7 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/, SemIR::Param /*inst*/) -> void { - CARBON_FATAL() << "Parameters should be lowered by `BuildFunctionDefinition`"; + CARBON_FATAL("Parameters should be lowered by `BuildFunctionDefinition`"); } auto HandleInst(FunctionContext& context, SemIR::InstId /*inst_id*/, @@ -209,8 +209,8 @@ auto HandleInst(FunctionContext& context, SemIR::InstId /*inst_id*/, context.builder().CreateRet(context.GetValue(inst.expr_id)); return; case SemIR::InitRepr::Incomplete: - CARBON_FATAL() << "Lowering return of incomplete type " - << context.sem_ir().types().GetAsInst(result_type_id); + CARBON_FATAL("Lowering return of incomplete type {0}", + context.sem_ir().types().GetAsInst(result_type_id)); } } diff --git a/toolchain/lower/handle_aggregates.cpp b/toolchain/lower/handle_aggregates.cpp index 40fac01fa2e7..e8cb49448f16 100644 --- a/toolchain/lower/handle_aggregates.cpp +++ b/toolchain/lower/handle_aggregates.cpp @@ -34,16 +34,16 @@ static auto GetAggregateElement(FunctionContext& context, case SemIR::ExprCategory::NotExpr: case SemIR::ExprCategory::Initializing: case SemIR::ExprCategory::Mixed: - CARBON_FATAL() << "Unexpected expression category for aggregate access"; + CARBON_FATAL("Unexpected expression category for aggregate access"); case SemIR::ExprCategory::Value: { auto value_rep = SemIR::ValueRepr::ForType(context.sem_ir(), aggr_inst.type_id()); - CARBON_CHECK(value_rep.aggregate_kind != SemIR::ValueRepr::NotAggregate) - << "aggregate type should have aggregate value representation"; + CARBON_CHECK(value_rep.aggregate_kind != SemIR::ValueRepr::NotAggregate, + "aggregate type should have aggregate value representation"); switch (value_rep.kind) { case SemIR::ValueRepr::Unknown: - CARBON_FATAL() << "Lowering access to incomplete aggregate type"; + CARBON_FATAL("Lowering access to incomplete aggregate type"); case SemIR::ValueRepr::None: return aggr_value; case SemIR::ValueRepr::Copy: @@ -73,8 +73,8 @@ static auto GetAggregateElement(FunctionContext& context, context.GetType(result_value_type_id), elem_ptr, name + ".load"); } case SemIR::ValueRepr::Custom: - CARBON_FATAL() - << "Aggregate should never have custom value representation"; + CARBON_FATAL( + "Aggregate should never have custom value representation"); } } @@ -132,8 +132,9 @@ static auto EmitAggregateInitializer(FunctionContext& context, case SemIR::InitRepr::ByCopy: { auto refs = context.sem_ir().inst_blocks().Get(refs_id); - CARBON_CHECK(refs.size() == 1) - << "Unexpected size for aggregate with by-copy value representation"; + CARBON_CHECK( + refs.size() == 1, + "Unexpected size for aggregate with by-copy value representation"); // TODO: Remove the LLVM StructType wrapper in this case, so we don't // need this `insert_value` wrapping. return context.builder().CreateInsertValue( @@ -142,8 +143,8 @@ static auto EmitAggregateInitializer(FunctionContext& context, } case SemIR::InitRepr::Incomplete: - CARBON_FATAL() << "Lowering aggregate initialization of incomplete type " - << context.sem_ir().types().GetAsInst(type_id); + CARBON_FATAL("Lowering aggregate initialization of incomplete type {0}", + context.sem_ir().types().GetAsInst(type_id)); } } @@ -177,7 +178,7 @@ static auto EmitAggregateValueRepr(FunctionContext& context, auto value_rep = SemIR::ValueRepr::ForType(context.sem_ir(), type_id); switch (value_rep.kind) { case SemIR::ValueRepr::Unknown: - CARBON_FATAL() << "Incomplete aggregate type in lowering"; + CARBON_FATAL("Incomplete aggregate type in lowering"); case SemIR::ValueRepr::None: // TODO: Add a helper to get a "no value representation" value. @@ -185,8 +186,9 @@ static auto EmitAggregateValueRepr(FunctionContext& context, case SemIR::ValueRepr::Copy: { auto refs = context.sem_ir().inst_blocks().Get(refs_id); - CARBON_CHECK(refs.size() == 1) - << "Unexpected size for aggregate with by-copy value representation"; + CARBON_CHECK( + refs.size() == 1, + "Unexpected size for aggregate with by-copy value representation"); // TODO: Remove the LLVM StructType wrapper in this case, so we don't // need this `insert_value` wrapping. return context.builder().CreateInsertValue( @@ -211,8 +213,7 @@ static auto EmitAggregateValueRepr(FunctionContext& context, } case SemIR::ValueRepr::Custom: - CARBON_FATAL() - << "Aggregate should never have custom value representation"; + CARBON_FATAL("Aggregate should never have custom value representation"); } } diff --git a/toolchain/lower/handle_call.cpp b/toolchain/lower/handle_call.cpp index d3281f1186d8..ab5ca0c259db 100644 --- a/toolchain/lower/handle_call.cpp +++ b/toolchain/lower/handle_call.cpp @@ -30,7 +30,7 @@ static auto GetBuiltinICmpPredicate(SemIR::BuiltinFunctionKind builtin_kind, case SemIR::BuiltinFunctionKind::IntGreaterEq: return is_signed ? llvm::CmpInst::ICMP_SGE : llvm::CmpInst::ICMP_UGE; default: - CARBON_FATAL() << "Unexpected builtin kind " << builtin_kind; + CARBON_FATAL("Unexpected builtin kind {0}", builtin_kind); } } @@ -52,7 +52,7 @@ static auto GetBuiltinFCmpPredicate(SemIR::BuiltinFunctionKind builtin_kind) case SemIR::BuiltinFunctionKind::FloatGreaterEq: return llvm::CmpInst::FCMP_OGE; default: - CARBON_FATAL() << "Unexpected builtin kind " << builtin_kind; + CARBON_FATAL("Unexpected builtin kind {0}", builtin_kind); } } @@ -74,7 +74,7 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id, // TODO: Move the instruction names here into InstNamer. switch (builtin_kind) { case SemIR::BuiltinFunctionKind::None: - CARBON_FATAL() << "No callee in function call."; + CARBON_FATAL("No callee in function call."); case SemIR::BuiltinFunctionKind::PrintInt: { llvm::Type* char_type[] = {llvm::PointerType::get( @@ -287,7 +287,7 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id, } } - CARBON_FATAL() << "Unsupported builtin call."; + CARBON_FATAL("Unsupported builtin call."); } auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, diff --git a/toolchain/lower/handle_expr_category.cpp b/toolchain/lower/handle_expr_category.cpp index 7a6739229a6b..87f5ac3cb8e0 100644 --- a/toolchain/lower/handle_expr_category.cpp +++ b/toolchain/lower/handle_expr_category.cpp @@ -12,8 +12,8 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, switch (auto rep = SemIR::ValueRepr::ForType(context.sem_ir(), inst.type_id); rep.kind) { case SemIR::ValueRepr::Unknown: - CARBON_FATAL() - << "Value binding for type with incomplete value representation"; + CARBON_FATAL( + "Value binding for type with incomplete value representation"); case SemIR::ValueRepr::None: // Nothing should use this value, but StubRef needs a value to // propagate. @@ -30,7 +30,7 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, context.SetLocal(inst_id, context.GetValue(inst.value_id)); break; case SemIR::ValueRepr::Custom: - CARBON_FATAL() << "TODO: Add support for BindValue with custom value rep"; + CARBON_FATAL("TODO: Add support for BindValue with custom value rep"); } } diff --git a/toolchain/lower/mangler.cpp b/toolchain/lower/mangler.cpp index 29cdc5737a33..5288f8609327 100644 --- a/toolchain/lower/mangler.cpp +++ b/toolchain/lower/mangler.cpp @@ -62,7 +62,7 @@ auto Mangler::MangleInverseQualifiedNameScope(llvm::raw_ostream& os, break; } default: - CARBON_FATAL() << "Attempting to mangle unsupported SemIR."; + CARBON_FATAL("Attempting to mangle unsupported SemIR."); break; } // Skip the tail of the loop that adds the parent name scope to the @@ -86,7 +86,7 @@ auto Mangler::MangleInverseQualifiedNameScope(llvm::raw_ostream& os, break; } default: - CARBON_FATAL() << "Attempting to mangle unsupported SemIR."; + CARBON_FATAL("Attempting to mangle unsupported SemIR."); break; } names_to_render.push_back( diff --git a/toolchain/parse/context.cpp b/toolchain/parse/context.cpp index 661c6153c7fb..3d9a557353a8 100644 --- a/toolchain/parse/context.cpp +++ b/toolchain/parse/context.cpp @@ -59,11 +59,11 @@ Context::Context(Tree& tree, Lex::TokenizedBuffer& tokens, vlog_stream_(vlog_stream), position_(tokens_->tokens().begin()), end_(tokens_->tokens().end()) { - CARBON_CHECK(position_ != end_) << "Empty TokenizedBuffer"; + CARBON_CHECK(position_ != end_, "Empty TokenizedBuffer"); --end_; - CARBON_CHECK(tokens_->GetKind(*end_) == Lex::TokenKind::FileEnd) - << "TokenizedBuffer should end with FileEnd, ended with " - << tokens_->GetKind(*end_); + CARBON_CHECK(tokens_->GetKind(*end_) == Lex::TokenKind::FileEnd, + "TokenizedBuffer should end with FileEnd, ended with {0}", + tokens_->GetKind(*end_)); } auto Context::AddLeafNode(NodeKind kind, Lex::TokenIndex token, bool has_error) @@ -79,8 +79,8 @@ auto Context::AddNode(NodeKind kind, Lex::TokenIndex token, bool has_error) auto Context::ReplacePlaceholderNode(int32_t position, NodeKind kind, Lex::TokenIndex token, bool has_error) -> void { - CARBON_CHECK(position >= 0 && position < tree_->size()) - << "position: " << position << " size: " << tree_->size(); + CARBON_CHECK(position >= 0 && position < tree_->size(), + "position: {0} size: {1}", position, tree_->size()); auto* node_impl = &tree_->node_impls_[position]; CARBON_CHECK(node_impl->kind == NodeKind::Placeholder); node_impl->kind = kind; @@ -138,8 +138,8 @@ auto Context::ConsumeAndAddLeafNodeIf(Lex::TokenKind token_kind, } auto Context::ConsumeChecked(Lex::TokenKind kind) -> Lex::TokenIndex { - CARBON_CHECK(PositionIs(kind)) - << "Required " << kind << ", found " << PositionKind(); + CARBON_CHECK(PositionIs(kind), "Required {0}, found {1}", kind, + PositionKind()); return Consume(); } @@ -230,10 +230,10 @@ auto Context::SkipPastLikelyEnd(Lex::TokenIndex skip_root) -> Lex::TokenIndex { } auto Context::SkipTo(Lex::TokenIndex t) -> void { - CARBON_CHECK(t >= *position_) << "Tried to skip backwards from " << position_ - << " to " << Lex::TokenIterator(t); + CARBON_CHECK(t >= *position_, "Tried to skip backwards from {0} to {1}", + position_, Lex::TokenIterator(t)); position_ = Lex::TokenIterator(t); - CARBON_CHECK(position_ != end_) << "Skipped past EOF."; + CARBON_CHECK(position_ != end_, "Skipped past EOF."); } // Determines whether the given token is considered to be the start of an @@ -265,7 +265,7 @@ static auto IsPossibleStartOfOperand(Lex::TokenKind kind) -> bool { } auto Context::IsLexicallyValidInfixOperator() -> bool { - CARBON_CHECK(position_ != end_) << "Expected an operator token."; + CARBON_CHECK(position_ != end_, "Expected an operator token."); bool leading_space = tokens().HasLeadingWhitespace(*position_); bool trailing_space = tokens().HasTrailingWhitespace(*position_); @@ -371,9 +371,8 @@ auto Context::ConsumeListToken(NodeKind comma_kind, Lex::TokenKind close_kind, // Recover from the invalid token. auto end_of_element = FindNextOf({Lex::TokenKind::Comma, close_kind}); // The lexer guarantees that parentheses are balanced. - CARBON_CHECK(end_of_element) - << "missing matching `" << close_kind.opening_symbol() << "` for `" - << close_kind << "`"; + CARBON_CHECK(end_of_element, "missing matching `{0}` for `{1}`", + close_kind.opening_symbol(), close_kind); SkipTo(*end_of_element); } diff --git a/toolchain/parse/context.h b/toolchain/parse/context.h index fe71bfc5b907..a8ae5b09b329 100644 --- a/toolchain/parse/context.h +++ b/toolchain/parse/context.h @@ -267,8 +267,8 @@ class Context { auto PushState(StateStackEntry state) -> void { CARBON_VLOG("Push {0}: {1}\n", state_stack_.size(), state); state_stack_.push_back(state); - CARBON_CHECK(state_stack_.size() < (1 << 20)) - << "Excessive stack size: likely infinite loop"; + CARBON_CHECK(state_stack_.size() < (1 << 20), + "Excessive stack size: likely infinite loop"); } // Pushes a constructed state onto the stack, with a different parse state. diff --git a/toolchain/parse/handle_expr.cpp b/toolchain/parse/handle_expr.cpp index 7e7068e90377..91b53c658dd0 100644 --- a/toolchain/parse/handle_expr.cpp +++ b/toolchain/parse/handle_expr.cpp @@ -350,8 +350,8 @@ auto HandleExprLoop(Context& context) -> void { #include "toolchain/parse/node_kind.def" default: - CARBON_FATAL() << "Unexpected token kind for postfix operator: " - << operator_kind; + CARBON_FATAL("Unexpected token kind for postfix operator: {0}", + operator_kind); } context.AddNode(node_kind, state.token, state.has_error); @@ -381,8 +381,7 @@ auto HandleExprLoopForInfixOperator(Context& context) -> void { #include "toolchain/parse/node_kind.def" default: - CARBON_FATAL() << "Unexpected token kind for infix operator: " - << token_kind; + CARBON_FATAL("Unexpected token kind for infix operator: {0}", token_kind); } } @@ -398,8 +397,8 @@ auto HandleExprLoopForPrefixOperator(Context& context) -> void { #include "toolchain/parse/node_kind.def" default: - CARBON_FATAL() << "Unexpected token kind for prefix operator: " - << token_kind; + CARBON_FATAL("Unexpected token kind for prefix operator: {0}", + token_kind); } } diff --git a/toolchain/parse/handle_paren_expr.cpp b/toolchain/parse/handle_paren_expr.cpp index e54510c1a18f..888027c5bcb2 100644 --- a/toolchain/parse/handle_paren_expr.cpp +++ b/toolchain/parse/handle_paren_expr.cpp @@ -71,8 +71,8 @@ auto HandleExprAfterOpenParenFinish(Context& context) -> void { // We found a comma, so switch parent state to tuple handling. auto finish_state = context.PopState(); - CARBON_CHECK(finish_state.state == State::ParenExprFinish) - << "Unexpected parent state, found: " << finish_state.state; + CARBON_CHECK(finish_state.state == State::ParenExprFinish, + "Unexpected parent state, found: {0}", finish_state.state); context.PushState(finish_state, State::TupleLiteralFinish); // If the comma is not immediately followed by a close paren, push handlers diff --git a/toolchain/parse/handle_requirement.cpp b/toolchain/parse/handle_requirement.cpp index 086500697e3a..394bba49a0b9 100644 --- a/toolchain/parse/handle_requirement.cpp +++ b/toolchain/parse/handle_requirement.cpp @@ -88,8 +88,8 @@ auto HandleRequirementOperatorFinish(Context& context) -> void { // RequirementOperatorFinish state is only pushed in // HandleRequirementOperator on one of the three requirement operator // tokens. - CARBON_FATAL() << "Unexpected token kind for requirement operator: " - << token_kind; + CARBON_FATAL("Unexpected token kind for requirement operator: {0}", + token_kind); return; } if (state.has_error) { diff --git a/toolchain/parse/node_kind.h b/toolchain/parse/node_kind.h index 0630def4344e..8dccf7e9c5d3 100644 --- a/toolchain/parse/node_kind.h +++ b/toolchain/parse/node_kind.h @@ -171,7 +171,7 @@ class NodeKind::Definition : public NodeKind { // Returns the bracketing node kind for the current node kind. Requires that // has_bracket is true. constexpr auto bracket() const -> NodeKind { - CARBON_CHECK(has_bracket()) << *this; + CARBON_CHECK(has_bracket(), "{0}", *this); return bracket_; } @@ -181,7 +181,7 @@ class NodeKind::Definition : public NodeKind { // Returns the number of children that the node must have, often 0. Requires // that has_child_count is true. constexpr auto child_count() const -> int32_t { - CARBON_CHECK(has_child_count()) << *this; + CARBON_CHECK(has_child_count(), "{0}", *this); return child_count_; } @@ -194,8 +194,7 @@ class NodeKind::Definition : public NodeKind { // This is factored out and non-constexpr to improve the compile-time error // message if the check below fails. auto MustSpecifyEitherBracketingNodeOrChildCount() { - CARBON_FATAL() - << "Must specify either bracketing node or fixed child count."; + CARBON_FATAL("Must specify either bracketing node or fixed child count."); } constexpr explicit Definition(NodeKind kind, DefinitionArgs args) diff --git a/toolchain/parse/parse.cpp b/toolchain/parse/parse.cpp index df13a0890e64..d6c5642032cc 100644 --- a/toolchain/parse/parse.cpp +++ b/toolchain/parse/parse.cpp @@ -13,8 +13,8 @@ namespace Carbon::Parse { auto HandleInvalid(Context& context) -> void { - CARBON_FATAL() << "The Invalid state shouldn't be on the stack: " - << context.PopState(); + CARBON_FATAL("The Invalid state shouldn't be on the stack: {0}", + context.PopState()); } auto Parse(Lex::TokenizedBuffer& tokens, DiagnosticConsumer& consumer, @@ -55,7 +55,7 @@ auto Parse(Lex::TokenizedBuffer& tokens, DiagnosticConsumer& consumer, // hopefully comfortable copy-pasting stderr when there are bugs in tree // construction. tree.Print(llvm::errs()); - CARBON_FATAL() << "Invalid tree returned by Parse(): " << verify.error(); + CARBON_FATAL("Invalid tree returned by Parse(): {0}", verify.error()); } return tree; } diff --git a/toolchain/parse/precedence.cpp b/toolchain/parse/precedence.cpp index ba280b5d42aa..bc68a3500c8c 100644 --- a/toolchain/parse/precedence.cpp +++ b/toolchain/parse/precedence.cpp @@ -126,8 +126,8 @@ struct OperatorPriorityTable { for (int8_t a = 0; a != NumPrecedenceLevels; ++a) { for (int8_t b = 0; b != NumPrecedenceLevels; ++b) { if (table[a][b] == OperatorPriority::LeftFirst) { - CARBON_CHECK(table[b][a] != OperatorPriority::LeftFirst) - << "inconsistent lookup table entries"; + CARBON_CHECK(table[b][a] != OperatorPriority::LeftFirst, + "inconsistent lookup table entries"); table[b][a] = OperatorPriority::RightFirst; } } @@ -163,13 +163,13 @@ struct OperatorPriorityTable { for (int8_t level = 0; level != NumPrecedenceLevels; ++level) { if (level != Highest) { CARBON_CHECK(table[Highest][level] == OperatorPriority::LeftFirst && - table[level][Highest] == OperatorPriority::RightFirst) - << "Highest is not highest priority"; + table[level][Highest] == OperatorPriority::RightFirst, + "Highest is not highest priority"); } if (level != Lowest) { CARBON_CHECK(table[Lowest][level] == OperatorPriority::RightFirst && - table[level][Lowest] == OperatorPriority::LeftFirst) - << "Lowest is not lowest priority"; + table[level][Lowest] == OperatorPriority::LeftFirst, + "Lowest is not lowest priority"); } } } diff --git a/toolchain/parse/tree_and_subtrees.cpp b/toolchain/parse/tree_and_subtrees.cpp index 4f1d0a47150a..4f75b3d1e540 100644 --- a/toolchain/parse/tree_and_subtrees.cpp +++ b/toolchain/parse/tree_and_subtrees.cpp @@ -19,25 +19,26 @@ TreeAndSubtrees::TreeAndSubtrees(const Lex::TokenizedBuffer& tokens, auto kind = tree.node_kind(n); if (kind.has_child_count()) { // When the child count is set, remove the specific number from the stack. - CARBON_CHECK(static_cast(size_stack.size()) >= - kind.child_count()) - << "Need " << kind.child_count() << " children for " << kind - << ", have " << size_stack.size() << " available"; + CARBON_CHECK( + static_cast(size_stack.size()) >= kind.child_count(), + "Need {0} children for {1}, have {2} available", kind.child_count(), + kind, size_stack.size()); for (auto i : llvm::seq(kind.child_count())) { auto child = size_stack.pop_back_val(); CARBON_CHECK((size_t)child.index < subtree_sizes_.size()); size += subtree_sizes_[child.index]; if (kind.has_bracket() && i == kind.child_count() - 1) { - CARBON_CHECK(kind.bracket() == tree.node_kind(child)) - << "Node " << kind << " with child count " << kind.child_count() - << " needs bracket " << kind.bracket() << ", found wrong bracket " - << tree.node_kind(child); + CARBON_CHECK(kind.bracket() == tree.node_kind(child), + "Node {0} with child count {1} needs bracket {2}, found " + "wrong bracket {3}", + kind, kind.child_count(), kind.bracket(), + tree.node_kind(child)); } } } else { while (true) { - CARBON_CHECK(!size_stack.empty()) - << "Node " << kind << " is missing bracket " << kind.bracket(); + CARBON_CHECK(!size_stack.empty(), "Node {0} is missing bracket {1}", + kind, kind.bracket()); auto child = size_stack.pop_back_val(); size += subtree_sizes_[child.index]; if (kind.bracket() == tree.node_kind(child)) { @@ -52,15 +53,15 @@ TreeAndSubtrees::TreeAndSubtrees(const Lex::TokenizedBuffer& tokens, CARBON_CHECK(static_cast(subtree_sizes_.size()) == tree_->size()); // Remaining nodes should all be roots in the tree; make sure they line up. - CARBON_CHECK(size_stack.back().index == - static_cast(tree_->size()) - 1) - << size_stack.back() << " " << tree_->size() - 1; + CARBON_CHECK( + size_stack.back().index == static_cast(tree_->size()) - 1, + "{0} {1}", size_stack.back(), tree_->size() - 1); int prev_index = -1; for (const auto& n : size_stack) { - CARBON_CHECK(n.index - subtree_sizes_[n.index] == prev_index) - << "NodeId " << n << " is a root " << tree_->node_kind(n) - << " with subtree_size " << subtree_sizes_[n.index] - << ", but previous root was at " << prev_index << "."; + CARBON_CHECK(n.index - subtree_sizes_[n.index] == prev_index, + "NodeId {0} is a root {1} with subtree_size {2}, but previous " + "root was at {3}.", + n, tree_->node_kind(n), subtree_sizes_[n.index], prev_index); prev_index = n.index; } } @@ -219,7 +220,7 @@ auto TreeAndSubtrees::PrintPreorder(llvm::raw_ostream& output) const -> void { } int next_depth = node_stack.empty() ? 0 : node_stack.back().second; - CARBON_CHECK(next_depth <= depth) << "Cannot have the next depth increase!"; + CARBON_CHECK(next_depth <= depth, "Cannot have the next depth increase!"); for (int close_children_count : llvm::seq(0, depth - next_depth)) { (void)close_children_count; output << "]}"; diff --git a/toolchain/parse/tree_and_subtrees.h b/toolchain/parse/tree_and_subtrees.h index 783991e0477c..39954138b56d 100644 --- a/toolchain/parse/tree_and_subtrees.h +++ b/toolchain/parse/tree_and_subtrees.h @@ -230,8 +230,8 @@ auto TreeAndSubtrees::ExtractNodeFromChildren( // On error try again, this time capturing a trace. ErrorBuilder trace; TryExtractNodeFromChildren(node_id, children, &trace); - CARBON_FATAL() << "Malformed parse node:\n" - << static_cast(trace).message(); + CARBON_FATAL("Malformed parse node:\n{0}", + static_cast(trace).message()); } return *result; } diff --git a/toolchain/sem_ir/block_value_store.h b/toolchain/sem_ir/block_value_store.h index 9e17280d9ed5..1e865913b1f2 100644 --- a/toolchain/sem_ir/block_value_store.h +++ b/toolchain/sem_ir/block_value_store.h @@ -103,8 +103,8 @@ class BlockValueStore : public Yaml::Printable> { // Sets the contents of an empty block to the given content. auto SetContent(IdT block_id, llvm::ArrayRef content) -> void { - CARBON_CHECK(Get(block_id).empty()) - << "inst block content set more than once"; + CARBON_CHECK(Get(block_id).empty(), + "inst block content set more than once"); values_.Get(block_id) = AllocateCopy(content); } diff --git a/toolchain/sem_ir/constant.cpp b/toolchain/sem_ir/constant.cpp index 4a68947ec28c..bbd59544546c 100644 --- a/toolchain/sem_ir/constant.cpp +++ b/toolchain/sem_ir/constant.cpp @@ -29,9 +29,9 @@ auto ConstantStore::GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId { return const_id; }); CARBON_CHECK(result.value() != ConstantId::Invalid); - CARBON_CHECK(result.value().is_symbolic() == is_symbolic) - << "Constant " << inst - << " registered as both symbolic and template constant."; + CARBON_CHECK( + result.value().is_symbolic() == is_symbolic, + "Constant {0} registered as both symbolic and template constant.", inst); return result.value(); } diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 4bbd99ebcfee..073876808d7a 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -49,9 +49,9 @@ File::File(CheckIRId check_ir_id, IdentifierId package_id, : TypeId::TypeType, \ .builtin_inst_kind = BuiltinInstKind::Name})); #include "toolchain/sem_ir/builtin_inst_kind.def" - CARBON_CHECK(insts_.size() == BuiltinInstKind::ValidCount) - << "Builtins should produce " << BuiltinInstKind::ValidCount - << " insts, actual: " << insts_.size(); + CARBON_CHECK(insts_.size() == BuiltinInstKind::ValidCount, + "Builtins should produce {0} insts, actual: {1}", + BuiltinInstKind::ValidCount, insts_.size()); for (auto i : llvm::seq(BuiltinInstKind::ValidCount)) { auto builtin_id = SemIR::InstId(i); constant_values_.Set(builtin_id, @@ -176,8 +176,8 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const // precedence of that type's syntax. Higher numbers correspond to higher // precedence. static auto GetTypePrecedence(InstKind kind) -> int { - CARBON_CHECK(kind.is_type() != InstIsType::Never) - << "Only called for kinds which can define a type."; + CARBON_CHECK(kind.is_type() != InstIsType::Never, + "Only called for kinds which can define a type."); if (kind == ConstType::Kind) { return -1; } diff --git a/toolchain/sem_ir/generic.cpp b/toolchain/sem_ir/generic.cpp index 96860521be82..c86e8d8ef5c3 100644 --- a/toolchain/sem_ir/generic.cpp +++ b/toolchain/sem_ir/generic.cpp @@ -81,10 +81,11 @@ auto GetConstantInSpecific(const File& sem_ir, SpecificId specific_id, } auto value_block_id = specific.GetValueBlock(symbolic.index.region()); - CARBON_CHECK(value_block_id.is_valid()) - << "Queried " << symbolic.index << " in " << specific_id << " for " - << sem_ir.insts().Get(sem_ir.generics().Get(specific.generic_id).decl_id) - << " before it was resolved."; + CARBON_CHECK( + value_block_id.is_valid(), + "Queried {0} in {1} for {2} before it was resolved.", symbolic.index, + specific_id, + sem_ir.insts().Get(sem_ir.generics().Get(specific.generic_id).decl_id)); return sem_ir.constant_values().Get( sem_ir.inst_blocks().Get(value_block_id)[symbolic.index.index()]); } diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index daf0405e8127..95f345c63b38 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -426,8 +426,8 @@ struct BoolValue : public IdBase, public Printable { // Returns the `bool` corresponding to this `BoolValue`. constexpr auto ToBool() -> bool { - CARBON_CHECK(*this == False || *this == True) - << "Invalid bool value " << index; + CARBON_CHECK(*this == False || *this == True, "Invalid bool value {0}", + index); return *this != False; } @@ -438,7 +438,7 @@ struct BoolValue : public IdBase, public Printable { } else if (*this == True) { out << "true"; } else { - CARBON_FATAL() << "Invalid bool value " << index; + CARBON_FATAL("Invalid bool value {0}", index); } } }; @@ -465,7 +465,7 @@ struct IntKind : public IdBase, public Printable { } else if (*this == Signed) { out << "signed"; } else { - CARBON_FATAL() << "Invalid int kind value " << index; + CARBON_FATAL("Invalid int kind value {0}", index); } } }; @@ -510,7 +510,7 @@ struct NameId : public IdBase, public Printable { } else if (!id.is_valid()) { return NameId::Invalid; } else { - CARBON_FATAL() << "Unexpected identifier ID " << id; + CARBON_FATAL("Unexpected identifier ID {0}", id); } } @@ -535,7 +535,7 @@ struct NameId : public IdBase, public Printable { } else if (*this == Base) { out << "Base"; } else { - CARBON_CHECK(!is_valid() || index >= 0) << "Unknown index " << index; + CARBON_CHECK(!is_valid() || index >= 0, "Unknown index {0}", index); IdBase::Print(out); } } @@ -710,8 +710,8 @@ struct LibraryNameId : public IdBase, public Printable { // Returns the LibraryNameId for a library name as a string literal. static auto ForStringLiteralValueId(StringLiteralValueId id) -> LibraryNameId { - CARBON_CHECK(id.index >= InvalidIndex) - << "Unexpected library name ID " << id; + CARBON_CHECK(id.index >= InvalidIndex, "Unexpected library name ID {0}", + id); if (id == StringLiteralValueId::Invalid) { // Prior to SemIR, we use invalid to indicate `default`. return LibraryNameId::Default; @@ -724,7 +724,7 @@ struct LibraryNameId : public IdBase, public Printable { // Converts a LibraryNameId back to a string literal. auto AsStringLiteralValueId() const -> StringLiteralValueId { - CARBON_CHECK(index >= InvalidIndex) << *this << " must be handled directly"; + CARBON_CHECK(index >= InvalidIndex, "{0} must be handled directly", *this); return StringLiteralValueId(index); } diff --git a/toolchain/sem_ir/inst.h b/toolchain/sem_ir/inst.h index e929b86930d7..748b53234e70 100644 --- a/toolchain/sem_ir/inst.h +++ b/toolchain/sem_ir/inst.h @@ -164,8 +164,8 @@ class Inst : public Printable { requires Internal::InstLikeType auto As() const -> TypedInst { using Info = Internal::InstLikeTypeInfo; - CARBON_CHECK(Is()) << "Casting inst of kind " << kind() - << " to wrong kind " << Info::DebugName(); + CARBON_CHECK(Is(), "Casting inst of kind {0} to wrong kind {1}", + kind(), Info::DebugName()); auto build_with_type_id_onwards = [&](auto... type_id_onwards) { if constexpr (Internal::HasKindMemberAsField) { return TypedInst{kind(), type_id_onwards...}; @@ -393,9 +393,9 @@ class InstStore { } auto GetLocId(InstId inst_id) const -> LocId { - CARBON_CHECK(inst_id.index >= 0) << inst_id.index; - CARBON_CHECK(inst_id.index < (int)loc_ids_.size()) - << inst_id.index << " " << loc_ids_.size(); + CARBON_CHECK(inst_id.index >= 0, "{0}", inst_id.index); + CARBON_CHECK(inst_id.index < (int)loc_ids_.size(), "{0} {1}", inst_id.index, + loc_ids_.size()); return loc_ids_[inst_id.index]; } diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index 3cbad8dc635d..022ab102d670 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -206,7 +206,7 @@ auto InstNamer::GetLabelFor(ScopeId scope_id, InstBlockId block_id) const auto InstNamer::Namespace::Name::str() const -> llvm::StringRef { llvm::StringMapEntry* value = value_; - CARBON_CHECK(value) << "cannot print a null name"; + CARBON_CHECK(value, "cannot print a null name"); while (value->second.ambiguous && value->second.fallback) { value = value->second.fallback.value_; } diff --git a/toolchain/sem_ir/name.cpp b/toolchain/sem_ir/name.cpp index 05b0b9af1eaa..088580021367 100644 --- a/toolchain/sem_ir/name.cpp +++ b/toolchain/sem_ir/name.cpp @@ -24,7 +24,7 @@ static auto GetSpecialName(NameId name_id, bool for_ir) -> llvm::StringRef { case NameId::Base.index: return "base"; default: - CARBON_FATAL() << "Unknown special name"; + CARBON_FATAL("Unknown special name"); } } diff --git a/toolchain/sem_ir/name_scope.h b/toolchain/sem_ir/name_scope.h index 4401cd9a0144..a8d4b8c34f4b 100644 --- a/toolchain/sem_ir/name_scope.h +++ b/toolchain/sem_ir/name_scope.h @@ -54,8 +54,8 @@ struct NameScope : Printable { return index; }; auto result = name_map.Insert(name_entry.name_id, add_name); - CARBON_CHECK(result.is_inserted()) - << "Failed to add required name: " << name_entry.name_id; + CARBON_CHECK(result.is_inserted(), "Failed to add required name: {0}", + name_entry.name_id); } // Names in the scope. We store both an insertion-ordered vector for iterating diff --git a/toolchain/sem_ir/type.h b/toolchain/sem_ir/type.h index 183ef6b36097..69f199c801c9 100644 --- a/toolchain/sem_ir/type.h +++ b/toolchain/sem_ir/type.h @@ -86,8 +86,8 @@ class TypeStore : public Yaml::Printable { CARBON_CHECK(value_repr.kind != ValueRepr::Unknown); auto insert_info = complete_type_info_.Insert(type_id, {.value_repr = value_repr}); - CARBON_CHECK(insert_info.is_inserted()) - << "Type " << type_id << " completed more than once"; + CARBON_CHECK(insert_info.is_inserted(), "Type {0} completed more than once", + type_id); complete_types_.push_back(type_id); CARBON_CHECK(IsComplete(type_id)); } diff --git a/toolchain/testing/file_test.cpp b/toolchain/testing/file_test.cpp index 55cd36e4fccc..3fd54476f1e0 100644 --- a/toolchain/testing/file_test.cpp +++ b/toolchain/testing/file_test.cpp @@ -71,8 +71,8 @@ class ToolchainFileTest : public FileTestBase { } else if (component_ == "lower") { args.push_back("--dump-llvm-ir"); } else { - CARBON_FATAL() << "Unexpected test component " << component_ << ": " - << test_name(); + CARBON_FATAL("Unexpected test component {0}: {1}", component_, + test_name()); } // For `lex` and `parse`, we don't need to import the prelude; exclude it to @@ -150,7 +150,7 @@ class ToolchainFileTest : public FileTestBase { // This handles cases where the toolchain directory may be copied into a // repository that doesn't put it at the root. auto pos = test_name.find("toolchain/"); - CARBON_CHECK(pos != llvm::StringRef::npos) << test_name; + CARBON_CHECK(pos != llvm::StringRef::npos, "{0}", test_name); test_name = test_name.drop_front(pos + strlen("toolchain/")); test_name = test_name.take_front(test_name.find("/")); return test_name;