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 <gromer@google.com>
This commit is contained in:
Jon Ross-Perkins
2025-01-18 01:11:44 +00:00
committed by GitHub
co-authored by Geoff Romer
parent ef6e035e7d
commit 4c4c4a4d2c
47 changed files with 318 additions and 275 deletions
+27 -7
View File
@@ -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",
],
)
+17 -19
View File
@@ -6,6 +6,7 @@
#include <memory>
#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<int>(buffer_str.size()) > max_option_width) {
if (static_cast<int>(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<int>(buffer_str.size()) > max_option_width) {
if (static_cast<int>(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<int>(buffer_str.size()) <= max_option_width) {
*out_ << " [" << buffer_str << "]";
if (!buffer_out.empty()) {
if (static_cast<int>(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<Success> {
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<Success> {
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<Success> {
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<ParseResult> {
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
+12 -13
View File
@@ -8,15 +8,14 @@
#include <gtest/gtest.h>
#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:
+2 -2
View File
@@ -6,7 +6,7 @@
#include <gtest/gtest.h>
#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;
+8 -6
View File
@@ -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<llvm::raw_string_ostream>(message_)) {}
out_(std::make_unique<RawStringOstream>()) {}
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 <typename T>
// NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns.
operator ErrorOr<T>() {
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<llvm::raw_string_ostream> out_;
std::unique_ptr<RawStringOstream> out_;
};
} // namespace Carbon
+2 -2
View File
@@ -7,7 +7,7 @@
#include <gtest/gtest.h>
#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");
}
+6 -6
View File
@@ -10,6 +10,7 @@
#include <concepts>
#include <type_traits>
#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<uint8_t>(c));
rendered << sep << llvm::formatv("{0:x2}", static_cast<uint8_t>(c));
}
os << "}";
return rendered;
rendered << "}";
return rendered.TakeStr();
}
template <typename T>
+64
View File
@@ -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_
@@ -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 <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -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
+3 -3
View File
@@ -7,7 +7,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#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");
}
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
],
)
+2 -2
View File
@@ -6,8 +6,8 @@
#include <gtest/gtest.h>
#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");
}
+2 -2
View File
@@ -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_;
};
+1 -22
View File
@@ -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,
+15 -13
View File
@@ -6,6 +6,7 @@
#include <numeric>
#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 <cstdint>\n";
source << "#include <cstdint>\n";
// Header for `std::pair`.
os << "#include <utility>\n";
source << "#include <utility>\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,
-42
View File
@@ -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 <gtest/gtest.h>
#include <string>
#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_
+2
View File
@@ -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",
+3 -2
View File
@@ -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_) {
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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",
],
+3 -3
View File
@@ -7,7 +7,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#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<Yaml::MappingValue> 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()),
+2
View File
@@ -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",
+4 -4
View File
@@ -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<llvm::vfs::FileSystem> 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<clang::DiagnosticOptions> 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());
}
}
@@ -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 <invalid>";
} 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;
}
+7 -3
View File
@@ -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",
+10 -11
View File
@@ -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(""));
+2 -2
View File
@@ -6,10 +6,10 @@
#include <string>
#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<llvm::vfs::InMemoryFileSystem> 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();
+3 -4
View File
@@ -11,17 +11,16 @@
#include <fstream>
#include <utility>
#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<llvm::vfs::InMemoryFileSystem> 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_;
+4 -4
View File
@@ -6,6 +6,7 @@
#include <string>
#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();
}
+1
View File
@@ -16,6 +16,7 @@ cc_library(
":outgoing_messages",
"//common:error",
"//common:ostream",
"//common:raw_string_ostream",
"@llvm-project//clang-tools-extra/clangd:ClangDaemon",
],
)
@@ -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();
}
+2 -1
View File
@@ -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",
+13 -11
View File
@@ -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<llvm::StringRef> 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<void>(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) {
+17 -17
View File
@@ -11,9 +11,9 @@
#include <forward_list>
#include <iterator>
#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(
+1
View File
@@ -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",
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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",
+3 -4
View File
@@ -9,7 +9,7 @@
#include <forward_list>
#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(
+5 -1
View File
@@ -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",
+3 -3
View File
@@ -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<InstCat> : InstLikeTypeInfoBase<InstCat> {
}
// 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();
}
};
+19 -25
View File
@@ -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 << "<unexpected>." << inst_id;
RawStringOstream out;
out << "<unexpected>." << 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)
<< "<unexpected instblockref " << block_id << ">";
return str;
RawStringOstream out;
out << "<unexpected instblockref " << block_id << ">";
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<IntValue>(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<NameRef>(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): {
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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
+2 -3
View File
@@ -6,17 +6,16 @@
#include <gtest/gtest.h>
#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",
+1
View File
@@ -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",
+3 -2
View File
@@ -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<SequenceValue> {
sm.setDiagHandler(
[](const llvm::SMDiagnostic& diag, void* context) -> void {
auto* error_message = static_cast<std::optional<std::string>*>(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);