Remove all mutations of OutputFile objects.

The purpose of this is to allow OutputFile to store a StringAtom, which
requires it to be immutable. Doing so would allow us to cheaply copy
OutputFile objects.

Bug: 491925153
Change-Id: I5c535d2d36427a9918577cc0ae5fd6246a6a6964
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/23920
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: Matt Stark <msta@google.com>
diff --git a/src/gn/ninja_c_binary_target_writer.cc b/src/gn/ninja_c_binary_target_writer.cc
index 6d870da..a56f587 100644
--- a/src/gn/ninja_c_binary_target_writer.cc
+++ b/src/gn/ninja_c_binary_target_writer.cc
@@ -565,7 +565,9 @@
   }
 
   OutputFile link_phony = target_->dependency_output();
-  link_phony.append(".linkdeps");
+  std::string path(link_phony.value());
+  path.append(".linkdeps");
+  link_phony = OutputFile(std::move(path));
 
   out_ << "build ";
   path_output_.WriteFile(out_, link_phony);
diff --git a/src/gn/ninja_target_command_util.cc b/src/gn/ninja_target_command_util.cc
index 825d644..713af4a 100644
--- a/src/gn/ninja_target_command_util.cc
+++ b/src/gn/ninja_target_command_util.cc
@@ -146,8 +146,9 @@
       NOTREACHED() << "No outputs for no PCH type.";
       break;
   }
-  output_value.resize(extension_offset);
-  output_value.append(output_extension);
+  std::string path(output_value.value().substr(0, extension_offset));
+  path.append(output_extension);
+  output_value = OutputFile(std::move(path));
 }
 
 std::string GetGCCPCHOutputExtension(const char* tool_name) {
diff --git a/src/gn/ninja_utils.cc b/src/gn/ninja_utils.cc
index 8a4ae8c..bf30bfb 100644
--- a/src/gn/ninja_utils.cc
+++ b/src/gn/ninja_utils.cc
@@ -32,7 +32,6 @@
 
 OutputFile GetPublicInputsOutputFile(const Target* target,
                                      const BuildSettings* build_settings) {
-  OutputFile result;
   if (build_settings->no_stamp_files()) {
     return GetOutputFile(*target, BuildDirType::PHONY, target->label().name(),
                          ".public_inputs");
diff --git a/src/gn/resolved_target_data.cc b/src/gn/resolved_target_data.cc
index 90063d9..fe906d7 100644
--- a/src/gn/resolved_target_data.cc
+++ b/src/gn/resolved_target_data.cc
@@ -331,7 +331,9 @@
   } else if (target->has_dependency_output()) {
     OutputFile dep_output = target->dependency_output();
     if (target->output_type() == Target::SOURCE_SET) {
-      dep_output.append(".linkdeps");
+      std::string path(dep_output.value());
+      path.append(".linkdeps");
+      dep_output = OutputFile(std::move(path));
     }
     all_order_only_deps.push_back(dep_output);
   }
diff --git a/src/gn/runtime_deps.cc b/src/gn/runtime_deps.cc
index 855365d..997f64f 100644
--- a/src/gn/runtime_deps.cc
+++ b/src/gn/runtime_deps.cc
@@ -183,11 +183,13 @@
       // Force the first output for shared-library-type linker outputs since
       // the dependency output files might not be the main output.
       CHECK(!target->computed_outputs().empty());
-      output_file.emplace(target->computed_outputs()[0]);
-      output_file->append(extension);
+      std::string path(target->computed_outputs()[0].value());
+      path.append(extension);
+      output_file = OutputFile(std::move(path));
     } else if (target->has_dependency_output_file()) {
-      output_file.emplace(target->dependency_output_file());
-      output_file->append(extension);
+      std::string path(target->dependency_output_file().value());
+      path.append(extension);
+      output_file = OutputFile(std::move(path));
     } else {
       // If there is no dependency_output_file, this target's dependency output
       // is either a phony alias or was elided entirely (due to lack of real
diff --git a/src/gn/substitution_writer.cc b/src/gn/substitution_writer.cc
index 52d0c81..b6d0c48 100644
--- a/src/gn/substitution_writer.cc
+++ b/src/gn/substitution_writer.cc
@@ -472,15 +472,16 @@
     const Target* target,
     const SourceFile& source,
     const SubstitutionPattern& pattern) {
-  OutputFile result;
+  std::string result_path;
   for (const auto& subrange : pattern.ranges()) {
     if (subrange.type == &SubstitutionLiteral) {
-      result.append(subrange.literal);
+      result_path.append(subrange.literal);
     } else {
-      result.append(GetCompilerSubstitution(target, source, subrange.type));
+      result_path.append(
+          GetCompilerSubstitution(target, source, subrange.type));
     }
   }
-  return result;
+  return OutputFile(result_path);
 }
 
 // static
@@ -514,15 +515,15 @@
     const Target* target,
     const Tool* tool,
     const SubstitutionPattern& pattern) {
-  OutputFile result;
+  std::string result_path;
   for (const auto& subrange : pattern.ranges()) {
     if (subrange.type == &SubstitutionLiteral) {
-      result.append(subrange.literal);
+      result_path.append(subrange.literal);
     } else {
-      result.append(GetLinkerSubstitution(target, tool, subrange.type));
+      result_path.append(GetLinkerSubstitution(target, tool, subrange.type));
     }
   }
-  return result;
+  return OutputFile(result_path);
 }
 
 // static