Introduce StringBuilder utility around raw_string_ostream

Alp Toker alp at nuanti.com
Wed Jun 11 21:25:02 PDT 2014


Replaces the pattern:

   std::string buf;
   raw_string_ostream os(buf);
   ...
   os.flush();
   use(buf);

with:
   StringBuilder os;
   ...
   use (os.str());

Benefits:

  * Provides an inherently safe and opaque interface for building 
std::string instances
  * Opens up the possibility of changing the underlying storage in future.

Patch also converts various uses, some of which were accessing the 
storage without flushing.

Alp.

-- 
http://www.nuanti.com
the browser experts

-------------- next part --------------
diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h
index e6d2ed1..57b7333 100644
--- a/include/llvm/Analysis/CFGPrinter.h
+++ b/include/llvm/Analysis/CFGPrinter.h
@@ -36,9 +36,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
     if (!Node->getName().empty())
       return Node->getName().str();
 
-    std::string Str;
-    raw_string_ostream OS(Str);
-
+    StringBuilder OS;
     Node->printAsOperand(OS, false);
     return OS.str();
   }
@@ -46,8 +44,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
   static std::string getCompleteNodeLabel(const BasicBlock *Node,
                                           const Function *) {
     enum { MaxColumns = 80 };
-    std::string Str;
-    raw_string_ostream OS(Str);
+    StringBuilder OS;
 
     if (Node->getName().empty()) {
       Node->printAsOperand(OS, false);
@@ -109,8 +106,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
 
       if (SuccNo == 0) return "def";
 
-      std::string Str;
-      raw_string_ostream OS(Str);
+      StringBuilder OS;
       SwitchInst::ConstCaseIt Case =
           SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
       OS << Case.getCaseValue()->getValue();
diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h
index 2f02aa7..98ae1a1 100644
--- a/include/llvm/Support/GraphWriter.h
+++ b/include/llvm/Support/GraphWriter.h
@@ -184,8 +184,7 @@ public:
         O << "|" << DOT::EscapeString(NodeDesc);
     }
 
-    std::string edgeSourceLabels;
-    raw_string_ostream EdgeSourceLabels(edgeSourceLabels);
+    StringBuilder EdgeSourceLabels;
     bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels, Node);
 
     if (hasEdgeSourceLabels) {
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index 50da769..e9d4491 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -612,8 +612,7 @@ template<typename T>
 typename std::enable_if<has_ScalarTraits<T>::value,void>::type
 yamlize(IO &io, T &Val, bool) {
   if ( io.outputting() ) {
-    std::string Storage;
-    llvm::raw_string_ostream Buffer(Storage);
+    llvm::StringBuilder Buffer;
     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
     StringRef Str = Buffer.str();
     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index 34fbe08..7105762 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -449,6 +449,24 @@ public:
   }
 };
 
+/// StringBuilder - A raw_ostream that builds an std::string.  This is
+/// a raw_string_ostream with storage.
+class StringBuilder : public raw_string_ostream {
+  std::string Buffer;
+
+protected:
+  // There's no need to explicitly flush a StringBuilder.
+  using raw_string_ostream::flush;
+
+public:
+  StringBuilder() : raw_string_ostream(Buffer) {}
+
+  void clear() {
+    flush();
+    Buffer.clear();
+  }
+};
+
 /// raw_svector_ostream - A raw_ostream that writes to an SmallVector or
 /// SmallString.  This is a simple adaptor class. This class does not
 /// encounter output errors.
diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp
index ade940a..24f57cd 100644
--- a/lib/Analysis/Analysis.cpp
+++ b/lib/Analysis/Analysis.cpp
@@ -75,8 +75,7 @@ void LLVMInitializeAnalysis(LLVMPassRegistryRef R) {
 LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action,
                           char **OutMessages) {
   raw_ostream *DebugOS = Action != LLVMReturnStatusAction ? &errs() : nullptr;
-  std::string Messages;
-  raw_string_ostream MsgsOS(Messages);
+  StringBuilder MsgsOS;
 
   LLVMBool Result = verifyModule(*unwrap(M), OutMessages ? &MsgsOS : DebugOS);
 
diff --git a/lib/Analysis/BlockFrequencyInfo.cpp b/lib/Analysis/BlockFrequencyInfo.cpp
index 8ed8e3e..3d00418 100644
--- a/lib/Analysis/BlockFrequencyInfo.cpp
+++ b/lib/Analysis/BlockFrequencyInfo.cpp
@@ -82,10 +82,9 @@ struct DOTGraphTraits<BlockFrequencyInfo*> : public DefaultDOTGraphTraits {
 
   std::string getNodeLabel(const BasicBlock *Node,
                            const BlockFrequencyInfo *Graph) {
-    std::string Result;
-    raw_string_ostream OS(Result);
+    StringBuilder OS;
 
-    OS << Node->getName().str() << ":";
+    OS << Node->getName() << ":";
     switch (ViewBlockFreqPropagationDAG) {
     case GVDT_Fraction:
       Graph->printBlockFreq(OS, Node);
@@ -98,7 +97,7 @@ struct DOTGraphTraits<BlockFrequencyInfo*> : public DefaultDOTGraphTraits {
                        "never reach this point.");
     }
 
-    return Result;
+    return OS.str();
   }
 };
 
diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp
index b14f329..492149b 100644
--- a/lib/Analysis/Lint.cpp
+++ b/lib/Analysis/Lint.cpp
@@ -105,11 +105,10 @@ namespace {
     const DataLayout *DL;
     TargetLibraryInfo *TLI;
 
-    std::string Messages;
-    raw_string_ostream MessagesStr;
+    StringBuilder MessagesStr;
 
     static char ID; // Pass identification, replacement for typeid
-    Lint() : FunctionPass(ID), MessagesStr(Messages) {
+    Lint() : FunctionPass(ID) {
       initializeLintPass(*PassRegistry::getPassRegistry());
     }
 
@@ -181,7 +180,7 @@ bool Lint::runOnFunction(Function &F) {
   TLI = &getAnalysis<TargetLibraryInfo>();
   visit(F);
   dbgs() << MessagesStr.str();
-  Messages.clear();
+  MessagesStr.clear();
   return false;
 }
 
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index a528a7e..92a063a 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -28,10 +28,9 @@
 using namespace llvm;
 
 static std::string getTypeString(Type *T) {
-  std::string Result;
-  raw_string_ostream Tmp(Result);
-  Tmp << *T;
-  return Tmp.str();
+  StringBuilder Result;
+  Result << *T;
+  return Result.str();
 }
 
 /// Run: module ::= toplevelentity*
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 996dc21..d69c2e0 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1586,8 +1586,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) {
 
     // Otherwise report the problem to the user.
     {
-      std::string S;
-      raw_string_ostream OS(S);
+      StringBuilder OS;
       OS << "Unsupported expression in static initializer: ";
       CE->printAsOperand(OS, /*PrintType=*/false,
                      !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 46ee0c8..cf48e6e 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -241,8 +241,7 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
         }
       }
       if (Error) {
-        std::string msg;
-        raw_string_ostream Msg(msg);
+        StringBuilder Msg;
         Msg << "invalid operand in inline asm: '" << AsmStr << "'";
         MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
       }
@@ -413,8 +412,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
           }
         }
         if (Error) {
-          std::string msg;
-          raw_string_ostream Msg(msg);
+          StringBuilder Msg;
           Msg << "invalid operand in inline asm: '" << AsmStr << "'";
           MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
         }
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp
index 74af1e2..7f07393 100644
--- a/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/lib/CodeGen/MachineBlockPlacement.cpp
@@ -264,23 +264,19 @@ INITIALIZE_PASS_END(MachineBlockPlacement, "block-placement2",
 ///
 /// Only used by debug logging.
 static std::string getBlockName(MachineBasicBlock *BB) {
-  std::string Result;
-  raw_string_ostream OS(Result);
+  StringBuilder OS;
   OS << "BB#" << BB->getNumber()
      << " (derived from LLVM BB '" << BB->getName() << "')";
-  OS.flush();
-  return Result;
+  return OS.str();
 }
 
 /// \brief Helper to print the number of a MBB.
 ///
 /// Only used by debug logging.
 static std::string getBlockNum(MachineBasicBlock *BB) {
-  std::string Result;
-  raw_string_ostream OS(Result);
+  StringBuilder OS;
   OS << "BB#" << BB->getNumber();
-  OS.flush();
-  return Result;
+  return OS.str();
 }
 #endif
 
diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp
index cbe937a..e2d4a1a 100644
--- a/lib/CodeGen/MachineScheduler.cpp
+++ b/lib/CodeGen/MachineScheduler.cpp
@@ -3231,8 +3231,7 @@ struct DOTGraphTraits<ScheduleDAGMI*> : public DefaultDOTGraphTraits {
   }
 
   static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G) {
-    std::string Str;
-    raw_string_ostream SS(Str);
+    StringBuilder SS;
     const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
     const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
       static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index 92a9a30..0b7c78a 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -1197,8 +1197,7 @@ void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const {
 }
 
 std::string ScheduleDAGInstrs::getGraphNodeLabel(const SUnit *SU) const {
-  std::string s;
-  raw_string_ostream oss(s);
+  StringBuilder oss;
   if (SU == &EntrySU)
     oss << "<entry>";
   else if (SU == &ExitSU)
diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp
index a33548e..1023193 100644
--- a/lib/DebugInfo/DWARFDebugFrame.cpp
+++ b/lib/DebugInfo/DWARFDebugFrame.cpp
@@ -353,10 +353,9 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
 
     if (Offset != EndStructureOffset) {
-      std::string Str;
-      raw_string_ostream OS(Str);
-      OS << format("Parsing entry instructions at %lx failed", StartOffset);
-      report_fatal_error(Str);
+      StringBuilder Str;
+      Str << format("Parsing entry instructions at %lx failed", StartOffset);
+      report_fatal_error(Str.str());
     }
   }
 }
diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index f24704c..2431d70 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -110,14 +110,10 @@ unsigned LLVMGetMDKindID(const char* Name, unsigned SLen) {
 }
 
 char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI) {
-  std::string MsgStorage;
-  raw_string_ostream Stream(MsgStorage);
-  DiagnosticPrinterRawOStream DP(Stream);
-
+  StringBuilder Msg;
+  DiagnosticPrinterRawOStream DP(Msg);
   unwrap(DI)->print(DP);
-  Stream.flush();
-
-  return LLVMCreateMessage(MsgStorage.c_str());
+  return LLVMCreateMessage(Msg.str().c_str());
 }
 
 LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI){
@@ -201,13 +197,9 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
 }
 
 char *LLVMPrintModuleToString(LLVMModuleRef M) {
-  std::string buf;
-  raw_string_ostream os(buf);
-
+  StringBuilder os;
   unwrap(M)->print(os, nullptr);
-  os.flush();
-
-  return strdup(buf.c_str());
+  return strdup(os.str().c_str());
 }
 
 /*--.. Operations on inline assembler ......................................--*/
