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
+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,