From 4c4c4a4d2cc238fdf97e4bb4cc000dedbf58ed29 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 17 Jan 2025 17:11:44 -0800 Subject: [PATCH] Add RawStringOstream for slightly simpler streaming to strings (#4817) This adds a RawStringOstream. Versus TestRawOstream, which is consolidated over to RawStringOstream, it uses a string for storage instead of a vector, mainly to support move-to-string semantics. Versus llvm::raw_string_ostream, it owns the string and supports pwrite (which is needed for driver and its fd_ostream compatibility requirement). This converts most uses of llvm::raw_string_ostream, leaving behind a few in InstNamer that explicitly cannot own the string, such as: ``` llvm::raw_string_ostream(name) << "_" << tree.tokens().GetColumnNumber(token); ``` I have this as its own library so that it can use CHECK. Yes this doesn't save much code, but it's code we repeatedly write. --------- Co-authored-by: Geoff Romer --- common/BUILD | 34 ++++++++-- common/command_line.cpp | 36 +++++------ common/command_line_test.cpp | 25 ++++---- common/enum_base_test.cpp | 4 +- common/error.h | 14 ++-- common/error_test.cpp | 4 +- common/hashing_test.cpp | 12 ++-- common/raw_string_ostream.h | 64 +++++++++++++++++++ .../raw_string_ostream_test.cpp | 28 +++++--- common/vlog_test.cpp | 6 +- explorer/BUILD | 2 +- explorer/base/BUILD | 2 +- explorer/base/error_builders_test.cpp | 4 +- explorer/file_test.cpp | 4 +- testing/base/BUILD | 23 +------ testing/base/source_gen.cpp | 28 ++++---- testing/base/test_raw_ostream.h | 42 ------------ testing/file_test/BUILD | 2 + testing/file_test/autoupdate.cpp | 5 +- testing/file_test/file_test_base.cpp | 6 +- toolchain/base/BUILD | 6 +- toolchain/base/shared_value_stores_test.cpp | 6 +- toolchain/check/BUILD | 2 + toolchain/check/import_cpp.cpp | 8 +-- .../check/sem_ir_diagnostic_converter.cpp | 13 ++-- toolchain/driver/BUILD | 10 ++- toolchain/driver/clang_runner_test.cpp | 21 +++--- toolchain/driver/driver_fuzzer.cpp | 4 +- toolchain/driver/driver_test.cpp | 7 +- toolchain/driver/format_subcommand.cpp | 8 +-- toolchain/language_server/BUILD | 1 + toolchain/language_server/language_server.cpp | 6 +- toolchain/lex/BUILD | 3 +- toolchain/lex/tokenized_buffer_benchmark.cpp | 24 +++---- toolchain/lex/tokenized_buffer_test.cpp | 34 +++++----- toolchain/lower/BUILD | 1 + toolchain/lower/mangler.cpp | 6 +- toolchain/parse/BUILD | 2 +- toolchain/parse/tree_test.cpp | 7 +- toolchain/sem_ir/BUILD | 6 +- toolchain/sem_ir/inst.h | 6 +- toolchain/sem_ir/inst_namer.cpp | 44 ++++++------- toolchain/sem_ir/stringify_type.cpp | 6 +- toolchain/sem_ir/type_info.cpp | 6 +- toolchain/sem_ir/yaml_test.cpp | 5 +- toolchain/testing/BUILD | 1 + toolchain/testing/yaml_test_helpers.cpp | 5 +- 47 files changed, 318 insertions(+), 275 deletions(-) create mode 100644 common/raw_string_ostream.h rename testing/base/test_raw_ostream_test.cpp => common/raw_string_ostream_test.cpp (67%) delete mode 100644 testing/base/test_raw_ostream.h diff --git a/common/BUILD b/common/BUILD index 0a4474e77e52..7b8c620660d9 100644 --- a/common/BUILD +++ b/common/BUILD @@ -43,6 +43,7 @@ cc_library( ":check", ":error", ":ostream", + ":raw_string_ostream", "@llvm-project//llvm:Support", ], ) @@ -54,8 +55,8 @@ cc_test( deps = [ ":command_line", ":error_test_helpers", + ":raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", "@llvm-project//llvm:Support", ], @@ -108,8 +109,8 @@ cc_test( deps = [ ":enum_base", ":enum_base_test_def", + ":raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", ], ) @@ -120,6 +121,7 @@ cc_library( deps = [ ":check", ":ostream", + ":raw_string_ostream", "@llvm-project//llvm:Support", ], ) @@ -141,8 +143,8 @@ cc_test( deps = [ ":error", ":error_test_helpers", + ":raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", ], ) @@ -185,8 +187,8 @@ cc_test( srcs = ["hashing_test.cpp"], deps = [ ":hashing", + ":raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", "@llvm-project//llvm:Support", ], @@ -289,7 +291,6 @@ cc_test( ":map", ":raw_hashtable_test_helpers", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", ], ) @@ -411,6 +412,26 @@ cc_library( ], ) +cc_library( + name = "raw_string_ostream", + hdrs = ["raw_string_ostream.h"], + deps = [ + ":check", + ":ostream", + ], +) + +cc_test( + name = "raw_string_ostream_test", + size = "small", + srcs = ["raw_string_ostream_test.cpp"], + deps = [ + ":raw_string_ostream", + "//testing/base:gtest_main", + "@googletest//:gtest", + ], +) + cc_library( name = "set", hdrs = ["set.h"], @@ -430,7 +451,6 @@ cc_test( ":raw_hashtable_test_helpers", ":set", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", ], ) @@ -616,9 +636,9 @@ cc_test( size = "small", srcs = ["vlog_test.cpp"], deps = [ + ":raw_string_ostream", ":vlog", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", ], ) diff --git a/common/command_line.cpp b/common/command_line.cpp index 0c043c15c406..ce8f07e1b7af 100644 --- a/common/command_line.cpp +++ b/common/command_line.cpp @@ -6,6 +6,7 @@ #include +#include "common/raw_string_ostream.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/FormatVariadic.h" @@ -550,12 +551,11 @@ void MetaPrinter::PrintRawUsageCommandAndOptions(const Command& command, *out_ << command.info.name; // Buffer the options rendering so we can limit its length. - std::string buffer_str; - llvm::raw_string_ostream buffer_out(buffer_str); + RawStringOstream buffer_out; MetaPrinter buffer_printer(&buffer_out); bool have_short_flags = false; for (const auto& arg : command.options) { - if (static_cast(buffer_str.size()) > max_option_width) { + if (static_cast(buffer_out.size()) > max_option_width) { break; } // We can summarize positive boolean flags with a short name using a @@ -571,7 +571,7 @@ void MetaPrinter::PrintRawUsageCommandAndOptions(const Command& command, } llvm::StringRef space = have_short_flags ? " " : ""; for (const auto& option : command.options) { - if (static_cast(buffer_str.size()) > max_option_width) { + if (static_cast(buffer_out.size()) > max_option_width) { break; } if (option->is_help_hidden || option->meta_action) { @@ -587,10 +587,11 @@ void MetaPrinter::PrintRawUsageCommandAndOptions(const Command& command, buffer_printer.PrintOptionUsage(*option); space = " "; } - if (!buffer_str.empty()) { - if (static_cast(buffer_str.size()) <= max_option_width) { - *out_ << " [" << buffer_str << "]"; + if (!buffer_out.empty()) { + if (static_cast(buffer_out.size()) <= max_option_width) { + *out_ << " [" << buffer_out.TakeStr() << "]"; } else { + buffer_out.clear(); *out_ << " [OPTIONS]"; } } @@ -911,8 +912,7 @@ auto Parser::ParseOneOfArgValue(const Arg& arg, llvm::StringRef value) -> ErrorOr { CARBON_CHECK(arg.kind == Arg::Kind::OneOf, "Incorrect kind: {0}", arg.kind); if (!arg.value_action(arg, value)) { - std::string error_str; - llvm::raw_string_ostream error(error_str); + RawStringOstream error; error << "option `--" << arg.info.name << "="; llvm::printEscapedString(value, error); error << "` has an invalid value `"; @@ -920,7 +920,7 @@ auto Parser::ParseOneOfArgValue(const Arg& arg, llvm::StringRef value) error << "`; valid values are: "; PrintListOfAlternatives(error, arg.value_strings, [](llvm::StringRef x) { return x; }); - return Error(error_str); + return Error(error.TakeStr()); } return Success(); } @@ -1079,14 +1079,14 @@ auto Parser::FinalizeParsedOptions() -> ErrorOr { return lhs->info.name < rhs->info.name; }); - std::string error_str = "required options not provided: "; - llvm::raw_string_ostream error(error_str); + RawStringOstream error; + error << "required options not provided: "; llvm::ListSeparator sep; for (const Arg* option : missing_options) { error << sep << "--" << option->info.name; } - return Error(error_str); + return Error(error.TakeStr()); } auto Parser::ParsePositionalArg(llvm::StringRef unparsed_arg) @@ -1117,12 +1117,11 @@ auto Parser::ParsePositionalArg(llvm::StringRef unparsed_arg) auto Parser::ParseSubcommand(llvm::StringRef unparsed_arg) -> ErrorOr { auto subcommand_it = subcommand_map_.find(unparsed_arg); if (subcommand_it == subcommand_map_.end()) { - std::string error_str; - llvm::raw_string_ostream error(error_str); + RawStringOstream error; error << "invalid subcommand `" << unparsed_arg << "`; available subcommands: "; MetaPrinter(&error).PrintSubcommands(*command_); - return Error(error_str); + return Error(error.TakeStr()); } // Before we recurse into the subcommand, verify that all the required @@ -1179,11 +1178,10 @@ auto Parser::FinalizeParse() -> ErrorOr { case Command::Kind::Invalid: CARBON_FATAL("Should never have a parser with an invalid command!"); case Command::Kind::RequiresSubcommand: { - std::string error_str; - llvm::raw_string_ostream error(error_str); + RawStringOstream error; error << "no subcommand specified; available subcommands: "; MetaPrinter(&error).PrintSubcommands(*command_); - return Error(error_str); + return Error(error.TakeStr()); } case Command::Kind::Action: // All arguments have been successfully parsed, run any action for the diff --git a/common/command_line_test.cpp b/common/command_line_test.cpp index 1157aa8b9dc9..909f5db89010 100644 --- a/common/command_line_test.cpp +++ b/common/command_line_test.cpp @@ -8,15 +8,14 @@ #include #include "common/error_test_helpers.h" +#include "common/raw_string_ostream.h" #include "llvm/Support/FormatVariadic.h" -#include "testing/base/test_raw_ostream.h" namespace Carbon::CommandLine { namespace { using ::Carbon::Testing::IsError; using ::Carbon::Testing::IsSuccess; -using ::Carbon::Testing::TestRawOstream; using ::testing::ElementsAre; using ::testing::Eq; using ::testing::StrEq; @@ -92,7 +91,7 @@ TEST(ArgParserTest, BooleanFlags) { IsSuccess(Eq(ParseResult::Success))); EXPECT_FALSE(flag); - TestRawOstream os; + RawStringOstream os; EXPECT_THAT( parse({"--no-flag=true"}, os), IsError(StrEq("cannot specify a value when using a flag name prefixed " @@ -187,7 +186,7 @@ TEST(ArgParserTest, ShortArgs) { EXPECT_TRUE(example); EXPECT_THAT(integer_option, Eq(123)); - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({"-v"}, os), IsError(StrEq("unknown short option `-v`"))); EXPECT_THAT(parse({"-xvx"}, os), IsError(StrEq("unknown short option `-v`"))); @@ -231,7 +230,7 @@ TEST(ArgParserTest, PositionalArgs) { }); }; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({"--flag", "--option=x"}, os), IsError(StrEq( "not all required positional arguments were provided; first " @@ -277,7 +276,7 @@ TEST(ArgParserTest, PositionalAppendArgs) { }); }; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({"--flag", "--option=x"}, os), IsError(StrEq( "not all required positional arguments were provided; first " @@ -339,7 +338,7 @@ TEST(ArgParserTest, BasicSubcommands) { }); }; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({}, os), IsError(StrEq("no subcommand specified; available subcommands: " "`sub1`, `sub2`, or `help`"))); @@ -474,7 +473,7 @@ TEST(ArgParserTest, OneOfOption) { IsSuccess(Eq(ParseResult::Success))); EXPECT_THAT(value, Eq(3)); - TestRawOstream os; + RawStringOstream os; EXPECT_THAT( parse({"--option"}, os), @@ -502,7 +501,7 @@ TEST(ArgParserTest, OneOfOption) { TEST(ArgParserTest, OneOfOptionWithTwoOptions) { int value = 0; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(ParseOneOfOption({"--option=z"}, os, [&](auto& arg_b) { arg_b.SetOneOf( @@ -518,7 +517,7 @@ TEST(ArgParserTest, OneOfOptionWithTwoOptions) { TEST(ArgParserTest, OneOfOptionWithOneOption) { int value = 0; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(ParseOneOfOption({"--option=z"}, os, [&](auto& arg_b) { arg_b.SetOneOf( @@ -611,7 +610,7 @@ TEST(ArgParserTest, RequiredArgs) { }); }; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({}, os), IsError(StrEq("required options not provided: --opt1, --opt2"))); @@ -771,7 +770,7 @@ A hidden subcommand. }); }; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({"--flag", "--help"}, os), IsSuccess(Eq(ParseResult::MetaSuccess))); @@ -936,7 +935,7 @@ x }); }; - TestRawOstream os; + RawStringOstream os; EXPECT_THAT(parse({"--help"}, os), IsSuccess(Eq(ParseResult::MetaSuccess))); EXPECT_THAT(os.TakeStr(), StrEq(llvm::StringRef(R"""( Usage: diff --git a/common/enum_base_test.cpp b/common/enum_base_test.cpp index df22f8dc58e2..6a68455fb56e 100644 --- a/common/enum_base_test.cpp +++ b/common/enum_base_test.cpp @@ -6,7 +6,7 @@ #include -#include "testing/base/test_raw_ostream.h" +#include "common/raw_string_ostream.h" namespace Carbon { namespace { @@ -45,7 +45,7 @@ TEST(EnumBaseTest, NamesAndConstants) { } TEST(EnumBaseTest, Printing) { - Testing::TestRawOstream stream; + RawStringOstream stream; TestKind kind = TestKind::Beep; stream << kind << " " << TestKind::Beep; diff --git a/common/error.h b/common/error.h index 18715cfddd17..8b29e66ae41f 100644 --- a/common/error.h +++ b/common/error.h @@ -10,6 +10,7 @@ #include "common/check.h" #include "common/ostream.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/Twine.h" namespace Carbon { @@ -138,7 +139,10 @@ class ErrorBuilder { public: explicit ErrorBuilder(std::string location = "") : location_(std::move(location)), - out_(std::make_unique(message_)) {} + out_(std::make_unique()) {} + + ErrorBuilder(ErrorBuilder&&) = default; + auto operator=(ErrorBuilder&&) -> ErrorBuilder& = default; // Accumulates string message to a temporary `ErrorBuilder`. After streaming, // the builder must be converted to an `Error` or `ErrorOr`. @@ -156,19 +160,17 @@ class ErrorBuilder { } // NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns. - operator Error() { return Error(location_, message_); } + operator Error() { return Error(location_, out_->TakeStr()); } template // NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns. operator ErrorOr() { - return Error(location_, message_); + return Error(location_, out_->TakeStr()); } private: std::string location_; - std::string message_; - // Use a pointer to allow move construction. - std::unique_ptr out_; + std::unique_ptr out_; }; } // namespace Carbon diff --git a/common/error_test.cpp b/common/error_test.cpp index 04e3989a11ec..ebe56ae194f1 100644 --- a/common/error_test.cpp +++ b/common/error_test.cpp @@ -7,7 +7,7 @@ #include #include "common/error_test_helpers.h" -#include "testing/base/test_raw_ostream.h" +#include "common/raw_string_ostream.h" namespace Carbon { namespace { @@ -108,7 +108,7 @@ TEST(ErrorTest, ErrorBuilderOperatorImplicitCast) { TEST(ErrorTest, StreamError) { Error result = ErrorBuilder("TestFunc") << "msg"; - Testing::TestRawOstream result_stream; + RawStringOstream result_stream; result_stream << result; EXPECT_EQ(result_stream.TakeStr(), "TestFunc: msg"); } diff --git a/common/hashing_test.cpp b/common/hashing_test.cpp index df8231abd743..d33b56ff553a 100644 --- a/common/hashing_test.cpp +++ b/common/hashing_test.cpp @@ -10,6 +10,7 @@ #include #include +#include "common/raw_string_ostream.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/FormatVariadic.h" @@ -469,15 +470,14 @@ TEST(HashingTest, TupleRecursion) { constexpr uint64_t TestSeed = 42ULL * 1024; auto ToHexBytes(llvm::StringRef s) -> std::string { - std::string rendered; - llvm::raw_string_ostream os(rendered); - os << "{"; + RawStringOstream rendered; + rendered << "{"; llvm::ListSeparator sep(", "); for (const char c : s) { - os << sep << llvm::formatv("{0:x2}", static_cast(c)); + rendered << sep << llvm::formatv("{0:x2}", static_cast(c)); } - os << "}"; - return rendered; + rendered << "}"; + return rendered.TakeStr(); } template diff --git a/common/raw_string_ostream.h b/common/raw_string_ostream.h new file mode 100644 index 000000000000..37b121143c21 --- /dev/null +++ b/common/raw_string_ostream.h @@ -0,0 +1,64 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_COMMON_RAW_STRING_OSTREAM_H_ +#define CARBON_COMMON_RAW_STRING_OSTREAM_H_ + +#include "common/check.h" +#include "common/ostream.h" + +namespace Carbon { + +// Implements streaming output with an underlying string. The string must always +// be taken prior to destruction. +// +// Versus `llvm::raw_string_ostream`: +// - Owns the underlying string. +// - Supports `pwrite` for compatibility with more stream uses in tests. +class RawStringOstream : public llvm::raw_pwrite_stream { + public: + explicit RawStringOstream() : llvm::raw_pwrite_stream(/*Unbuffered=*/true) {} + + ~RawStringOstream() override { + CARBON_CHECK(str_.empty(), "Expected to be emptied by TakeStr, have: {0}", + str_); + } + + // Returns the streamed contents, clearing the stream back to empty. + auto TakeStr() -> std::string { + std::string result = std::move(str_); + clear(); + return result; + } + + // Clears the buffer, which can be helpful when destructing without + // necessarily calling `TakeStr()`. + auto clear() -> void { str_.clear(); } + + auto empty() -> bool { return str_.empty(); } + auto size() -> size_t { return str_.size(); } + + private: + auto current_pos() const -> uint64_t override { return str_.size(); } + + auto pwrite_impl(const char* ptr, size_t size, uint64_t offset) + -> void override { + str_.replace(offset, size, ptr, size); + } + + auto write_impl(const char* ptr, size_t size) -> void override { + str_.append(ptr, size); + } + + void reserveExtraSpace(uint64_t extra_size) override { + str_.reserve(str_.size() + extra_size); + } + + // The actual buffer. + std::string str_; +}; + +} // namespace Carbon + +#endif // CARBON_COMMON_RAW_STRING_OSTREAM_H_ diff --git a/testing/base/test_raw_ostream_test.cpp b/common/raw_string_ostream_test.cpp similarity index 67% rename from testing/base/test_raw_ostream_test.cpp rename to common/raw_string_ostream_test.cpp index 62b580cd5742..00cfee95563b 100644 --- a/testing/base/test_raw_ostream_test.cpp +++ b/common/raw_string_ostream_test.cpp @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include "testing/base/test_raw_ostream.h" +#include "common/raw_string_ostream.h" #include #include @@ -13,8 +13,8 @@ namespace { using ::testing::HasSubstr; using ::testing::StrEq; -TEST(TestRawOstreamTest, Basics) { - TestRawOstream os; +TEST(RawStringOstreamTest, Basics) { + RawStringOstream os; os << "test 1"; EXPECT_THAT(os.TakeStr(), StrEq("test 1")); @@ -30,9 +30,9 @@ TEST(TestRawOstreamTest, Basics) { EXPECT_THAT(os.TakeStr(), StrEq("test 3")); } -TEST(TestRawOstreamTest, MultipleStreams) { - TestRawOstream os1; - TestRawOstream os2; +TEST(RawStringOstreamTest, MultipleStreams) { + RawStringOstream os1; + RawStringOstream os2; os1 << "test "; os2 << "test stream 2"; @@ -41,8 +41,8 @@ TEST(TestRawOstreamTest, MultipleStreams) { EXPECT_THAT(os2.TakeStr(), StrEq("test stream 2")); } -TEST(TestRawOstreamTest, MultipleLines) { - TestRawOstream os; +TEST(RawStringOstreamTest, MultipleLines) { + RawStringOstream os; os << "test line 1\n"; os << "test line 2\n"; @@ -50,8 +50,8 @@ TEST(TestRawOstreamTest, MultipleLines) { EXPECT_THAT(os.TakeStr(), StrEq("test line 1\ntest line 2\ntest line 3\n")); } -TEST(TestRawOstreamTest, Substring) { - TestRawOstream os; +TEST(RawStringOstreamTest, Substring) { + RawStringOstream os; os << "test line 1\n"; os << "test line 2\n"; @@ -59,5 +59,13 @@ TEST(TestRawOstreamTest, Substring) { EXPECT_THAT(os.TakeStr(), HasSubstr("test line 2")); } +TEST(RawStringOstreamTest, Pwrite) { + RawStringOstream os; + os << "test line 1\n"; + os.pwrite("splat", 5, 1); + os << "test line 2\n"; + EXPECT_THAT(os.TakeStr(), HasSubstr("tsplatine 1\ntest line 2\n")); +} + } // namespace } // namespace Carbon::Testing diff --git a/common/vlog_test.cpp b/common/vlog_test.cpp index db095f89ee16..3761e24628a6 100644 --- a/common/vlog_test.cpp +++ b/common/vlog_test.cpp @@ -7,7 +7,7 @@ #include #include -#include "testing/base/test_raw_ostream.h" +#include "common/raw_string_ostream.h" namespace Carbon::Testing { namespace { @@ -30,7 +30,7 @@ class VLogger { auto TakeStr() -> std::string { return buffer_.TakeStr(); } private: - TestRawOstream buffer_; + RawStringOstream buffer_; llvm::raw_ostream* vlog_stream_ = nullptr; }; @@ -50,7 +50,7 @@ TEST(VLogTest, Disabled) { } TEST(VLogTest, To) { - TestRawOstream buffer; + RawStringOstream buffer; CARBON_VLOG_TO(&buffer, "Test"); EXPECT_THAT(buffer.TakeStr(), "Test"); } diff --git a/explorer/BUILD b/explorer/BUILD index 27d048d41d23..e93d4b12859f 100644 --- a/explorer/BUILD +++ b/explorer/BUILD @@ -57,7 +57,7 @@ cc_binary( deps = [ ":main", "//common:check", - "//testing/base:test_raw_ostream", + "//common:raw_string_ostream", "//testing/file_test:file_test_base", "@abseil-cpp//absl/flags:flag", "@re2", diff --git a/explorer/base/BUILD b/explorer/base/BUILD index 0004a7d27e6d..c5cf8fb7e96a 100644 --- a/explorer/base/BUILD +++ b/explorer/base/BUILD @@ -79,8 +79,8 @@ cc_test( deps = [ ":error_builders", ":source_location", + "//common:raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", ], ) diff --git a/explorer/base/error_builders_test.cpp b/explorer/base/error_builders_test.cpp index 125c8325dcef..eee6d19f5911 100644 --- a/explorer/base/error_builders_test.cpp +++ b/explorer/base/error_builders_test.cpp @@ -6,8 +6,8 @@ #include +#include "common/raw_string_ostream.h" #include "explorer/base/source_location.h" -#include "testing/base/test_raw_ostream.h" namespace Carbon { namespace { @@ -17,7 +17,7 @@ TEST(ErrorBuildersTest, ProgramError) { EXPECT_EQ(err.location(), "x:1"); EXPECT_EQ(err.message(), "test"); - Testing::TestRawOstream out; + RawStringOstream out; out << err; EXPECT_EQ(out.TakeStr(), "x:1: test"); } diff --git a/explorer/file_test.cpp b/explorer/file_test.cpp index e7cf9cf944b0..94d408dffe7b 100644 --- a/explorer/file_test.cpp +++ b/explorer/file_test.cpp @@ -3,9 +3,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "absl/flags/flag.h" +#include "common/raw_string_ostream.h" #include "explorer/main.h" #include "re2/re2.h" -#include "testing/base/test_raw_ostream.h" #include "testing/file_test/file_test_base.h" ABSL_FLAG(bool, trace, false, @@ -103,7 +103,7 @@ class ExplorerFileTest : public FileTestBase { return test_name().find("/trace/") != std::string::npos; } - TestRawOstream trace_stream_; + RawStringOstream trace_stream_; RE2 prelude_line_re_; RE2 timing_re_; }; diff --git a/testing/base/BUILD b/testing/base/BUILD index b9b6934e0bbb..f19165e3f2a0 100644 --- a/testing/base/BUILD +++ b/testing/base/BUILD @@ -53,6 +53,7 @@ cc_library( deps = [ "//common:check", "//common:map", + "//common:raw_string_ostream", "//common:set", "//toolchain/lex:token_kind", "@abseil-cpp//absl/random", @@ -90,28 +91,6 @@ cc_binary( ], ) -cc_library( - name = "test_raw_ostream", - testonly = 1, - hdrs = ["test_raw_ostream.h"], - deps = [ - "//common:ostream", - "@googletest//:gtest", - "@llvm-project//llvm:Support", - ], -) - -cc_test( - name = "test_raw_ostream_test", - size = "small", - srcs = ["test_raw_ostream_test.cpp"], - deps = [ - ":test_raw_ostream", - "//testing/base:gtest_main", - "@googletest//:gtest", - ], -) - cc_library( name = "global_exe_path", testonly = 1, diff --git a/testing/base/source_gen.cpp b/testing/base/source_gen.cpp index 819dccc6e3c4..8db91c865f1a 100644 --- a/testing/base/source_gen.cpp +++ b/testing/base/source_gen.cpp @@ -6,6 +6,7 @@ #include +#include "common/raw_string_ostream.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" @@ -311,8 +312,7 @@ static auto EstimateAvgClassDefLines(SourceGen::ClassParams params) -> double { auto SourceGen::GenAPIFileDenseDecls(int target_lines, const DenseDeclParams& params) -> std::string { - std::string source; - llvm::raw_string_ostream os(source); + RawStringOstream source; // Figure out how many classes fit in our target lines, each separated by a // blank line. We need to account the comment lines below to start the file. @@ -327,27 +327,29 @@ auto SourceGen::GenAPIFileDenseDecls(int target_lines, int expected_lines = NumFileCommentLines + num_classes * (avg_class_lines + 1); - os << "// Generated " << (!IsCpp() ? "Carbon" : "C++") << " source file.\n"; - os << llvm::formatv("// {0} target lines: {1} classes, {2} expected lines", - target_lines, num_classes, expected_lines) - << "\n"; - os << "//\n// Generating as an API file with dense declarations.\n"; + source << "// Generated " << (!IsCpp() ? "Carbon" : "C++") + << " source file.\n"; + source << llvm::formatv( + "// {0} target lines: {1} classes, {2} expected lines", + target_lines, num_classes, expected_lines) + << "\n"; + source << "//\n// Generating as an API file with dense declarations.\n"; // Carbon uses an implicitly imported prelude to get builtin types, but C++ // requires header files so include those. if (IsCpp()) { - os << "\n"; + source << "\n"; // Header for specific integer types like `std::int64_t`. - os << "#include \n"; + source << "#include \n"; // Header for `std::pair`. - os << "#include \n"; + source << "#include \n"; } auto class_gen_state = ClassGenState(*this, num_classes, params.class_params, params.type_use_params); for ([[maybe_unused]] int _ : llvm::seq(num_classes)) { - os << "\n"; - GenerateClassDef(params.class_params, class_gen_state, os); + source << "\n"; + GenerateClassDef(params.class_params, class_gen_state, source); } // Make sure we consumed all the state. @@ -358,7 +360,7 @@ auto SourceGen::GenAPIFileDenseDecls(int target_lines, CARBON_CHECK(class_gen_state.class_names().empty()); CARBON_CHECK(class_gen_state.type_names().empty()); - return source; + return source.TakeStr(); } auto SourceGen::GetShuffledIdentifiers(int number, int min_length, diff --git a/testing/base/test_raw_ostream.h b/testing/base/test_raw_ostream.h deleted file mode 100644 index 1dec83f0d47e..000000000000 --- a/testing/base/test_raw_ostream.h +++ /dev/null @@ -1,42 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#ifndef CARBON_TESTING_BASE_TEST_RAW_OSTREAM_H_ -#define CARBON_TESTING_BASE_TEST_RAW_OSTREAM_H_ - -#include - -#include - -#include "common/ostream.h" -#include "llvm/ADT/SmallString.h" - -namespace Carbon::Testing { - -// A raw_ostream that makes it easy to repeatedly check streamed output. -class TestRawOstream : public llvm::raw_svector_ostream { - public: - explicit TestRawOstream() : llvm::raw_svector_ostream(buffer_) {} - - ~TestRawOstream() override { - if (!buffer_.empty()) { - ADD_FAILURE() << "Unchecked output:\n" << buffer_; - } - } - - // Flushes the stream and returns the contents so far, clearing the stream - // back to empty. - auto TakeStr() -> std::string { - std::string result = buffer_.str().str(); - buffer_.clear(); - return result; - } - - private: - llvm::SmallString<16> buffer_; -}; - -} // namespace Carbon::Testing - -#endif // CARBON_TESTING_BASE_TEST_RAW_OSTREAM_H_ diff --git a/testing/file_test/BUILD b/testing/file_test/BUILD index 723af4d21a56..8020e0ca1df7 100644 --- a/testing/file_test/BUILD +++ b/testing/file_test/BUILD @@ -18,6 +18,7 @@ cc_library( deps = [ "//common:check", "//common:ostream", + "//common:raw_string_ostream", "@abseil-cpp//absl/strings:string_view", "@llvm-project//llvm:Support", "@re2", @@ -36,6 +37,7 @@ cc_library( "//common:exe_path", "//common:init_llvm", "//common:ostream", + "//common:raw_string_ostream", "@abseil-cpp//absl/flags:flag", "@abseil-cpp//absl/flags:parse", "@googletest//:gtest", diff --git a/testing/file_test/autoupdate.cpp b/testing/file_test/autoupdate.cpp index 307753cc2909..b8588198aa69 100644 --- a/testing/file_test/autoupdate.cpp +++ b/testing/file_test/autoupdate.cpp @@ -9,6 +9,7 @@ #include "absl/strings/string_view.h" #include "common/check.h" #include "common/ostream.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/FormatVariadic.h" @@ -363,11 +364,11 @@ auto FileTestAutoupdater::Run(bool dry_run) -> bool { } // Generate the autoupdated file. - std::string new_content; - llvm::raw_string_ostream new_content_stream(new_content); + RawStringOstream new_content_stream; for (const auto& line : new_lines_) { new_content_stream << *line << '\n'; } + std::string new_content = new_content_stream.TakeStr(); // Update the file on disk if needed. if (new_content == input_content_) { diff --git a/testing/file_test/file_test_base.cpp b/testing/file_test/file_test_base.cpp index d5886ef6a76c..ce80f1d25c73 100644 --- a/testing/file_test/file_test_base.cpp +++ b/testing/file_test/file_test_base.cpp @@ -18,6 +18,7 @@ #include "common/error.h" #include "common/exe_path.h" #include "common/init_llvm.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" @@ -108,8 +109,7 @@ enum class BazelMode : uint8_t { // Returns the requested bazel command string for the given execution mode. static auto GetBazelCommand(BazelMode mode, llvm::StringRef test_name) -> std::string { - std::string args_str; - llvm::raw_string_ostream args(args_str); + RawStringOstream args; const char* target = getenv("TEST_TARGET"); args << "bazel " << ((mode == BazelMode::Test) ? "test" : "run") << " " @@ -131,7 +131,7 @@ static auto GetBazelCommand(BazelMode mode, llvm::StringRef test_name) args << "--file_tests="; args << test_name; - return args_str; + return args.TakeStr(); } // Runs a test and compares output. This keeps output split by line so that diff --git a/toolchain/base/BUILD b/toolchain/base/BUILD index 0a523566991a..0a345a618549 100644 --- a/toolchain/base/BUILD +++ b/toolchain/base/BUILD @@ -83,8 +83,8 @@ cc_test( deps = [ ":value_ids", ":value_store", + "//common:raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/testing:yaml_test_helpers", "@googletest//:gtest", ], @@ -113,8 +113,8 @@ cc_test( srcs = ["int_test.cpp"], deps = [ ":int", + "//common:raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/testing:yaml_test_helpers", "@googletest//:gtest", ], @@ -138,8 +138,8 @@ cc_test( srcs = ["shared_value_stores_test.cpp"], deps = [ ":shared_value_stores", + "//common:raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/testing:yaml_test_helpers", "@googletest//:gtest", ], diff --git a/toolchain/base/shared_value_stores_test.cpp b/toolchain/base/shared_value_stores_test.cpp index e8872a40b892..05af75ddda90 100644 --- a/toolchain/base/shared_value_stores_test.cpp +++ b/toolchain/base/shared_value_stores_test.cpp @@ -7,7 +7,7 @@ #include #include -#include "testing/base/test_raw_ostream.h" +#include "common/raw_string_ostream.h" #include "toolchain/testing/yaml_test_helpers.h" namespace Carbon::Testing { @@ -31,7 +31,7 @@ auto MatchSharedValues(testing::Matcher ints, TEST(SharedValueStores, PrintEmpty) { SharedValueStores value_stores; - TestRawOstream out; + RawStringOstream out; value_stores.Print(out); EXPECT_THAT(Yaml::Value::FromText(out.TakeStr()), MatchSharedValues(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty())); @@ -46,7 +46,7 @@ TEST(SharedValueStores, PrintVals) { Real{.mantissa = apint, .exponent = apint, .is_decimal = true}); value_stores.identifiers().Add("a"); value_stores.string_literal_values().Add("foo'\"baz"); - TestRawOstream out; + RawStringOstream out; value_stores.Print(out); EXPECT_THAT(Yaml::Value::FromText(out.TakeStr()), diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 73432525bbb4..02701c5eee2c 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -74,6 +74,7 @@ cc_library( "//common:array_stack", "//common:check", "//common:map", + "//common:raw_string_ostream", "//common:set", "//common:vlog", "//toolchain/base:index_base", @@ -281,6 +282,7 @@ cc_library( hdrs = ["sem_ir_diagnostic_converter.h"], deps = [ ":context", + "//common:raw_string_ostream", "//toolchain/diagnostics:diagnostic_emitter", "//toolchain/lex:token_index", "//toolchain/parse:tree_node_diagnostic_converter", diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index fd4cf37cc074..eef20e3feb19 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -9,6 +9,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Tooling/Tooling.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" @@ -22,8 +23,7 @@ namespace Carbon::Check { auto ImportCppFile(Context& context, SemIRLoc loc, llvm::IntrusiveRefCntPtr fs, llvm::StringRef file_path, llvm::StringRef code) -> void { - std::string diagnostics_str; - llvm::raw_string_ostream diagnostics_stream(diagnostics_str); + RawStringOstream diagnostics_stream; llvm::IntrusiveRefCntPtr diagnostic_options( new clang::DiagnosticOptions()); @@ -45,13 +45,13 @@ auto ImportCppFile(Context& context, SemIRLoc loc, "{0} error{0:s} and {1} warning{1:s} in `Cpp` import `{2}`:\n{3}", IntAsSelect, IntAsSelect, std::string, std::string); context.emitter().Emit(loc, CppInteropParseError, num_errors, num_warnings, - file_path.str(), diagnostics_str); + file_path.str(), diagnostics_stream.TakeStr()); } else if (num_warnings > 0) { CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning, "{0} warning{0:s} in `Cpp` import `{1}`:\n{2}", IntAsSelect, std::string, std::string); context.emitter().Emit(loc, CppInteropParseWarning, num_warnings, - file_path.str(), diagnostics_str); + file_path.str(), diagnostics_stream.TakeStr()); } } diff --git a/toolchain/check/sem_ir_diagnostic_converter.cpp b/toolchain/check/sem_ir_diagnostic_converter.cpp index 2cf0e846dbd8..c3c6faebdc62 100644 --- a/toolchain/check/sem_ir_diagnostic_converter.cpp +++ b/toolchain/check/sem_ir_diagnostic_converter.cpp @@ -4,7 +4,9 @@ #include "toolchain/check/sem_ir_diagnostic_converter.h" +#include "common/raw_string_ostream.h" #include "toolchain/sem_ir/stringify_type.h" + namespace Carbon::Check { auto SemIRDiagnosticConverter::ConvertLoc(SemIRLoc loc, @@ -146,11 +148,12 @@ auto SemIRDiagnosticConverter::ConvertArg(llvm::Any arg) const -> llvm::Any { } else if (!library_name_id->is_valid()) { library_name = "library "; } else { - llvm::raw_string_ostream stream(library_name); - stream << "library \""; - stream << sem_ir_->string_literal_values().Get( - library_name_id->AsStringLiteralValueId()); - stream << "\""; + RawStringOstream stream; + stream << "library \"" + << sem_ir_->string_literal_values().Get( + library_name_id->AsStringLiteralValueId()) + << "\""; + library_name = stream.TakeStr(); } return library_name; } diff --git a/toolchain/driver/BUILD b/toolchain/driver/BUILD index d8ac6767b014..b5bd1017b58e 100644 --- a/toolchain/driver/BUILD +++ b/toolchain/driver/BUILD @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") +load("//bazel/cc_toolchains:defs.bzl", "cc_env") load("//testing/fuzzing:rules.bzl", "cc_fuzz_test") package(default_visibility = ["//visibility:public"]) @@ -41,14 +42,15 @@ cc_test( name = "clang_runner_test", size = "small", srcs = ["clang_runner_test.cpp"], + env = cc_env(), deps = [ ":clang_runner", "//common:all_llvm_targets", "//common:check", "//common:ostream", + "//common:raw_string_ostream", "//testing/base:global_exe_path", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "@googletest//:gtest", "@llvm-project//llvm:Object", "@llvm-project//llvm:Support", @@ -113,6 +115,7 @@ cc_library( ":clang_runner", "//common:command_line", "//common:ostream", + "//common:raw_string_ostream", "//common:version", "//common:vlog", "//toolchain/base:pretty_stack_trace_function", @@ -144,12 +147,13 @@ cc_test( name = "driver_test", size = "small", srcs = ["driver_test.cpp"], + env = cc_env(), deps = [ ":driver", "//common:all_llvm_targets", + "//common:raw_string_ostream", "//testing/base:global_exe_path", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/diagnostics:diagnostic_emitter", "//toolchain/install:install_paths", "//toolchain/lex:tokenized_buffer_test_helpers", @@ -168,7 +172,7 @@ cc_fuzz_test( deps = [ ":driver", "//common:exe_path", - "//testing/base:test_raw_ostream", + "//common:raw_string_ostream", "//testing/fuzzing:libfuzzer_header", "//toolchain/install:install_paths", "@llvm-project//llvm:Support", diff --git a/toolchain/driver/clang_runner_test.cpp b/toolchain/driver/clang_runner_test.cpp index 28c34714c09d..e746ae6994f4 100644 --- a/toolchain/driver/clang_runner_test.cpp +++ b/toolchain/driver/clang_runner_test.cpp @@ -13,18 +13,17 @@ #include "common/check.h" #include "common/ostream.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Object/Binary.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Program.h" #include "llvm/TargetParser/Host.h" #include "testing/base/global_exe_path.h" -#include "testing/base/test_raw_ostream.h" namespace Carbon { namespace { -using ::Carbon::Testing::TestRawOstream; using ::testing::HasSubstr; using ::testing::StrEq; @@ -54,7 +53,7 @@ static auto RunWithCapturedOutput(std::string& out, std::string& err, } TEST(ClangRunnerTest, Version) { - TestRawOstream test_os; + RawStringOstream test_os; const auto install_paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath()); std::string target = llvm::sys::getDefaultTargetTriple(); @@ -127,11 +126,10 @@ TEST(ClangRunnerTest, LinkCommandEcho) { const auto install_paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath()); - std::string verbose_out; - llvm::raw_string_ostream verbose_os(verbose_out); + RawStringOstream verbose_out; std::string target = llvm::sys::getDefaultTargetTriple(); auto vfs = llvm::vfs::getRealFileSystem(); - ClangRunner runner(&install_paths, target, vfs, &verbose_os); + ClangRunner runner(&install_paths, target, vfs, &verbose_out); std::string out; std::string err; EXPECT_TRUE(RunWithCapturedOutput(out, err, @@ -141,7 +139,8 @@ TEST(ClangRunnerTest, LinkCommandEcho) { bar_file.string()}); })) << "Verbose output from runner:\n" - << verbose_out << "\n"; + << verbose_out.TakeStr() << "\n"; + verbose_out.clear(); // Because we use `-###' above, we should just see the command that the Clang // driver would have run in a subprocess. This will be very architecture @@ -161,11 +160,10 @@ TEST(ClangRunnerTest, DashC) { const auto install_paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath()); - std::string verbose_out; - llvm::raw_string_ostream verbose_os(verbose_out); + RawStringOstream verbose_out; std::string target = llvm::sys::getDefaultTargetTriple(); auto vfs = llvm::vfs::getRealFileSystem(); - ClangRunner runner(&install_paths, target, vfs, &verbose_os); + ClangRunner runner(&install_paths, target, vfs, &verbose_out); std::string out; std::string err; EXPECT_TRUE(RunWithCapturedOutput(out, err, @@ -175,7 +173,8 @@ TEST(ClangRunnerTest, DashC) { test_output.string()}); })) << "Verbose output from runner:\n" - << verbose_out << "\n"; + << verbose_out.TakeStr() << "\n"; + verbose_out.clear(); // No output should be produced. EXPECT_THAT(out, StrEq("")); diff --git a/toolchain/driver/driver_fuzzer.cpp b/toolchain/driver/driver_fuzzer.cpp index 3a1b46b53db0..91b189c6bf8a 100644 --- a/toolchain/driver/driver_fuzzer.cpp +++ b/toolchain/driver/driver_fuzzer.cpp @@ -6,10 +6,10 @@ #include #include "common/exe_path.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" -#include "testing/base/test_raw_ostream.h" #include "testing/fuzzing/libfuzzer.h" #include "toolchain/driver/driver.h" #include "toolchain/install/install_paths.h" @@ -80,7 +80,7 @@ extern "C" auto LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) llvm::IntrusiveRefCntPtr fs = new llvm::vfs::InMemoryFileSystem; - TestRawOstream error_stream; + RawStringOstream error_stream; llvm::raw_null_ostream dest; Driver d(fs, install_paths, dest, error_stream); d.SetFuzzing(); diff --git a/toolchain/driver/driver_test.cpp b/toolchain/driver/driver_test.cpp index 3c8112d9b458..3b2bbae97823 100644 --- a/toolchain/driver/driver_test.cpp +++ b/toolchain/driver/driver_test.cpp @@ -11,17 +11,16 @@ #include #include +#include "common/raw_string_ostream.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Object/Binary.h" #include "llvm/Support/FormatVariadic.h" #include "testing/base/global_exe_path.h" -#include "testing/base/test_raw_ostream.h" #include "toolchain/testing/yaml_test_helpers.h" namespace Carbon { namespace { -using ::Carbon::Testing::TestRawOstream; using ::testing::_; using ::testing::ContainsRegex; using ::testing::HasSubstr; @@ -94,8 +93,8 @@ class DriverTest : public testing::Test { llvm::IntrusiveRefCntPtr fs_ = new llvm::vfs::InMemoryFileSystem; const InstallPaths installation_; - TestRawOstream test_output_stream_; - TestRawOstream test_error_stream_; + RawStringOstream test_output_stream_; + RawStringOstream test_error_stream_; // Some tests work directly with files in the test temporary directory. std::filesystem::path test_tmpdir_; diff --git a/toolchain/driver/format_subcommand.cpp b/toolchain/driver/format_subcommand.cpp index 714c96252587..41745b1d16e6 100644 --- a/toolchain/driver/format_subcommand.cpp +++ b/toolchain/driver/format_subcommand.cpp @@ -6,6 +6,7 @@ #include +#include "common/raw_string_ostream.h" #include "toolchain/base/shared_value_stores.h" #include "toolchain/diagnostics/diagnostic_consumer.h" #include "toolchain/format/format.h" @@ -83,15 +84,14 @@ auto FormatSubcommand::Run(DriverEnv& driver_env) -> DriverResult { SharedValueStores value_stores; auto tokens = Lex::Lex(value_stores, *source, consumer); - std::string buffer_str; - llvm::raw_string_ostream buffer(buffer_str); - + RawStringOstream buffer; if (Format::Format(tokens, buffer)) { // TODO: Figure out a multi-file output setup that supports good // multi-file testing. // TODO: Use --output values (and default to overwrite). - driver_env.output_stream << buffer_str; + driver_env.output_stream << buffer.TakeStr(); } else { + buffer.clear(); mark_per_file_error(); driver_env.output_stream << source->text(); } diff --git a/toolchain/language_server/BUILD b/toolchain/language_server/BUILD index 3d5686324804..ecde8af8ff57 100644 --- a/toolchain/language_server/BUILD +++ b/toolchain/language_server/BUILD @@ -16,6 +16,7 @@ cc_library( ":outgoing_messages", "//common:error", "//common:ostream", + "//common:raw_string_ostream", "@llvm-project//clang-tools-extra/clangd:ClangDaemon", ], ) diff --git a/toolchain/language_server/language_server.cpp b/toolchain/language_server/language_server.cpp index 285a30ee8c75..2b154d166fda 100644 --- a/toolchain/language_server/language_server.cpp +++ b/toolchain/language_server/language_server.cpp @@ -6,6 +6,7 @@ #include "clang-tools-extra/clangd/LSPBinder.h" #include "clang-tools-extra/clangd/Transport.h" +#include "common/raw_string_ostream.h" #include "toolchain/language_server/context.h" #include "toolchain/language_server/incoming_messages.h" #include "toolchain/language_server/outgoing_messages.h" @@ -26,10 +27,9 @@ auto Run(std::FILE* input_stream, llvm::raw_ostream& output_stream) // Run the server loop. llvm::Error err = transport->loop(incoming); if (err) { - std::string str; - llvm::raw_string_ostream out(str); + RawStringOstream out; out << err; - return Error(str); + return Error(out.TakeStr()); } else { return Success(); } diff --git a/toolchain/lex/BUILD b/toolchain/lex/BUILD index c68378ef81cc..6e4e850221ba 100644 --- a/toolchain/lex/BUILD +++ b/toolchain/lex/BUILD @@ -266,8 +266,8 @@ cc_test( ":token_kind", ":tokenized_buffer", ":tokenized_buffer_test_helpers", + "//common:raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/base:shared_value_stores", "//toolchain/diagnostics:diagnostic_emitter", "//toolchain/diagnostics:mocks", @@ -303,6 +303,7 @@ cc_binary( ":token_kind", ":tokenized_buffer", "//common:check", + "//common:raw_string_ostream", "//testing/base:benchmark_main", "//testing/base:source_gen_lib", "//toolchain/base:shared_value_stores", diff --git a/toolchain/lex/tokenized_buffer_benchmark.cpp b/toolchain/lex/tokenized_buffer_benchmark.cpp index 129a54b060cd..cffe8e6c394e 100644 --- a/toolchain/lex/tokenized_buffer_benchmark.cpp +++ b/toolchain/lex/tokenized_buffer_benchmark.cpp @@ -9,6 +9,7 @@ #include "absl/random/random.h" #include "common/check.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringExtras.h" #include "testing/base/source_gen.h" @@ -173,13 +174,14 @@ auto RandomSource(RandomSourceOptions options) -> std::string { // First place tokens onto each line. for (auto i : llvm::seq(NumTokens / options.tokens_per_line)) { lines.push_back(""); - llvm::raw_string_ostream os(lines.back()); + RawStringOstream os; // Arbitrarily indent each line by two spaces. os << " "; llvm::ListSeparator sep(" "); for (int j : llvm::seq(options.tokens_per_line)) { os << sep << tokens[i * options.tokens_per_line + j]; } + lines.push_back(os.TakeStr()); } // Next, synthesize blank and comment lines with the correct distribution. @@ -217,14 +219,14 @@ class LexerBenchHelper { } auto DiagnoseErrors() -> std::string { - std::string result; - llvm::raw_string_ostream out(result); - StreamDiagnosticConsumer consumer(out, /*include_diagnostic_kind=*/false); + RawStringOstream result; + StreamDiagnosticConsumer consumer(result, + /*include_diagnostic_kind=*/false); auto buffer = Lex::Lex(value_stores_, source_, consumer); consumer.Flush(); CARBON_CHECK(buffer.has_errors(), "Asked to diagnose errors but none found!"); - return result; + return result.TakeStr(); } auto source_text() -> llvm::StringRef { return source_.text(); } @@ -419,8 +421,7 @@ void BM_GroupingSymbols(benchmark::State& state) { // are also active and have some reasonable icache pressure. llvm::SmallVector ids = Testing::SourceGen::Global().GetShuffledIdentifiers(NumTokens); - std::string source; - llvm::raw_string_ostream os(source); + RawStringOstream os; int num_tokens_per_nest = curly_brace_depth * 2 + paren_depth * 2 + square_bracket_depth * 2 + 2; int num_nests = NumTokens / num_tokens_per_nest; @@ -449,7 +450,8 @@ void BM_GroupingSymbols(benchmark::State& state) { os << ids[(i * 2 + 1) % NumTokens] << "\n"; } - LexerBenchHelper helper(os.str()); + std::string source = os.TakeStr(); + LexerBenchHelper helper(source); for (auto _ : state) { TokenizedBuffer buffer = helper.Lex(); @@ -524,15 +526,15 @@ void BM_CommentLines(benchmark::State& state) { int num_comment_lines = state.range(0); int comment_length = state.range(1); int comment_indent = state.range(2); - std::string separator; - llvm::raw_string_ostream os(separator); + RawStringOstream os; os << "\n"; for (int i : llvm::seq(num_comment_lines)) { static_cast(i); os << std::string(comment_indent, ' ') << "//" << std::string(comment_length, ' ') << "\n"; } - std::string source = RandomIdentifierSeq(3, 5, /*uniform=*/true, separator); + std::string source = + RandomIdentifierSeq(3, 5, /*uniform=*/true, os.TakeStr()); LexerBenchHelper helper(source); for (auto _ : state) { diff --git a/toolchain/lex/tokenized_buffer_test.cpp b/toolchain/lex/tokenized_buffer_test.cpp index a8ce45ccbd45..0a014d4c1861 100644 --- a/toolchain/lex/tokenized_buffer_test.cpp +++ b/toolchain/lex/tokenized_buffer_test.cpp @@ -11,9 +11,9 @@ #include #include +#include "common/raw_string_ostream.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FormatVariadic.h" -#include "testing/base/test_raw_ostream.h" #include "toolchain/base/shared_value_stores.h" #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/diagnostics/mocks.h" @@ -27,7 +27,6 @@ namespace { using ::Carbon::Testing::ExpectedToken; using ::Carbon::Testing::IsSingleDiagnostic; -using ::Carbon::Testing::TestRawOstream; using ::testing::_; using ::testing::ElementsAre; using ::testing::Eq; @@ -1168,10 +1167,9 @@ TEST_F(LexerTest, DiagnosticFileTooLarge) { compile_helper_.GetTokenizedBuffer(input, &consumer); } -// Appends comment lines to the string, to create a comment block. -static auto AppendCommentLines(std::string& str, int count, llvm::StringRef tag) - -> void { - llvm::raw_string_ostream out(str); +// Outputs comments to the stream to create a comment block. +static auto AppendCommentLines(RawStringOstream& out, int count, + llvm::StringRef tag) -> void { for (int i : llvm::seq(count)) { out << "// " << tag << i << "\n"; } @@ -1179,13 +1177,15 @@ static auto AppendCommentLines(std::string& str, int count, llvm::StringRef tag) TEST_F(LexerTest, CommentBlock) { for (int comments_before = 0; comments_before < 5; ++comments_before) { - std::string prefix; + RawStringOstream prefix; AppendCommentLines(prefix, comments_before, "B"); + std::string prefix_out = prefix.TakeStr(); for (int comments_after = 1; comments_after < 5; ++comments_after) { - std::string source = prefix; + RawStringOstream source; + source << prefix_out; if (comments_before > 0) { - source += "//\n"; + source << "//\n"; } AppendCommentLines(source, comments_after, "C"); @@ -1193,7 +1193,7 @@ TEST_F(LexerTest, CommentBlock) { "{0} comment lines before the empty comment line, {1} after", comments_before, comments_after)); - auto& buffer = compile_helper_.GetTokenizedBuffer(source); + auto& buffer = compile_helper_.GetTokenizedBuffer(source.TakeStr()); ASSERT_FALSE(buffer.has_errors()); EXPECT_THAT(buffer.comments_size(), Eq(1)); @@ -1205,17 +1205,17 @@ TEST_F(LexerTest, IndentedComments) { for (int indent = 0; indent < 40; ++indent) { SCOPED_TRACE(llvm::formatv("Indent: {0}", indent)); - std::string source; - llvm::raw_string_ostream source_stream(source); - source_stream.indent(indent); - source_stream << "// Comment\n"; + RawStringOstream source; + source.indent(indent); + source << "// Comment\n"; + std::string source_str = source.TakeStr(); - auto& buffer = compile_helper_.GetTokenizedBuffer(source); + auto& buffer = compile_helper_.GetTokenizedBuffer(source_str); ASSERT_FALSE(buffer.has_errors()); EXPECT_THAT(buffer.comments_size(), Eq(1)); std::string simd_source = - source + + source_str + "\"Add a bunch of padding so that SIMD logic shouldn't hit EOF\""; auto& simd_buffer = compile_helper_.GetTokenizedBuffer(simd_source); ASSERT_FALSE(simd_buffer.has_errors()); @@ -1282,7 +1282,7 @@ TEST_F(LexerTest, PrintingOutputYaml) { auto& buffer = compile_helper_.GetTokenizedBuffer("\n ;\n\n\n; ;\n\n\n\n\n\n\n\n\n\n\n"); ASSERT_FALSE(buffer.has_errors()); - TestRawOstream print_stream; + RawStringOstream print_stream; buffer.Print(print_stream); EXPECT_THAT( diff --git a/toolchain/lower/BUILD b/toolchain/lower/BUILD index bbcfa03f21f3..c9445b2c3362 100644 --- a/toolchain/lower/BUILD +++ b/toolchain/lower/BUILD @@ -46,6 +46,7 @@ cc_library( deps = [ "//common:check", "//common:map", + "//common:raw_string_ostream", "//common:vlog", "//toolchain/base:kind_switch", "//toolchain/check:sem_ir_diagnostic_converter", diff --git a/toolchain/lower/mangler.cpp b/toolchain/lower/mangler.cpp index 8d32a015b797..751f04c5e13b 100644 --- a/toolchain/lower/mangler.cpp +++ b/toolchain/lower/mangler.cpp @@ -4,6 +4,7 @@ #include "toolchain/lower/mangler.h" +#include "common/raw_string_ostream.h" #include "toolchain/base/kind_switch.h" #include "toolchain/sem_ir/entry_point.h" #include "toolchain/sem_ir/ids.h" @@ -131,8 +132,7 @@ auto Mangler::Mangle(SemIR::FunctionId function_id, CARBON_CHECK(!specific_id.is_valid(), "entry point should not be generic"); return "main"; } - std::string result; - llvm::raw_string_ostream os(result); + RawStringOstream os; os << "_C"; os << names().GetAsStringIfIdentifier(function.name_id); @@ -151,7 +151,7 @@ auto Mangler::Mangle(SemIR::FunctionId function_id, llvm::HexPrintStyle::Lower, 16); } - return os.str(); + return os.TakeStr(); } } // namespace Carbon::Lower diff --git a/toolchain/parse/BUILD b/toolchain/parse/BUILD index 748f83d30e4e..8fccba148630 100644 --- a/toolchain/parse/BUILD +++ b/toolchain/parse/BUILD @@ -157,8 +157,8 @@ cc_test( ":parse", ":tree", "//common:ostream", + "//common:raw_string_ostream", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/base:shared_value_stores", "//toolchain/diagnostics:diagnostic_emitter", "//toolchain/diagnostics:mocks", diff --git a/toolchain/parse/tree_test.cpp b/toolchain/parse/tree_test.cpp index bacc294bebaa..29adddea0a10 100644 --- a/toolchain/parse/tree_test.cpp +++ b/toolchain/parse/tree_test.cpp @@ -9,7 +9,7 @@ #include -#include "testing/base/test_raw_ostream.h" +#include "common/raw_string_ostream.h" #include "toolchain/base/shared_value_stores.h" #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/diagnostics/mocks.h" @@ -23,7 +23,6 @@ namespace Carbon::Parse { namespace { -using ::Carbon::Testing::TestRawOstream; using ::testing::ElementsAre; using ::testing::Pair; @@ -90,7 +89,7 @@ TEST_F(TreeTest, PrintPostorderAsYAML) { auto [tokens, tree_and_subtrees] = compile_helper_.GetTokenizedBufferWithTreeAndSubtrees("fn F();"); EXPECT_FALSE(tree_and_subtrees.tree().has_errors()); - TestRawOstream print_stream; + RawStringOstream print_stream; tree_and_subtrees.tree().Print(print_stream); auto file = Yaml::Sequence(ElementsAre( @@ -119,7 +118,7 @@ TEST_F(TreeTest, PrintPreorderAsYAML) { auto [tokens, tree_and_subtrees] = compile_helper_.GetTokenizedBufferWithTreeAndSubtrees("fn F();"); EXPECT_FALSE(tree_and_subtrees.tree().has_errors()); - TestRawOstream print_stream; + RawStringOstream print_stream; tree_and_subtrees.PrintPreorder(print_stream); auto param_list = Yaml::Sequence(ElementsAre(Yaml::Mapping( diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index 72e5dee71ab7..6031372784a2 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -55,6 +55,7 @@ cc_library( "//common:check", "//common:hashing", "//common:ostream", + "//common:raw_string_ostream", "//common:struct_reflection", "//toolchain/base:index_base", "//toolchain/base:int", @@ -112,6 +113,7 @@ cc_library( "//common:hashing", "//common:map", "//common:ostream", + "//common:raw_string_ostream", "//common:set", "//toolchain/base:int", "//toolchain/base:kind_switch", @@ -134,6 +136,7 @@ cc_library( ":file", ":typed_insts", "//common:check", + "//common:raw_string_ostream", "//toolchain/base:kind_switch", "@llvm-project//llvm:Support", ], @@ -153,6 +156,7 @@ cc_library( ":file", ":typed_insts", "//common:ostream", + "//common:raw_string_ostream", "//toolchain/base:kind_switch", "//toolchain/base:shared_value_stores", "//toolchain/base:value_ids", @@ -232,9 +236,9 @@ cc_test( srcs = ["yaml_test.cpp"], deps = [ "//common:ostream", + "//common:raw_string_ostream", "//testing/base:global_exe_path", "//testing/base:gtest_main", - "//testing/base:test_raw_ostream", "//toolchain/driver", "//toolchain/testing:yaml_test_helpers", "@googletest//:gtest", diff --git a/toolchain/sem_ir/inst.h b/toolchain/sem_ir/inst.h index 17929a94183d..7423003d6e3d 100644 --- a/toolchain/sem_ir/inst.h +++ b/toolchain/sem_ir/inst.h @@ -11,6 +11,7 @@ #include "common/check.h" #include "common/hashing.h" #include "common/ostream.h" +#include "common/raw_string_ostream.h" #include "common/struct_reflection.h" #include "toolchain/base/index_base.h" #include "toolchain/base/int.h" @@ -88,15 +89,14 @@ struct InstLikeTypeInfo : InstLikeTypeInfoBase { } // A name that can be streamed to an llvm::raw_ostream. static auto DebugName() -> std::string { - std::string str; - llvm::raw_string_ostream out(str); + RawStringOstream out; out << "{"; llvm::ListSeparator sep; for (auto kind : InstCat::Kinds) { out << sep << kind; } out << "}"; - return out.str(); + return out.TakeStr(); } }; diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index 2aa6abd2df45..f28613a8375c 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -5,6 +5,7 @@ #include "toolchain/sem_ir/inst_namer.h" #include "common/ostream.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StableHashing.h" @@ -152,18 +153,17 @@ auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const const auto& [inst_scope, inst_name] = insts_[inst_id.index]; if (!inst_name) { // This should not happen in valid IR. - std::string str; - llvm::raw_string_ostream str_stream(str); - str_stream << "." << inst_id; + RawStringOstream out; + out << "." << inst_id; auto loc_id = sem_ir_->insts().GetLocId(inst_id); // TODO: Consider handling inst_id cases. if (loc_id.is_node_id()) { const auto& tree = sem_ir_->parse_tree(); auto token = tree.node_token(loc_id.node_id()); - str_stream << ".loc" << tree.tokens().GetLineNumber(token) << "_" - << tree.tokens().GetColumnNumber(token); + out << ".loc" << tree.tokens().GetLineNumber(token) << "_" + << tree.tokens().GetColumnNumber(token); } - return str; + return out.TakeStr(); } if (inst_scope == scope_id) { return ("%" + inst_name.str()).str(); @@ -190,10 +190,9 @@ auto InstNamer::GetLabelFor(ScopeId scope_id, InstBlockId block_id) const const auto& [label_scope, label_name] = labels_[block_id.index]; if (!label_name) { // This should not happen in valid IR. - std::string str; - llvm::raw_string_ostream(str) - << ""; - return str; + RawStringOstream out; + out << ""; + return out.TakeStr(); } if (label_scope == scope_id) { return ("!" + label_name.str()).str(); @@ -443,8 +442,7 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, auto add_int_or_float_type_name = [&](char type_literal_prefix, SemIR::InstId bit_width_id, llvm::StringRef suffix = "") { - std::string name; - llvm::raw_string_ostream out(name); + RawStringOstream out; out << type_literal_prefix; if (auto bit_width = sem_ir_->insts().TryGetAs(bit_width_id)) { out << sem_ir_->ints().Get(bit_width->int_id); @@ -452,7 +450,7 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, out << "N"; } out << suffix; - add_inst_name(std::move(name)); + add_inst_name(out.TakeStr()); }; auto facet_access_name_id = [&](InstId facet_value_inst_id) -> NameId { if (auto name = sem_ir_->insts().TryGetAs(facet_value_inst_id)) { @@ -483,10 +481,9 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, continue; } case CARBON_KIND(AssociatedEntity inst): { - std::string name; - llvm::raw_string_ostream out(name); + RawStringOstream out; out << "assoc" << inst.index.index; - add_inst_name(std::move(name)); + add_inst_name(out.TakeStr()); continue; } case CARBON_KIND(AssociatedEntityType inst): { @@ -679,10 +676,9 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, } case CARBON_KIND(ImplWitnessAccess inst): { // TODO: Include information about the impl? - std::string name; - llvm::raw_string_ostream out(name); + RawStringOstream out; out << "impl.elem" << inst.index.index; - add_inst_name(std::move(name)); + add_inst_name(out.TakeStr()); continue; } case CARBON_KIND(ImportDecl inst): { @@ -724,10 +720,9 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, continue; } case CARBON_KIND(IntValue inst): { - std::string name; - llvm::raw_string_ostream out(name); + RawStringOstream out; out << "int_" << sem_ir_->ints().Get(inst.int_id); - add_inst_name(std::move(name)); + add_inst_name(out.TakeStr()); continue; } case CARBON_KIND(NameBindingDecl inst): { @@ -840,10 +835,9 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, continue; } case CARBON_KIND(TupleAccess inst): { - std::string name; - llvm::raw_string_ostream out(name); + RawStringOstream out; out << "tuple.elem" << inst.index.index; - add_inst_name(std::move(name)); + add_inst_name(out.TakeStr()); continue; } case CARBON_KIND(TupleType inst): { diff --git a/toolchain/sem_ir/stringify_type.cpp b/toolchain/sem_ir/stringify_type.cpp index 9278fa1a65d2..cfaa8f6ec8d9 100644 --- a/toolchain/sem_ir/stringify_type.cpp +++ b/toolchain/sem_ir/stringify_type.cpp @@ -4,6 +4,7 @@ #include "toolchain/sem_ir/stringify_type.h" +#include "common/raw_string_ostream.h" #include "toolchain/base/kind_switch.h" #include "toolchain/sem_ir/entity_with_params_base.h" #include "toolchain/sem_ir/ids.h" @@ -147,8 +148,7 @@ class StepStack { auto StringifyTypeExpr(const SemIR::File& sem_ir, InstId outer_inst_id) -> std::string { - std::string str; - llvm::raw_string_ostream out(str); + RawStringOstream out; // Note: Since this is a stack, work is resolved in the reverse order from the // order pushed. @@ -617,7 +617,7 @@ auto StringifyTypeExpr(const SemIR::File& sem_ir, InstId outer_inst_id) } } - return str; + return out.TakeStr(); } } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/type_info.cpp b/toolchain/sem_ir/type_info.cpp index 6143fc687947..105c63610f91 100644 --- a/toolchain/sem_ir/type_info.cpp +++ b/toolchain/sem_ir/type_info.cpp @@ -4,6 +4,7 @@ #include "toolchain/sem_ir/type_info.h" +#include "common/raw_string_ostream.h" #include "toolchain/sem_ir/file.h" namespace Carbon::SemIR { @@ -121,10 +122,9 @@ auto NumericTypeLiteralInfo::PrintLiteral(const File& file, auto NumericTypeLiteralInfo::GetLiteralAsString(const File& file) const -> std::string { - std::string result; - llvm::raw_string_ostream out(result); + RawStringOstream out; PrintLiteral(file, out); - return result; + return out.TakeStr(); } } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index 7886bb1b6474..0a77e0fe1ac9 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -6,17 +6,16 @@ #include #include "common/ostream.h" +#include "common/raw_string_ostream.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/VirtualFileSystem.h" #include "testing/base/global_exe_path.h" -#include "testing/base/test_raw_ostream.h" #include "toolchain/driver/driver.h" #include "toolchain/testing/yaml_test_helpers.h" namespace Carbon::SemIR { namespace { -using ::Carbon::Testing::TestRawOstream; using ::testing::_; using ::testing::AllOf; using ::testing::Contains; @@ -38,7 +37,7 @@ TEST(SemIRTest, YAML) { llvm::MemoryBuffer::getMemBuffer("fn F() { var x: () = (); return; }"))); const auto install_paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath()); - TestRawOstream print_stream; + RawStringOstream print_stream; Driver d(fs, &install_paths, print_stream, llvm::errs()); auto run_result = d.RunCommand({"compile", "--no-prelude-import", "--phase=check", diff --git a/toolchain/testing/BUILD b/toolchain/testing/BUILD index 11e2edc3126d..6c5b3d7214d9 100644 --- a/toolchain/testing/BUILD +++ b/toolchain/testing/BUILD @@ -73,6 +73,7 @@ cc_library( deps = [ "//common:error", "//common:ostream", + "//common:raw_string_ostream", "@abseil-cpp//absl/strings", "@googletest//:gtest", "@llvm-project//llvm:Support", diff --git a/toolchain/testing/yaml_test_helpers.cpp b/toolchain/testing/yaml_test_helpers.cpp index 8bb9b877395c..118391d799bd 100644 --- a/toolchain/testing/yaml_test_helpers.cpp +++ b/toolchain/testing/yaml_test_helpers.cpp @@ -4,6 +4,7 @@ #include "toolchain/testing/yaml_test_helpers.h" +#include "common/raw_string_ostream.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/YAMLParser.h" @@ -63,9 +64,9 @@ auto Value::FromText(llvm::StringRef text) -> ErrorOr { sm.setDiagHandler( [](const llvm::SMDiagnostic& diag, void* context) -> void { auto* error_message = static_cast*>(context); - *error_message = std::string(); - llvm::raw_string_ostream stream(**error_message); + RawStringOstream stream; diag.print(/*ProgName=*/nullptr, stream, /*ShowColors=*/false); + *error_message = stream.TakeStr(); }, &error_message); llvm::yaml::Stream yaml_stream(text, sm);