@@ -278,14 +270,10 @@ void LLVMDumpType(LLVMTypeRef Ty) {
 }
 
 char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
-  std::string buf;
-  raw_string_ostream os(buf);
-
+  StringBuilder os;
   assert(unwrap(Ty) != nullptr && "Expecting non-null Type");
   unwrap(Ty)->print(os);
-  os.flush();
-
-  return strdup(buf.c_str());
+  return strdup(os.str().c_str());
 }
 
 /*--.. Operations on integer types .........................................--*/
@@ -529,14 +517,10 @@ void LLVMDumpValue(LLVMValueRef Val) {
 }
 
 char* LLVMPrintValueToString(LLVMValueRef Val) {
-  std::string buf;
-  raw_string_ostream os(buf);
-
+  StringBuilder os;
   assert(unwrap(Val) != nullptr && "Expecting non-null Value");
   unwrap(Val)->print(os);
-  os.flush();
-
-  return strdup(buf.c_str());
+  return strdup(os.str().c_str());
 }
 
 void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) {
diff --git a/lib/IRReader/IRReader.cpp b/lib/IRReader/IRReader.cpp
index f4ed437..c1f6c71 100644
--- a/lib/IRReader/IRReader.cpp
+++ b/lib/IRReader/IRReader.cpp
@@ -108,13 +108,9 @@ LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef,
 
   if(!*OutM) {
     if (OutMessage) {
-      std::string buf;
-      raw_string_ostream os(buf);
-
+      StringBuilder os;
       Diag.print(nullptr, os, false);
-      os.flush();
-
-      *OutMessage = strdup(buf.c_str());
+      *OutMessage = strdup(os.str().c_str());
     }
     return 1;
   }
diff --git a/lib/Target/TargetMachineC.cpp b/lib/Target/TargetMachineC.cpp
index 20923c9..cf04faa 100644
--- a/lib/Target/TargetMachineC.cpp
+++ b/lib/Target/TargetMachineC.cpp
@@ -237,13 +237,11 @@ LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
 LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
   LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
   LLVMMemoryBufferRef *OutMemBuf) {
-  std::string CodeString;
-  raw_string_ostream OStream(CodeString);
-  formatted_raw_ostream Out(OStream);
+  StringBuilder Code;
+  formatted_raw_ostream Out(Code);
   bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage);
-  OStream.flush();
 
-  std::string &Data = OStream.str();
+  std::string &Data = Code.str();
   *OutMemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.c_str(),
                                                      Data.length(), "");
   return Result;
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index 77914c5..6618464 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -686,8 +686,7 @@ static void writeSymbolTable(
     std::vector<std::pair<unsigned, unsigned> > &MemberOffsetRefs) {
   unsigned StartOffset = 0;
   unsigned MemberNum = 0;
-  std::string NameBuf;
-  raw_string_ostream NameOS(NameBuf);
+  StringBuilder NameOS;
   unsigned NumSyms = 0;
   std::vector<object::SymbolicFile *> DeleteIt;
   LLVMContext &Context = getGlobalContext();
diff --git a/tools/llvm-readobj/ARMWinEHPrinter.cpp b/tools/llvm-readobj/ARMWinEHPrinter.cpp
index d82b847..de4c058 100644
--- a/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -95,8 +95,7 @@ raw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {
 
 static std::string formatSymbol(StringRef Name, uint64_t Address,
                                 uint64_t Offset = 0) {
-  std::string Buffer;
-  raw_string_ostream OS(Buffer);
+  StringBuilder OS;
 
   if (!Name.empty())
     OS << Name << " ";
diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp
index c64d362..f876d46 100644
--- a/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/tools/llvm-readobj/Win64EHDumper.cpp
@@ -115,8 +115,7 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
 static std::string formatSymbol(const Dumper::Context &Ctx,
                                 const coff_section *Section, uint64_t Offset,
                                 uint32_t Displacement) {
-  std::string Buffer;
-  raw_string_ostream OS(Buffer);
+  StringBuilder OS;
 
   StringRef Name;
   SymbolRef Symbol;
@@ -131,6 +130,7 @@ static std::string formatSymbol(const Dumper::Context &Ctx,
     OS << format(" +0x%X (0x%" PRIX64 ")", Displacement, Offset);
   else
     OS << format(" (0x%" PRIX64 ")", Offset);
+
   return OS.str();
 }
 
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 4d0c0ca..e909cf3 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -319,8 +319,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
 
   // Default case: unhandled opcode
   o << "  default:\n"
-    << "    std::string msg;\n"
-    << "    raw_string_ostream Msg(msg);\n"
+    << "    StringBuilder Msg;\n"
     << "    Msg << \"Not supported instr: \" << MI;\n"
     << "    report_fatal_error(Msg.str());\n"
     << "  }\n"


More information about the llvm-commits mailing list