Sfoglia il codice sorgente

Source sweep: Use cmStrCat for string concatenation

This patch is generated by a python script that uses regular expressions to
search for string concatenation patterns of the kind

```
std::string str = <ARG0>;
str += <ARG1>;
str += <ARG2>;
...
```

and replaces them with a single `cmStrCat` call

```
std::string str = cmStrCat(<ARG0>, <ARG1>, <ARG2>, ...);
```

If any `<ARGX>` is itself a concatenated string of the kind

```
a + b + c + ...;
```

then `<ARGX>` is split into multiple arguments for the `cmStrCat` call.

If there's a sequence of literals in the `<ARGX>`, then all literals in the
sequence are concatenated and merged into a single literal argument for
the `cmStrCat` call.

Single character strings are converted to single char arguments for
the `cmStrCat` call.

`std::to_string(...)` wrappings are removed from `cmStrCat` arguments,
because it supports numeric types as well as string types.

`arg.substr(x)` arguments to `cmStrCat` are replaced with
`cm::string_view(arg).substr(x)`
Sebastian Holtermann 6 anni fa
parent
commit
9b334397f5
100 ha cambiato i file con 932 aggiunte e 1451 eliminazioni
  1. 3 4
      Source/CPack/IFW/cmCPackIFWGenerator.cxx
  2. 2 2
      Source/CPack/IFW/cmCPackIFWInstaller.cxx
  3. 3 5
      Source/CPack/WiX/cmCPackWIXGenerator.cxx
  4. 2 2
      Source/CPack/cmCPackArchiveGenerator.cxx
  5. 4 6
      Source/CPack/cmCPackBundleGenerator.cxx
  6. 2 3
      Source/CPack/cmCPackComponentGroup.cxx
  7. 4 6
      Source/CPack/cmCPackCygwinBinaryGenerator.cxx
  8. 15 17
      Source/CPack/cmCPackCygwinSourceGenerator.cxx
  9. 11 17
      Source/CPack/cmCPackDebGenerator.cxx
  10. 7 9
      Source/CPack/cmCPackDragNDropGenerator.cxx
  11. 17 24
      Source/CPack/cmCPackGenerator.cxx
  12. 29 39
      Source/CPack/cmCPackNSISGenerator.cxx
  13. 16 26
      Source/CPack/cmCPackOSXX11Generator.cxx
  14. 18 28
      Source/CPack/cmCPackPKGGenerator.cxx
  15. 21 27
      Source/CPack/cmCPackPackageMakerGenerator.cxx
  16. 9 14
      Source/CPack/cmCPackProductBuildGenerator.cxx
  17. 2 4
      Source/CPack/cmCPackRPMGenerator.cxx
  18. 2 2
      Source/CPack/cpack.cxx
  19. 3 3
      Source/CTest/cmCTestBuildAndTestHandler.cxx
  20. 3 3
      Source/CTest/cmCTestBuildCommand.cxx
  21. 12 19
      Source/CTest/cmCTestBuildHandler.cxx
  22. 3 2
      Source/CTest/cmCTestCVS.cxx
  23. 2 3
      Source/CTest/cmCTestConfigureCommand.cxx
  24. 14 23
      Source/CTest/cmCTestCoverageHandler.cxx
  25. 2 3
      Source/CTest/cmCTestCurl.cxx
  26. 2 2
      Source/CTest/cmCTestGIT.cxx
  27. 9 22
      Source/CTest/cmCTestLaunch.cxx
  28. 12 19
      Source/CTest/cmCTestRunTest.cxx
  29. 3 3
      Source/CTest/cmCTestSVN.cxx
  30. 13 20
      Source/CTest/cmCTestScriptHandler.cxx
  31. 15 38
      Source/CTest/cmCTestTestHandler.cxx
  32. 7 12
      Source/CTest/cmCTestUpdateHandler.cxx
  33. 2 3
      Source/CTest/cmParseCacheCoverage.cxx
  34. 1 3
      Source/CTest/cmParseGTMCoverage.cxx
  35. 1 3
      Source/CTest/cmParseJacocoCoverage.cxx
  36. 2 2
      Source/CTest/cmParseMumpsCoverage.cxx
  37. 2 3
      Source/CTest/cmParsePHPCoverage.cxx
  38. 2 2
      Source/CTest/cmProcess.cxx
  39. 2 2
      Source/CursesDialog/cmCursesMainForm.cxx
  40. 4 4
      Source/QtDialog/FirstConfigure.cxx
  41. 2 2
      Source/cmAddCustomCommandCommand.cxx
  42. 2 2
      Source/cmAddCustomTargetCommand.cxx
  43. 5 9
      Source/cmAddSubDirectoryCommand.cxx
  44. 39 47
      Source/cmArchiveWrite.cxx
  45. 2 6
      Source/cmAuxSourceDirectoryCommand.cxx
  46. 2 6
      Source/cmCPluginAPI.cxx
  47. 11 18
      Source/cmCTest.cxx
  48. 16 26
      Source/cmCacheManager.cxx
  49. 1 3
      Source/cmCommandArgumentParserHelper.cxx
  50. 8 12
      Source/cmCommonTargetGenerator.cxx
  51. 2 4
      Source/cmComputeLinkDepends.cxx
  52. 30 63
      Source/cmComputeLinkInformation.cxx
  53. 3 2
      Source/cmConfigureFileCommand.cxx
  54. 3 7
      Source/cmCoreTryCompile.cxx
  55. 5 8
      Source/cmCreateTestSourceList.cxx
  56. 3 2
      Source/cmCurl.cxx
  57. 1 3
      Source/cmCustomCommandGenerator.cxx
  58. 3 6
      Source/cmDepends.cxx
  59. 9 14
      Source/cmDependsC.cxx
  60. 12 31
      Source/cmDependsFortran.cxx
  61. 4 7
      Source/cmExecProgramCommand.cxx
  62. 1 2
      Source/cmExportBuildAndroidMKGenerator.cxx
  63. 3 6
      Source/cmExportBuildFileGenerator.cxx
  64. 2 5
      Source/cmExportCommand.cxx
  65. 7 10
      Source/cmExportFileGenerator.cxx
  66. 2 2
      Source/cmExportInstallAndroidMKGenerator.cxx
  67. 5 13
      Source/cmExportInstallFileGenerator.cxx
  68. 3 4
      Source/cmExportLibraryDependenciesCommand.cxx
  69. 5 7
      Source/cmExprParserHelper.cxx
  70. 3 2
      Source/cmExternalMakefileProjectGenerator.cxx
  71. 13 20
      Source/cmExtraCodeBlocksGenerator.cxx
  72. 6 8
      Source/cmExtraCodeLiteGenerator.cxx
  73. 13 26
      Source/cmExtraEclipseCDT4Generator.cxx
  74. 8 14
      Source/cmExtraKateGenerator.cxx
  75. 4 6
      Source/cmExtraSublimeTextGenerator.cxx
  76. 5 6
      Source/cmFLTKWrapUICommand.cxx
  77. 1 3
      Source/cmFileAPI.cxx
  78. 40 51
      Source/cmFileCommand.cxx
  79. 8 13
      Source/cmFileCopier.cxx
  80. 7 7
      Source/cmFileInstaller.cxx
  81. 3 9
      Source/cmFindBase.cxx
  82. 3 4
      Source/cmFindCommon.cxx
  83. 5 12
      Source/cmFindLibraryCommand.cxx
  84. 43 79
      Source/cmFindPackageCommand.cxx
  85. 5 11
      Source/cmFindPathCommand.cxx
  86. 1 2
      Source/cmFindProgramCommand.cxx
  87. 4 6
      Source/cmFortranParserImpl.cxx
  88. 3 3
      Source/cmFunctionCommand.cxx
  89. 6 8
      Source/cmGeneratorExpressionNode.cxx
  90. 73 107
      Source/cmGeneratorTarget.cxx
  91. 2 3
      Source/cmGetDirectoryPropertyCommand.cxx
  92. 3 3
      Source/cmGetPropertyCommand.cxx
  93. 24 32
      Source/cmGhsMultiTargetGenerator.cxx
  94. 2 2
      Source/cmGlobVerificationManager.cxx
  95. 62 101
      Source/cmGlobalGenerator.cxx
  96. 26 39
      Source/cmGlobalGhsMultiGenerator.cxx
  97. 2 4
      Source/cmGlobalMSYSMakefileGenerator.cxx
  98. 24 29
      Source/cmGlobalNinjaGenerator.cxx
  99. 46 69
      Source/cmGlobalUnixMakefileGenerator3.cxx
  100. 13 16
      Source/cmGlobalVisualStudio10Generator.cxx

+ 3 - 4
Source/CPack/IFW/cmCPackIFWGenerator.cxx

@@ -35,8 +35,7 @@ int cmCPackIFWGenerator::PackageFiles()
   this->Installer.GeneratePackageFiles();
 
   std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  std::string ifwTmpFile = ifwTLD;
-  ifwTmpFile += "/IFWOutput.log";
+  std::string ifwTmpFile = cmStrCat(ifwTLD, "/IFWOutput.log");
 
   // Run repogen
   if (!this->Installer.RemoteRepositories.empty()) {
@@ -117,8 +116,8 @@ int cmCPackIFWGenerator::PackageFiles()
 
   // Run binary creator
   {
-    std::string ifwCmd = this->BinCreator;
-    ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+    std::string ifwCmd =
+      cmStrCat(this->BinCreator, " -c ", this->toplevel, "/config/config.xml");
 
     if (!this->Installer.Resources.empty()) {
       ifwCmd += " -r ";

+ 2 - 2
Source/CPack/IFW/cmCPackIFWInstaller.cxx

@@ -193,8 +193,8 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
     this->TargetDir = optIFW_TARGET_DIRECTORY;
   } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
                this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
-    this->TargetDir = "@ApplicationsDir@/";
-    this->TargetDir += optPACKAGE_INSTALL_DIRECTORY;
+    this->TargetDir =
+      cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY);
   } else {
     this->TargetDir = "@RootDir@/usr/local";
   }

+ 3 - 5
Source/CPack/WiX/cmCPackWIXGenerator.cxx

@@ -11,6 +11,7 @@
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmUuid.h"
+#include "cm_string_view.hxx"
 #include <algorithm>
 
 #include "cmWIXDirectoriesSourceWriter.h"
@@ -519,9 +520,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
     for (auto const& i : this->Components) {
       cmCPackComponent const& component = i.second;
 
-      std::string componentPath = toplevel;
-      componentPath += "/";
-      componentPath += component.Name;
+      std::string componentPath = cmStrCat(toplevel, '/', component.Name);
 
       std::string const componentFeatureId = "CM_C_" + component.Name;
 
@@ -1087,8 +1086,7 @@ std::string cmCPackWIXGenerator::CreateHashedId(
   cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
   std::string const hash = sha1.HashString(path);
 
-  std::string identifier;
-  identifier += hash.substr(0, 7) + "_";
+  std::string identifier = cmStrCat(cm::string_view(hash).substr(0, 7), '_');
 
   const size_t maxFileNameLength = 52;
   if (normalizedFilename.length() > maxFileNameLength) {

+ 2 - 2
Source/CPack/cmCPackArchiveGenerator.cxx

@@ -6,6 +6,7 @@
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 
@@ -71,8 +72,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
   }
   std::string filePrefix;
   if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
-    filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
-    filePrefix += "/";
+    filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/');
   }
   const char* installPrefix =
     this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");

+ 4 - 6
Source/CPack/cmCPackBundleGenerator.cxx

@@ -41,9 +41,8 @@ int cmCPackBundleGenerator::InitializeInternal()
 
 const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
 {
-  this->InstallPrefix = "/";
-  this->InstallPrefix += this->GetOption("CPACK_BUNDLE_NAME");
-  this->InstallPrefix += ".app/Contents/Resources";
+  this->InstallPrefix = cmStrCat('/', this->GetOption("CPACK_BUNDLE_NAME"),
+                                 ".app/Contents/Resources");
 
   return this->InstallPrefix.c_str();
 }
@@ -191,9 +190,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
   if (!cpack_apple_cert_app.empty()) {
     std::string output;
     std::string bundle_path;
-    bundle_path = src_dir + "/";
-    bundle_path += this->GetOption("CPACK_BUNDLE_NAME");
-    bundle_path += ".app";
+    bundle_path =
+      cmStrCat(src_dir, '/', this->GetOption("CPACK_BUNDLE_NAME"), ".app");
 
     // A list of additional files to sign, ie. frameworks and plugins.
     const std::string sign_parameter =

+ 2 - 3
Source/CPack/cmCPackComponentGroup.cxx

@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackComponentGroup.h"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <string>
@@ -14,9 +15,7 @@ unsigned long cmCPackComponent::GetInstalledSize(
   }
 
   for (std::string const& file : this->Files) {
-    std::string path = installDir;
-    path += '/';
-    path += file;
+    std::string path = cmStrCat(installDir, '/', file);
     this->TotalSize += cmSystemTools::FileLength(path);
   }
 

+ 4 - 6
Source/CPack/cmCPackCygwinBinaryGenerator.cxx

@@ -28,13 +28,11 @@ int cmCPackCygwinBinaryGenerator::InitializeInternal()
 
 int cmCPackCygwinBinaryGenerator::PackageFiles()
 {
-  std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
-  packageName += "-";
-  packageName += this->GetOption("CPACK_PACKAGE_VERSION");
+  std::string packageName =
+    cmStrCat(this->GetOption("CPACK_PACKAGE_NAME"), '-',
+             this->GetOption("CPACK_PACKAGE_VERSION"));
   packageName = cmsys::SystemTools::LowerCase(packageName);
-  std::string manifest = "/usr/share/doc/";
-  manifest += packageName;
-  manifest += "/MANIFEST";
+  std::string manifest = cmStrCat("/usr/share/doc/", packageName, "/MANIFEST");
   std::string manifestFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
   // Create a MANIFEST file that contains all of the files in
   // the tar file

+ 15 - 17
Source/CPack/cmCPackCygwinSourceGenerator.cxx

@@ -37,8 +37,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
 {
   // Create a tar file of the sources
   std::string packageDirFileName =
-    this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-  packageDirFileName += ".tar.bz2";
+    cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".tar.bz2");
   packageFileNames[0] = packageDirFileName;
   std::string output;
   // skip one parent up to the cmCPackTarBZip2Generator
@@ -94,8 +93,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
                     << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
     return 0;
   }
-  std::string outerTarFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-  outerTarFile += "-";
+  std::string outerTarFile =
+    cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-');
   const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
   if (!patch) {
     cmCPackLogger(cmCPackLog::LOG_WARNING,
@@ -106,19 +105,18 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
   outerTarFile += patch;
   outerTarFile += "-src.tar.bz2";
   std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  std::string buildScript = tmpDir;
-  buildScript += "/";
-  buildScript += cmSystemTools::GetFilenameName(
-    this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"));
-  std::string patchFile = tmpDir;
-  patchFile += "/";
-  patchFile +=
-    cmSystemTools::GetFilenameName(this->GetOption("CPACK_CYGWIN_PATCH_FILE"));
+  std::string buildScript =
+    cmStrCat(tmpDir, '/',
+             cmSystemTools::GetFilenameName(
+               this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT")));
+  std::string patchFile =
+    cmStrCat(tmpDir, '/',
+             cmSystemTools::GetFilenameName(
+               this->GetOption("CPACK_CYGWIN_PATCH_FILE")));
 
   std::string file = cmSystemTools::GetFilenameName(compressOutFile);
-  std::string sourceTar = cmSystemTools::GetFilenamePath(compressOutFile);
-  sourceTar += "/";
-  sourceTar += file;
+  std::string sourceTar =
+    cmStrCat(cmSystemTools::GetFilenamePath(compressOutFile), '/', file);
   /* reset list of file to be packaged */
   files.clear();
   // a source release in cygwin should have the build script used
@@ -140,8 +138,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
 
 const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix()
 {
-  this->InstallPrefix = "/";
-  this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+  this->InstallPrefix =
+    cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
   return this->InstallPrefix.c_str();
 }
 

+ 11 - 17
Source/CPack/cmCPackDebGenerator.cxx

@@ -149,8 +149,7 @@ void DebGenerator::generateControlFile() const
 
   unsigned long totalSize = 0;
   {
-    std::string dirName = TemporaryDir;
-    dirName += '/';
+    std::string dirName = cmStrCat(TemporaryDir, '/');
     for (std::string const& file : PackageFiles) {
       totalSize += cmSystemTools::FileLength(file);
     }
@@ -248,8 +247,7 @@ std::string DebGenerator::generateMD5File() const
 
   cmGeneratedFileStream out(md5filename);
 
-  std::string topLevelWithTrailingSlash = TemporaryDir;
-  topLevelWithTrailingSlash += '/';
+  std::string topLevelWithTrailingSlash = cmStrCat(TemporaryDir, '/');
   for (std::string const& file : PackageFiles) {
     // hash only regular files
     if (cmSystemTools::FileIsDirectory(file) ||
@@ -469,8 +467,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
   // Tell CPackDeb.cmake the name of the component GROUP.
   this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName.c_str());
   // Tell CPackDeb.cmake the path where the component is.
-  std::string component_path = "/";
-  component_path += packageName;
+  std::string component_path = cmStrCat('/', packageName);
   this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
                   component_path.c_str());
   if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
@@ -500,9 +497,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
     retval = 0;
   }
   // add the generated package to package file names list
-  packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  packageFileName += "/";
-  packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
+  packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+                             this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
   packageFileNames.push_back(std::move(packageFileName));
 
   if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) {
@@ -524,9 +520,9 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
       retval = 0;
     }
     // add the generated package to package file names list
-    packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    packageFileName += "/";
-    packageFileName += this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME");
+    packageFileName =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+               this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"));
     packageFileNames.push_back(std::move(packageFileName));
   }
 
@@ -614,8 +610,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
 
   if (!compInstDirName.empty()) {
     // Tell CPackDeb.cmake the path where the component is.
-    std::string component_path = "/";
-    component_path += compInstDirName;
+    std::string component_path = cmStrCat('/', compInstDirName);
     this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
                     component_path.c_str());
   }
@@ -644,9 +639,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
     retval = 0;
   }
   // add the generated package to package file names list
-  packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  packageFileName += "/";
-  packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
+  packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+                             this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
   packageFileNames.push_back(std::move(packageFileName));
   return retval;
 }

+ 7 - 9
Source/CPack/cmCPackDragNDropGenerator.cxx

@@ -196,9 +196,7 @@ int cmCPackDragNDropGenerator::PackageFiles()
     full_package_name += std::string(GetOutputExtension());
     packageFileNames.push_back(full_package_name);
 
-    std::string src_dir = toplevel;
-    src_dir += "/";
-    src_dir += package_file;
+    std::string src_dir = cmStrCat(toplevel, '/', package_file);
 
     if (0 == this->CreateDMG(src_dir, full_package_name)) {
       return 0;
@@ -409,8 +407,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
   }
 
   // Create a temporary read-write disk image ...
-  std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  temp_image += "/temp.dmg";
+  std::string temp_image =
+    cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp.dmg");
 
   std::string create_error;
   std::ostringstream temp_image_command;
@@ -522,8 +520,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
   if (!cpack_license_file.empty() || !slaDirectory.empty()) {
     // Use old hardcoded style if sla_dir is not set
     bool oldStyle = slaDirectory.empty();
-    std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    sla_r += "/sla.r";
+    std::string sla_r =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.r");
 
     std::vector<std::string> languages;
     if (!oldStyle) {
@@ -649,8 +647,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
     if (temp_image_format != "UDZO") {
       temp_image_format = "UDZO";
       // convert to UDZO to enable unflatten/flatten
-      std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-      temp_udzo += "/temp-udzo.dmg";
+      std::string temp_udzo = cmStrCat(
+        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp-udzo.dmg");
 
       std::ostringstream udco_image_command;
       udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");

+ 17 - 24
Source/CPack/cmCPackGenerator.cxx

@@ -73,8 +73,8 @@ int cmCPackGenerator::PrepareNames()
     }
   }
 
-  std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
-  tempDirectory += "/_CPack_Packages/";
+  std::string tempDirectory =
+    cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/");
   const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
   if (toplevelTag) {
     tempDirectory += toplevelTag;
@@ -197,8 +197,7 @@ int cmCPackGenerator::InstallProject()
   }
 
   if (setDestDir) {
-    std::string destDir = "DESTDIR=";
-    destDir += tempInstallDirectory;
+    std::string destDir = cmStrCat("DESTDIR=", tempInstallDirectory);
     cmSystemTools::PutEnv(destDir);
   } else {
     // Make sure there is no destdir
@@ -271,8 +270,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
   (void)setDestDir;
   const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
   if (installCommands && *installCommands) {
-    std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX=";
-    tempInstallDirectoryEnv += tempInstallDirectory;
+    std::string tempInstallDirectoryEnv =
+      cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory);
     cmSystemTools::PutEnv(tempInstallDirectoryEnv);
     std::vector<std::string> installCommandsVector;
     cmExpandList(installCommands, installCommandsVector);
@@ -284,8 +283,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
         ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
         cmDuration::zero());
       if (!resB || retVal) {
-        std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-        tmpFile += "/InstallOutput.log";
+        std::string tmpFile = cmStrCat(
+          this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/InstallOutput.log");
         cmGeneratedFileStream ofs(tmpFile);
         ofs << "# Run command: " << ic << std::endl
             << "# Output:" << std::endl
@@ -343,8 +342,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
       std::string top = *it;
       it++;
       std::string subdir = *it;
-      std::string findExpr = top;
-      findExpr += "/*";
+      std::string findExpr = cmStrCat(top, "/*");
       cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                     "- Install directory: " << top << std::endl);
       gl.RecurseOn();
@@ -372,8 +370,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
         if (skip) {
           continue;
         }
-        std::string filePath = tempDir;
-        filePath += "/" + subdir + "/" + cmSystemTools::RelativePath(top, gf);
+        std::string filePath = cmStrCat(tempDir, '/', subdir, '/',
+                                        cmSystemTools::RelativePath(top, gf));
         cmCPackLogger(cmCPackLog::LOG_DEBUG,
                       "Copy file: " << inFile << " -> " << filePath
                                     << std::endl);
@@ -398,8 +396,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
       /* rebuild symlinks in the installed tree */
       if (!symlinkedFiles.empty()) {
         std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
-        std::string goToDir = tempDir;
-        goToDir += "/" + subdir;
+        std::string goToDir = cmStrCat(tempDir, '/', subdir);
         cmCPackLogger(cmCPackLog::LOG_DEBUG,
                       "Change dir to: " << goToDir << std::endl);
         cmWorkingDirectory workdir(goToDir);
@@ -662,8 +659,8 @@ int cmCPackGenerator::RunPreinstallTarget(
       buildCommand, &output, &output, &retVal, installDirectory.c_str(),
       this->GeneratorVerbose, cmDuration::zero());
     if (!resB || retVal) {
-      std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-      tmpFile += "/PreinstallOutput.log";
+      std::string tmpFile = cmStrCat(
+        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/PreinstallOutput.log");
       cmGeneratedFileStream ofs(tmpFile);
       ofs << "# Run command: " << buildCommand << std::endl
           << "# Directory: " << installDirectory << std::endl
@@ -911,10 +908,8 @@ int cmCPackGenerator::InstallCMakeProject(
         GetComponentInstallDirNameSuffix(component);
       if (nullptr != this->GetOption(absoluteDestFileComponent)) {
         std::string absoluteDestFilesListComponent =
-          this->GetOption(absoluteDestFileComponent);
-        absoluteDestFilesListComponent += ";";
-        absoluteDestFilesListComponent +=
-          mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+          cmStrCat(this->GetOption(absoluteDestFileComponent), ';',
+                   mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
         this->SetOption(absoluteDestFileComponent,
                         absoluteDestFilesListComponent.c_str());
       } else {
@@ -1006,8 +1001,7 @@ int cmCPackGenerator::DoPackage()
 
   cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
   cmsys::Glob gl;
-  std::string findExpr = tempDirectory;
-  findExpr += "/*";
+  std::string findExpr = cmStrCat(tempDirectory, "/*");
   gl.RecurseOn();
   gl.SetRecurseListDirs(true);
   gl.SetRecurseThroughSymlinks(false);
@@ -1203,8 +1197,7 @@ const char* cmCPackGenerator::GetInstallPath()
   if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
     this->InstallPath = prgfiles;
   } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
-    this->InstallPath = sysDrive;
-    this->InstallPath += "/Program Files";
+    this->InstallPath = cmStrCat(sysDrive, "/Program Files");
   } else {
     this->InstallPath = "c:/Program Files";
   }

+ 29 - 39
Source/CPack/cmCPackNSISGenerator.cxx

@@ -56,8 +56,7 @@ int cmCPackNSISGenerator::PackageFiles()
   }
 
   std::string nsisFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  std::string tmpFile = nsisFileName;
-  tmpFile += "/NSISOutput.log";
+  std::string tmpFile = cmStrCat(nsisFileName, "/NSISOutput.log");
   std::string nsisInstallOptions = nsisFileName + "/NSIS.InstallOptions.ini";
   nsisFileName += "/project.nsi";
   std::ostringstream str;
@@ -142,39 +141,34 @@ int cmCPackNSISGenerator::PackageFiles()
                             installerIconCode.c_str());
   }
   if (this->IsSet("CPACK_PACKAGE_ICON")) {
-    std::string installerIconCode = "!define MUI_HEADERIMAGE_BITMAP \"";
-    installerIconCode += this->GetOption("CPACK_PACKAGE_ICON");
-    installerIconCode += "\"\n";
+    std::string installerIconCode =
+      cmStrCat("!define MUI_HEADERIMAGE_BITMAP \"",
+               this->GetOption("CPACK_PACKAGE_ICON"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE",
                             installerIconCode.c_str());
   }
 
   if (this->IsSet("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP")) {
-    std::string installerBitmapCode =
-      "!define MUI_WELCOMEFINISHPAGE_BITMAP \"";
-    installerBitmapCode +=
-      this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP");
-    installerBitmapCode += "\"\n";
+    std::string installerBitmapCode = cmStrCat(
+      "!define MUI_WELCOMEFINISHPAGE_BITMAP \"",
+      this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE",
                             installerBitmapCode.c_str());
   }
 
   if (this->IsSet("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP")) {
-    std::string installerBitmapCode =
-      "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"";
-    installerBitmapCode +=
-      this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP");
-    installerBitmapCode += "\"\n";
+    std::string installerBitmapCode = cmStrCat(
+      "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"",
+      this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE",
                             installerBitmapCode.c_str());
   }
 
   if (this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN")) {
-    std::string installerRunCode = "!define MUI_FINISHPAGE_RUN \"$INSTDIR\\";
-    installerRunCode += this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
-    installerRunCode += "\\";
-    installerRunCode += this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN");
-    installerRunCode += "\"\n";
+    std::string installerRunCode =
+      cmStrCat("!define MUI_FINISHPAGE_RUN \"$INSTDIR\\",
+               this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"), '\\',
+               this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE",
                             installerRunCode.c_str());
   }
@@ -297,9 +291,9 @@ int cmCPackNSISGenerator::PackageFiles()
 
   this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions);
   this->ConfigureFile(nsisInFileName, nsisFileName);
-  std::string nsisCmd = "\"";
-  nsisCmd += this->GetOption("CPACK_INSTALLER_PROGRAM");
-  nsisCmd += "\" \"" + nsisFileName + "\"";
+  std::string nsisCmd =
+    cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" \"",
+             nsisFileName, '"');
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
   std::string output;
   int retVal = 1;
@@ -415,8 +409,7 @@ int cmCPackNSISGenerator::InitializeInternal()
   if (!resS || retVal ||
       (!versionRex.find(output) && !versionRexCVS.find(output))) {
     const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    std::string tmpFile = topDir ? topDir : ".";
-    tmpFile += "/NSISOutput.log";
+    std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log");
     cmGeneratedFileStream ofs(tmpFile);
     ofs << "# Run command: " << nsisCmd << std::endl
         << "# Output:" << std::endl
@@ -573,8 +566,7 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
     }
     // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
     // if so add a desktop link
-    std::string desktop = "CPACK_CREATE_DESKTOP_LINK_";
-    desktop += linkName;
+    std::string desktop = cmStrCat("CPACK_CREATE_DESKTOP_LINK_", linkName);
     if (this->IsSet(desktop)) {
       str << "  StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
       str << "    CreateShortCut \"$DESKTOP\\" << linkName
@@ -656,8 +648,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
   if (component->IsDownloaded) {
     if (component->ArchiveFile.empty()) {
       // Compute the name of the archive.
-      std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-      packagesDir += ".dummy";
+      std::string packagesDir =
+        cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy");
       std::ostringstream out;
       out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
           << component->Name << ".zip";
@@ -671,8 +663,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
     if (userUploadDirectory && *userUploadDirectory) {
       uploadDirectory = userUploadDirectory;
     } else {
-      uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
-      uploadDirectory += "/CPackUploads";
+      uploadDirectory =
+        cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads");
     }
     if (!cmSystemTools::FileExists(uploadDirectory)) {
       if (!cmSystemTools::MakeDirectory(uploadDirectory)) {
@@ -709,15 +701,13 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
     }
 
     // The directory where this component's files reside
-    std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-    dirName += '/';
-    dirName += component->Name;
-    dirName += '/';
+    std::string dirName = cmStrCat(
+      this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component->Name, '/');
 
     // Build the list of files to go into this archive, and determine the
     // size of the installed component.
-    std::string zipListFileName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-    zipListFileName += "/winZip.filelist";
+    std::string zipListFileName = cmStrCat(
+      this->GetOption("CPACK_TEMPORARY_DIRECTORY"), "/winZip.filelist");
     bool needQuotesInFile = cmIsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES"));
     unsigned long totalSize = 0;
     { // the scope is needed for cmGeneratedFileStream
@@ -747,8 +737,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
       cmd, &output, &output, &retVal, dirName.c_str(),
       cmSystemTools::OUTPUT_NONE, cmDuration::zero());
     if (!res || retVal) {
-      std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-      tmpFile += "/CompressZip.log";
+      std::string tmpFile = cmStrCat(
+        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/CompressZip.log");
       cmGeneratedFileStream ofs(tmpFile);
       ofs << "# Run command: " << cmd << std::endl
           << "# Output:" << std::endl

+ 16 - 26
Source/CPack/cmCPackOSXX11Generator.cxx

@@ -55,16 +55,14 @@ int cmCPackOSXX11Generator::PackageFiles()
     diskImageDirectory + "/.background";
 
   // App bundle directories
-  std::string packageDirFileName = toplevel;
-  packageDirFileName += "/";
-  packageDirFileName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
-  packageDirFileName += ".app";
+  std::string packageDirFileName = cmStrCat(
+    toplevel, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".app");
   std::string contentsDirectory = packageDirFileName + "/Contents";
   std::string resourcesDirectory = contentsDirectory + "/Resources";
   std::string appDirectory = contentsDirectory + "/MacOS";
   std::string scriptDirectory = resourcesDirectory + "/Scripts";
-  std::string resourceFileName = this->GetOption("CPACK_PACKAGE_FILE_NAME");
-  resourceFileName += ".rsrc";
+  std::string resourceFileName =
+    cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".rsrc");
 
   const char* dir = resourcesDirectory.c_str();
   const char* appdir = appDirectory.c_str();
@@ -113,13 +111,10 @@ int cmCPackOSXX11Generator::PackageFiles()
   }
 
   // Two of the files need to have execute permission, so ensure they do:
-  std::string runTimeScript = dir;
-  runTimeScript += "/";
-  runTimeScript += "RuntimeScript";
+  std::string runTimeScript = cmStrCat(dir, "/RuntimeScript");
 
-  std::string appScriptName = appdir;
-  appScriptName += "/";
-  appScriptName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+  std::string appScriptName =
+    cmStrCat(appdir, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
 
   mode_t mode;
   if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) {
@@ -139,8 +134,8 @@ int cmCPackOSXX11Generator::PackageFiles()
   }
 
   std::string output;
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/hdiutilOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/hdiutilOutput.log");
   std::ostringstream dmgCmd;
   dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
          << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
@@ -228,9 +223,8 @@ bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name)
     return false;
     }
 
-  std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  destFileName += "/Resources/";
-  destFileName += name + ext;
+  std::string destFileName = cmStrCat(
+this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources/", name, ext );
 
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
@@ -245,9 +239,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
   const std::string& name, const std::string& dir,
   const char* outputFileName /* = 0 */, bool copyOnly /* = false */)
 {
-  std::string inFName = "Internal/CPack/CPack.";
-  inFName += name;
-  inFName += ".in";
+  std::string inFName = cmStrCat("Internal/CPack/CPack.", name, ".in");
   std::string inFileName = this->FindTemplate(inFName.c_str());
   if (inFileName.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -259,9 +251,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
     outputFileName = name.c_str();
   }
 
-  std::string destFileName = dir;
-  destFileName += "/";
-  destFileName += outputFileName;
+  std::string destFileName = cmStrCat(dir, '/', outputFileName);
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                 "Configure file: " << inFileName << " to " << destFileName
@@ -272,8 +262,8 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
 
 const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix()
 {
-  this->InstallPrefix = "/";
-  this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME");
-  this->InstallPrefix += ".app/Contents/Resources";
+  this->InstallPrefix =
+    cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"),
+             ".app/Contents/Resources");
   return this->InstallPrefix.c_str();
 }

+ 18 - 28
Source/CPack/cmCPackPKGGenerator.cxx

@@ -7,6 +7,7 @@
 #include "cmCPackComponentGroup.h"
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
@@ -34,8 +35,8 @@ std::string cmCPackPKGGenerator::GetPackageName(
   const cmCPackComponent& component)
 {
   if (component.ArchiveFile.empty()) {
-    std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-    packagesDir += ".dummy";
+    std::string packagesDir =
+      cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy");
     std::ostringstream out;
     out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
         << component.Name << ".pkg";
@@ -56,8 +57,8 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
     return;
   }
 
-  std::string distributionFile = metapackageFile;
-  distributionFile += "/Contents/distribution.dist";
+  std::string distributionFile =
+    cmStrCat(metapackageFile, "/Contents/distribution.dist");
 
   // Create the choice outline, which provides a tree-based view of
   // the components in their groups.
@@ -144,12 +145,9 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group,
 void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
                                        cmXMLWriter& xout)
 {
-  std::string packageId = "com.";
-  packageId += this->GetOption("CPACK_PACKAGE_VENDOR");
-  packageId += '.';
-  packageId += this->GetOption("CPACK_PACKAGE_NAME");
-  packageId += '.';
-  packageId += component.Name;
+  std::string packageId =
+    cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+             this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
 
   xout.StartElement("choice");
   xout.Attribute("id", component.Name + "Choice");
@@ -192,14 +190,13 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
 
   // Create a description of the package associated with this
   // component.
-  std::string relativePackageLocation = "Contents/Packages/";
-  relativePackageLocation += this->GetPackageName(component);
+  std::string relativePackageLocation =
+    cmStrCat("Contents/Packages/", this->GetPackageName(component));
 
   // Determine the installed size of the package.
-  std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-  dirName += '/';
-  dirName += component.Name;
-  dirName += this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+  std::string dirName =
+    cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component.Name,
+             this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
   unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName);
 
   xout.StartElement("pkg-ref");
@@ -282,9 +279,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
     return false;
   }
 
-  std::string destFileName = dirName;
-  destFileName += '/';
-  destFileName += name + ext;
+  std::string destFileName = cmStrCat(dirName, '/', name, ext);
 
   // Set this so that distribution.dist gets the right name (without
   // the path).
@@ -305,9 +300,7 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
     outName = name.c_str();
   }
 
-  std::string inFName = "Internal/CPack/CPack.";
-  inFName += name;
-  inFName += ".in";
+  std::string inFName = cmStrCat("Internal/CPack/CPack.", name, ".in");
   std::string inFileName = this->FindTemplate(inFName.c_str());
   if (inFileName.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -315,9 +308,8 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
     return false;
   }
 
-  std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  destFileName += "/";
-  destFileName += outName;
+  std::string destFileName =
+    cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', outName);
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                 "Configure file: " << inFileName << " to " << destFileName
@@ -330,9 +322,7 @@ int cmCPackPKGGenerator::CopyInstallScript(const std::string& resdir,
                                            const std::string& script,
                                            const std::string& name)
 {
-  std::string dst = resdir;
-  dst += "/";
-  dst += name;
+  std::string dst = cmStrCat(resdir, '/', name);
   cmSystemTools::CopyFileAlways(script, dst);
   cmSystemTools::SetPermissions(dst.c_str(), 0777);
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,

+ 21 - 27
Source/CPack/cmCPackPackageMakerGenerator.cxx

@@ -15,6 +15,7 @@
 #include "cmCPackLog.h"
 #include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
@@ -47,8 +48,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
     this->GetOption("CPACK_TEMPORARY_DIRECTORY");
   if (this->Components.empty()) {
     packageDirFileName += ".pkg";
-    resDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    resDir += "/Resources";
+    resDir =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources");
   } else {
     packageDirFileName += ".mpkg";
     if (!cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str())) {
@@ -58,8 +59,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
       return 0;
     }
 
-    resDir = packageDirFileName;
-    resDir += "/Contents";
+    resDir = cmStrCat(packageDirFileName, "/Contents");
     if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
                     "unable to create package subdirectory " << resDir
@@ -155,8 +155,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
 
   if (!this->Components.empty()) {
     // Create the directory where component packages will be built.
-    std::string basePackageDir = packageDirFileName;
-    basePackageDir += "/Contents/Packages";
+    std::string basePackageDir =
+      cmStrCat(packageDirFileName, "/Contents/Packages");
     if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
                     "Problem creating component packages directory: "
@@ -172,8 +172,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
     if (userUploadDirectory && *userUploadDirectory) {
       uploadDirectory = userUploadDirectory;
     } else {
-      uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
-      uploadDirectory += "/CPackUploads";
+      uploadDirectory =
+        cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads");
     }
 
     // Create packages for each component
@@ -232,9 +232,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
       packageFile += '/';
       packageFile += GetPackageName(compIt->second);
 
-      std::string packageDir = toplevel;
-      packageDir += '/';
-      packageDir += compIt->first;
+      std::string packageDir = cmStrCat(toplevel, '/', compIt->first);
       if (!this->GenerateComponentPackage(
             packageFile.c_str(), packageDir.c_str(), compIt->second)) {
         return 0;
@@ -283,8 +281,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
     WriteDistributionFile(packageDirFileName.c_str());
   }
 
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/hdiutilOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/hdiutilOutput.log");
   std::ostringstream dmgCmd;
   dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
          << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
@@ -461,8 +459,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
 bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command,
                                                    const char* packageFile)
 {
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/PackageMakerOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/PackageMakerOutput.log");
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
   std::string output;
@@ -517,8 +515,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
       this->PackageMakerVersion < 3.0) {
     // Create Description.plist and Info.plist files for normal Mac OS
     // X packages, which work on Mac OS X 10.3 and newer.
-    std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    descriptionFile += '/' + component.Name + "-Description.plist";
+    std::string descriptionFile =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+               component.Name, "-Description.plist");
     cmsys::ofstream out(descriptionFile.c_str());
     cmXMLWriter xout(out);
     xout.StartDocument();
@@ -539,12 +538,10 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
     out.close();
 
     // Create the Info.plist file for this component
-    std::string moduleVersionSuffix = ".";
-    moduleVersionSuffix += component.Name;
+    std::string moduleVersionSuffix = cmStrCat('.', component.Name);
     this->SetOption("CPACK_MODULE_VERSION_SUFFIX",
                     moduleVersionSuffix.c_str());
-    std::string infoFileName = component.Name;
-    infoFileName += "-Info.plist";
+    std::string infoFileName = cmStrCat(component.Name, "-Info.plist");
     if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) {
       return false;
     }
@@ -561,12 +558,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
     // like normal packages, and can be downloaded by the installer
     // on-the-fly in Mac OS X 10.5 or newer. Thus, we need to create
     // flat packages when the packages will be downloaded on the fly.
-    std::string pkgId = "com.";
-    pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
-    pkgId += '.';
-    pkgId += this->GetOption("CPACK_PACKAGE_NAME");
-    pkgId += '.';
-    pkgId += component.Name;
+    std::string pkgId =
+      cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+               this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
 
     pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
            << "\" --root \"" << packageDir << "\""

+ 9 - 14
Source/CPack/cmCPackProductBuildGenerator.cxx

@@ -10,6 +10,7 @@
 #include "cmCPackLog.h"
 #include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
@@ -28,8 +29,8 @@ int cmCPackProductBuildGenerator::PackageFiles()
     this->GetOption("CPACK_TEMPORARY_DIRECTORY");
 
   // Create the directory where component packages will be built.
-  std::string basePackageDir = packageDirFileName;
-  basePackageDir += "/Contents/Packages";
+  std::string basePackageDir =
+    cmStrCat(packageDirFileName, "/Contents/Packages");
   if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "Problem creating component packages directory: "
@@ -41,9 +42,7 @@ int cmCPackProductBuildGenerator::PackageFiles()
     std::map<std::string, cmCPackComponent>::iterator compIt;
     for (compIt = this->Components.begin(); compIt != this->Components.end();
          ++compIt) {
-      std::string packageDir = toplevel;
-      packageDir += '/';
-      packageDir += compIt->first;
+      std::string packageDir = cmStrCat(toplevel, '/', compIt->first);
       if (!this->GenerateComponentPackage(basePackageDir,
                                           GetPackageName(compIt->second),
                                           packageDir, &compIt->second)) {
@@ -138,8 +137,8 @@ int cmCPackProductBuildGenerator::InitializeInternal()
 
 bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command)
 {
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/ProductBuildOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/ProductBuildOutput.log");
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
   std::string output;
@@ -166,9 +165,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
   const std::string& packageFileDir, const std::string& packageFileName,
   const std::string& packageDir, const cmCPackComponent* component)
 {
-  std::string packageFile = packageFileDir;
-  packageFile += '/';
-  packageFile += packageFileName;
+  std::string packageFile = cmStrCat(packageFileDir, '/', packageFileName);
 
   cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                 "-   Building component package: " << packageFile
@@ -206,10 +203,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
   // The command that will be used to run ProductBuild
   std::ostringstream pkgCmd;
 
-  std::string pkgId = "com.";
-  pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
-  pkgId += '.';
-  pkgId += this->GetOption("CPACK_PACKAGE_NAME");
+  std::string pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"),
+                               '.', this->GetOption("CPACK_PACKAGE_NAME"));
   if (component) {
     pkgId += '.';
     pkgId += component->Name;

+ 2 - 4
Source/CPack/cmCPackRPMGenerator.cxx

@@ -82,8 +82,7 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
   // Tell CPackRPM.cmake the name of the component NAME.
   this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str());
   // Tell CPackRPM.cmake the path where the component is.
-  std::string component_path = "/";
-  component_path += packageName;
+  std::string component_path = cmStrCat('/', packageName);
   this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
                   component_path.c_str());
   if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
@@ -376,8 +375,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
 
   if (!compInstDirName.empty()) {
     // Tell CPackRPM.cmake the path where the component is.
-    std::string component_path = "/";
-    component_path += compInstDirName;
+    std::string component_path = cmStrCat('/', compInstDirName);
     this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
                     component_path.c_str());
   }

+ 2 - 2
Source/CPack/cpack.cxx

@@ -230,8 +230,8 @@ int main(int argc, char const* const* argv)
 
   bool cpackConfigFileSpecified = true;
   if (cpackConfigFile.empty()) {
-    cpackConfigFile = cmSystemTools::GetCurrentWorkingDirectory();
-    cpackConfigFile += "/CPackConfig.cmake";
+    cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(),
+                               "/CPackConfig.cmake");
     cpackConfigFileSpecified = false;
   }
 

+ 3 - 3
Source/CTest/cmCTestBuildAndTestHandler.cxx

@@ -7,6 +7,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 #include "cmake.h"
@@ -289,9 +290,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
   std::vector<std::string> extraPaths;
   // if this->ExecutableDirectory is set try that as well
   if (!this->ExecutableDirectory.empty()) {
-    std::string tempPath = this->ExecutableDirectory;
-    tempPath += "/";
-    tempPath += this->TestCommand;
+    std::string tempPath =
+      cmStrCat(this->ExecutableDirectory, '/', this->TestCommand);
     extraPaths.push_back(tempPath);
   }
   std::vector<std::string> failed;

+ 3 - 3
Source/CTest/cmCTestBuildCommand.cxx

@@ -7,6 +7,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -90,9 +91,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
           this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
             cmakeGeneratorName);
         if (!this->GlobalGenerator) {
-          std::string e = "could not create generator named \"";
-          e += cmakeGeneratorName;
-          e += "\"";
+          std::string e = cmStrCat("could not create generator named \"",
+                                   cmakeGeneratorName, '"');
           this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
           cmSystemTools::SetFatalErrorOccured();
           return nullptr;

+ 12 - 19
Source/CTest/cmCTestBuildHandler.cxx

@@ -565,8 +565,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
   std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
   // make sure the source dir is in the correct case on windows
   // via a call to collapse full path.
-  srcdir = cmSystemTools::CollapseFullPath(srcdir);
-  srcdir += "/";
+  srcdir = cmStrCat(cmSystemTools::CollapseFullPath(srcdir), '/');
   for (it = ew.begin();
        it != ew.end() && (numErrorsAllowed || numWarningsAllowed); it++) {
     cmCTestBuildErrorWarning* cm = &(*it);
@@ -697,10 +696,8 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
   } else {
     // Compute a directory in which to store launcher fragments.
     std::string& launchDir = this->Handler->CTestLaunchDir;
-    launchDir = this->CTest->GetBinaryDir();
-    launchDir += "/Testing/";
-    launchDir += tag;
-    launchDir += "/Build";
+    launchDir =
+      cmStrCat(this->CTest->GetBinaryDir(), "/Testing/", tag, "/Build");
 
     // Clean out any existing launcher fragments.
     cmSystemTools::RemoveADirectory(launchDir);
@@ -709,8 +706,7 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
       // Enable launcher fragments.
       cmSystemTools::MakeDirectory(launchDir);
       this->WriteLauncherConfig();
-      std::string launchEnv = "CTEST_LAUNCH_LOGS=";
-      launchEnv += launchDir;
+      std::string launchEnv = cmStrCat("CTEST_LAUNCH_LOGS=", launchDir);
       cmSystemTools::PutEnv(launchEnv);
     }
   }
@@ -736,8 +732,8 @@ void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig()
                             this->Handler->ReallyCustomWarningExceptions);
 
   // Give some testing configuration information to the launcher.
-  std::string fname = this->Handler->CTestLaunchDir;
-  fname += "/CTestLaunchConfig.cmake";
+  std::string fname =
+    cmStrCat(this->Handler->CTestLaunchDir, "/CTestLaunchConfig.cmake");
   cmGeneratedFileStream fout(fname);
   std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
   fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n";
@@ -749,10 +745,8 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers(
   if (matchers.empty()) {
     return;
   }
-  std::string fname = this->Handler->CTestLaunchDir;
-  fname += "/Custom";
-  fname += purpose;
-  fname += ".txt";
+  std::string fname =
+    cmStrCat(this->Handler->CTestLaunchDir, "/Custom", purpose, ".txt");
   cmGeneratedFileStream fout(fname);
   for (std::string const& m : matchers) {
     fout << m << "\n";
@@ -891,9 +885,8 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command,
         // dashboard.
         cmCTestBuildErrorWarning errorwarning;
         errorwarning.LogLine = 1;
-        errorwarning.Text =
-          "*** WARNING non-zero return value in ctest from: ";
-        errorwarning.Text += argv[0];
+        errorwarning.Text = cmStrCat(
+          "*** WARNING non-zero return value in ctest from: ", argv[0]);
         errorwarning.PreContext.clear();
         errorwarning.PostContext.clear();
         errorwarning.Error = false;
@@ -915,8 +908,8 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command,
     // If there was an error running command, report that on the dashboard.
     cmCTestBuildErrorWarning errorwarning;
     errorwarning.LogLine = 1;
-    errorwarning.Text = "*** ERROR executing: ";
-    errorwarning.Text += cmsysProcess_GetErrorString(cp);
+    errorwarning.Text =
+      cmStrCat("*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
     errorwarning.PreContext.clear();
     errorwarning.PostContext.clear();
     errorwarning.Error = true;

+ 3 - 2
Source/CTest/cmCTestCVS.cxx

@@ -4,8 +4,10 @@
 
 #include "cmCTest.h"
 #include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
+#include "cm_string_view.hxx"
 
 #include "cmsys/FStream.hxx"
 #include "cmsys/RegularExpression.hxx"
@@ -204,8 +206,7 @@ std::string cmCTestCVS::ComputeBranchFlag(std::string const& dir)
   if (tagStream && cmSystemTools::GetLineFromStream(tagStream, tagLine) &&
       tagLine.size() > 1 && tagLine[0] == 'T') {
     // Use the branch specified in the tag file.
-    std::string flag = "-r";
-    flag += tagLine.substr(1);
+    std::string flag = cmStrCat("-r", cm::string_view(tagLine).substr(1));
     return flag;
   }
   // Use the default branch.

+ 2 - 3
Source/CTest/cmCTestConfigureCommand.cxx

@@ -76,9 +76,8 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
         delete gg;
       }
 
-      std::string cmakeConfigureCommand = "\"";
-      cmakeConfigureCommand += cmSystemTools::GetCMakeCommand();
-      cmakeConfigureCommand += "\"";
+      std::string cmakeConfigureCommand =
+        cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"');
 
       for (std::string const& option : options) {
         cmakeConfigureCommand += " \"";

+ 14 - 23
Source/CTest/cmCTestCoverageHandler.cxx

@@ -130,10 +130,9 @@ void cmCTestCoverageHandler::Initialize()
 
 void cmCTestCoverageHandler::CleanCoverageLogFiles(std::ostream& log)
 {
-  std::string logGlob = this->CTest->GetCTestConfiguration("BuildDirectory");
-  logGlob += "/Testing/";
-  logGlob += this->CTest->GetCurrentTag();
-  logGlob += "/CoverageLog*";
+  std::string logGlob =
+    cmStrCat(this->CTest->GetCTestConfiguration("BuildDirectory"), "/Testing/",
+             this->CTest->GetCurrentTag(), "/CoverageLog*");
   cmsys::Glob gl;
   gl.FindFiles(logGlob);
   std::vector<std::string> const& files = gl.GetFiles();
@@ -1456,8 +1455,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
       std::vector<std::string> lcovFiles;
       dir = this->CTest->GetBinaryDir();
       std::string daGlob;
-      daGlob = dir;
-      daGlob += "/*.LCOV";
+      daGlob = cmStrCat(dir, "/*.LCOV");
       cmCTestOptionalLog(
         this->CTest, HANDLER_VERBOSE_OUTPUT,
         "   looking for LCOV files in: " << daGlob << std::endl, this->Quiet);
@@ -1598,12 +1596,10 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
     cmCTestOptionalLog(
       this->CTest, HANDLER_VERBOSE_OUTPUT,
       "   globbing for coverage in: " << lm.first << std::endl, this->Quiet);
-    std::string daGlob = lm.first;
-    daGlob += "/*.da";
+    std::string daGlob = cmStrCat(lm.first, "/*.da");
     gl.FindFiles(daGlob);
     cmAppend(files, gl.GetFiles());
-    daGlob = lm.first;
-    daGlob += "/*.gcda";
+    daGlob = cmStrCat(lm.first, "/*.gcda");
     gl.FindFiles(daGlob);
     cmAppend(files, gl.GetFiles());
   }
@@ -1632,8 +1628,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
 
   // DPI file should appear in build directory
   std::string daGlob;
-  daGlob = buildDir;
-  daGlob += "/*.dpi";
+  daGlob = cmStrCat(buildDir, "/*.dpi");
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      "   looking for dpi files in: " << daGlob << std::endl,
                      this->Quiet);
@@ -1946,10 +1941,9 @@ int cmCTestCoverageHandler::RunBullseyeCommand(
   cmCTestRunProcess runCoverageSrc;
   runCoverageSrc.SetCommand(program.c_str());
   runCoverageSrc.AddArgument(arg);
-  std::string stdoutFile = cont->BinaryDir + "/Testing/Temporary/";
-  stdoutFile += this->GetCTestInstance()->GetCurrentTag();
-  stdoutFile += "-";
-  stdoutFile += cmd;
+  std::string stdoutFile =
+    cmStrCat(cont->BinaryDir, "/Testing/Temporary/",
+             this->GetCTestInstance()->GetCurrentTag(), '-', cmd);
   std::string stderrFile = stdoutFile;
   stdoutFile += ".stdout";
   stderrFile += ".stderr";
@@ -2038,9 +2032,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
       coveredFileNames.insert(file);
       if (!cmSystemTools::FileIsFullPath(sourceFile)) {
         // file will be relative to the binary dir
-        file = cont->BinaryDir;
-        file += "/";
-        file += sourceFile;
+        file = cmStrCat(cont->BinaryDir, '/', sourceFile);
       }
       file = cmSystemTools::CollapseFullPath(file);
       bool shouldIDoCoverage =
@@ -2222,8 +2214,8 @@ int cmCTestCoverageHandler::GetLabelId(std::string const& label)
 
 void cmCTestCoverageHandler::LoadLabels()
 {
-  std::string fileList = this->CTest->GetBinaryDir();
-  fileList += "/CMakeFiles/TargetDirectories.txt";
+  std::string fileList =
+    cmStrCat(this->CTest->GetBinaryDir(), "/CMakeFiles/TargetDirectories.txt");
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      " target directory list [" << fileList << "]\n",
                      this->Quiet);
@@ -2237,8 +2229,7 @@ void cmCTestCoverageHandler::LoadLabels()
 void cmCTestCoverageHandler::LoadLabels(const char* dir)
 {
   LabelSet& dirLabels = this->TargetDirs[dir];
-  std::string fname = dir;
-  fname += "/Labels.txt";
+  std::string fname = cmStrCat(dir, "/Labels.txt");
   cmsys::ifstream fin(fname.c_str());
   if (!fin) {
     return;

+ 2 - 3
Source/CTest/cmCTestCurl.cxx

@@ -5,6 +5,7 @@
 #include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCurl.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <ostream>
@@ -127,9 +128,7 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
     return false;
   }
   // set the url
-  std::string upload_url = url;
-  upload_url += "?";
-  upload_url += fields;
+  std::string upload_url = cmStrCat(url, '?', fields);
   ::curl_easy_setopt(this->Curl, CURLOPT_URL, upload_url.c_str());
   // now specify which file to upload
   ::curl_easy_setopt(this->Curl, CURLOPT_INFILE, ftpfile);

+ 2 - 2
Source/CTest/cmCTestGIT.cxx

@@ -111,8 +111,8 @@ std::string cmCTestGIT::FindGitDir()
   else if (git_dir[0] == '/') {
     // Cygwin Git reports a full path that Cygwin understands, but we
     // are a Windows application.  Run "cygpath" to get Windows path.
-    std::string cygpath_exe = cmSystemTools::GetFilenamePath(git);
-    cygpath_exe += "/cygpath.exe";
+    std::string cygpath_exe =
+      cmStrCat(cmSystemTools::GetFilenamePath(git), "/cygpath.exe");
     if (cmSystemTools::FileExists(cygpath_exe)) {
       char const* cygpath[] = { cygpath_exe.c_str(), "-w", git_dir.c_str(),
                                 0 };

+ 9 - 22
Source/CTest/cmCTestLaunch.cxx

@@ -176,14 +176,8 @@ void cmCTestLaunch::ComputeFileNames()
   this->LogHash = md5.FinalizeHex();
 
   // We store stdout and stderr in temporary log files.
-  this->LogOut = this->LogDir;
-  this->LogOut += "launch-";
-  this->LogOut += this->LogHash;
-  this->LogOut += "-out.txt";
-  this->LogErr = this->LogDir;
-  this->LogErr += "launch-";
-  this->LogErr += this->LogHash;
-  this->LogErr += "-err.txt";
+  this->LogOut = cmStrCat(this->LogDir, "launch-", this->LogHash, "-out.txt");
+  this->LogErr = cmStrCat(this->LogDir, "launch-", this->LogHash, "-err.txt");
 }
 
 void cmCTestLaunch::RunChild()
@@ -282,10 +276,8 @@ void cmCTestLaunch::LoadLabels()
   }
 
   // Labels are listed in per-target files.
-  std::string fname = this->OptionBuildDir;
-  fname += "/CMakeFiles/";
-  fname += this->OptionTargetName;
-  fname += ".dir/Labels.txt";
+  std::string fname = cmStrCat(this->OptionBuildDir, "/CMakeFiles/",
+                               this->OptionTargetName, ".dir/Labels.txt");
 
   // We are interested in per-target labels for this source file.
   std::string source = this->OptionSource;
@@ -339,10 +331,9 @@ bool cmCTestLaunch::IsError() const
 void cmCTestLaunch::WriteXML()
 {
   // Name the xml file.
-  std::string logXML = this->LogDir;
-  logXML += this->IsError() ? "error-" : "warning-";
-  logXML += this->LogHash;
-  logXML += ".xml";
+  std::string logXML =
+    cmStrCat(this->LogDir, this->IsError() ? "error-" : "warning-",
+             this->LogHash, ".xml");
 
   // Use cmGeneratedFileStream to atomically create the report file.
   cmGeneratedFileStream fxml(logXML);
@@ -545,10 +536,7 @@ void cmCTestLaunch::LoadScrapeRules()
 void cmCTestLaunch::LoadScrapeRules(
   const char* purpose, std::vector<cmsys::RegularExpression>& regexps)
 {
-  std::string fname = this->LogDir;
-  fname += "Custom";
-  fname += purpose;
-  fname += ".txt";
+  std::string fname = cmStrCat(this->LogDir, "Custom", purpose, ".txt");
   cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
   std::string line;
   cmsys::RegularExpression rex;
@@ -616,8 +604,7 @@ void cmCTestLaunch::LoadConfig()
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
   cmGlobalGenerator gg(&cm);
   cmMakefile mf(&gg, cm.GetCurrentSnapshot());
-  std::string fname = this->LogDir;
-  fname += "CTestLaunchConfig.cmake";
+  std::string fname = cmStrCat(this->LogDir, "CTestLaunchConfig.cmake");
   if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) {
     this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
     cmSystemTools::ConvertToUnixSlashes(this->SourceDir);

+ 12 - 19
Source/CTest/cmCTestRunTest.cxx

@@ -6,6 +6,7 @@
 #include "cmCTestMemCheckHandler.h"
 #include "cmCTestMultiProcessHandler.h"
 #include "cmProcess.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 
@@ -86,16 +87,13 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
     for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
       if (pass.first.find(this->ProcessOutput)) {
         found = true;
-        reason = "Required regular expression found.";
-        reason += " Regex=[";
-        reason += pass.second;
-        reason += "]";
+        reason = cmStrCat("Required regular expression found. Regex=[",
+                          pass.second, ']');
         break;
       }
     }
     if (!found) {
-      reason = "Required regular expression not found.";
-      reason += " Regex=[";
+      reason = "Required regular expression not found. Regex=[";
       for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
         reason += pass.second;
         reason += "\n";
@@ -108,10 +106,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
       this->FailedDependencies.empty()) {
     for (auto& fail : this->TestProperties->ErrorRegularExpressions) {
       if (fail.first.find(this->ProcessOutput)) {
-        reason = "Error regular expression found in output.";
-        reason += " Regex=[";
-        reason += fail.second;
-        reason += "]";
+        reason = cmStrCat("Error regular expression found in output. Regex=[",
+                          fail.second, ']');
         forceFail = true;
         break;
       }
@@ -121,10 +117,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
       this->FailedDependencies.empty()) {
     for (auto& skip : this->TestProperties->SkipRegularExpressions) {
       if (skip.first.find(this->ProcessOutput)) {
-        reason = "Skip regular expression found in output.";
-        reason += " Regex=[";
-        reason += skip.second;
-        reason += "]";
+        reason = cmStrCat("Skip regular expression found in output. Regex=[",
+                          skip.second, ']');
         forceSkip = true;
         break;
       }
@@ -504,12 +498,11 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
     this->TestProcess = cm::make_unique<cmProcess>(*this);
     std::string msg;
     if (this->CTest->GetConfigType().empty()) {
-      msg = "Test not available without configuration.";
-      msg += "  (Missing \"-C <config>\"?)";
+      msg = "Test not available without configuration.  (Missing \"-C "
+            "<config>\"?)";
     } else {
-      msg = "Test not available in configuration \"";
-      msg += this->CTest->GetConfigType();
-      msg += "\".";
+      msg = cmStrCat("Test not available in configuration \"",
+                     this->CTest->GetConfigType(), "\".");
     }
     *this->TestHandler->LogFile << msg << std::endl;
     cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl);

+ 3 - 3
Source/CTest/cmCTestSVN.cxx

@@ -6,6 +6,7 @@
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
@@ -143,9 +144,8 @@ bool cmCTestSVN::NoteNewRevision()
     // the repository root.
     if (!svninfo.Root.empty() &&
         cmCTestSVNPathStarts(svninfo.URL, svninfo.Root)) {
-      svninfo.Base =
-        cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size()));
-      svninfo.Base += "/";
+      svninfo.Base = cmStrCat(
+        cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size())), '/');
     }
     this->Log << "Repository '" << svninfo.LocalPath
               << "' Base = " << svninfo.Base << "\n";

+ 13 - 20
Source/CTest/cmCTestScriptHandler.cxx

@@ -451,12 +451,13 @@ int cmCTestScriptHandler::ExtractVariables()
   // make sure the required info is here
   if (this->SourceDir.empty() || this->BinaryDir.empty() ||
       this->CTestCmd.empty()) {
-    std::string msg = "CTEST_SOURCE_DIRECTORY = ";
-    msg += (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)";
-    msg += "\nCTEST_BINARY_DIRECTORY = ";
-    msg += (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)";
-    msg += "\nCTEST_COMMAND = ";
-    msg += (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)";
+    std::string msg =
+      cmStrCat("CTEST_SOURCE_DIRECTORY = ",
+               (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)",
+               "\nCTEST_BINARY_DIRECTORY = ",
+               (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)",
+               "\nCTEST_COMMAND = ",
+               (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)");
     cmSystemTools::Error(
       "Some required settings in the configuration file were missing:\n" +
       msg);
@@ -610,10 +611,8 @@ int cmCTestScriptHandler::BackupDirectories()
   int retVal;
 
   // compute the backup names
-  this->BackupSourceDir = this->SourceDir;
-  this->BackupSourceDir += "_CMakeBackup";
-  this->BackupBinaryDir = this->BinaryDir;
-  this->BackupBinaryDir += "_CMakeBackup";
+  this->BackupSourceDir = cmStrCat(this->SourceDir, "_CMakeBackup");
+  this->BackupBinaryDir = cmStrCat(this->BinaryDir, "_CMakeBackup");
 
   // backup the binary and src directories if requested
   if (this->Backup) {
@@ -653,9 +652,7 @@ int cmCTestScriptHandler::PerformExtraUpdates()
     std::vector<std::string> cvsArgs;
     cmExpandList(eu, cvsArgs);
     if (cvsArgs.size() == 2) {
-      std::string fullCommand = command;
-      fullCommand += " update ";
-      fullCommand += cvsArgs[1];
+      std::string fullCommand = cmStrCat(command, " update ", cvsArgs[1]);
       output.clear();
       retVal = 0;
       cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -756,9 +753,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
   int cmakeFailed = 0;
   std::string cmakeFailedOuput;
   if (!this->CMakeCmd.empty()) {
-    command = this->CMakeCmd;
-    command += " \"";
-    command += this->SourceDir;
+    command = cmStrCat(this->CMakeCmd, " \"", this->SourceDir);
     output.clear();
     command += "\"";
     retVal = 0;
@@ -839,8 +834,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
 bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
                                              const char* text)
 {
-  std::string cacheFile = directory;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt");
   cmGeneratedFileStream fout(cacheFile);
   if (!fout) {
     return false;
@@ -905,8 +899,7 @@ bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
   }
 
   // try to avoid deleting directories that we shouldn't
-  std::string check = sname;
-  check += "/CMakeCache.txt";
+  std::string check = cmStrCat(sname, "/CMakeCache.txt");
 
   if (!cmSystemTools::FileExists(check)) {
     return false;

+ 15 - 38
Source/CTest/cmCTestTestHandler.cxx

@@ -77,9 +77,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
     if (cmSystemTools::FileIsFullPath(arg)) {
       fname = arg;
     } else {
-      fname = cwd;
-      fname += "/";
-      fname += arg;
+      fname = cmStrCat(cwd, '/', arg);
     }
 
     if (!cmSystemTools::FileIsDirectory(fname)) {
@@ -110,8 +108,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
       readit = this->Makefile->ReadDependentFile(fname);
     }
     if (!readit) {
-      std::string m = "Could not find include file: ";
-      m += fname;
+      std::string m = cmStrCat("Could not find include file: ", fname);
       this->SetError(m);
       return false;
     }
@@ -150,9 +147,8 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
     return false;
   }
 
-  std::string fname = cmSystemTools::GetCurrentWorkingDirectory();
-  fname += "/";
-  fname += args[0];
+  std::string fname =
+    cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), '/', args[0]);
 
   if (!cmSystemTools::FileExists(fname)) {
     // No subdirectory? So what...
@@ -176,8 +172,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
     readit = this->Makefile->ReadDependentFile(fname);
   }
   if (!readit) {
-    std::string m = "Could not find include file: ";
-    m += fname;
+    std::string m = cmStrCat("Could not find include file: ", fname);
     this->SetError(m);
     return false;
   }
@@ -1552,50 +1547,32 @@ void cmCTestTestHandler::AddConfigurations(
   attemptedConfigs.emplace_back();
 
   if (!ctest->GetConfigType().empty()) {
-    tempPath = filepath;
-    tempPath += ctest->GetConfigType();
-    tempPath += "/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, ctest->GetConfigType(), '/', filename);
     attempted.push_back(tempPath);
     attemptedConfigs.push_back(ctest->GetConfigType());
     // If the file is an OSX bundle then the configtype
     // will be at the start of the path
-    tempPath = ctest->GetConfigType();
-    tempPath += "/";
-    tempPath += filepath;
-    tempPath += filename;
+    tempPath = cmStrCat(ctest->GetConfigType(), '/', filepath, filename);
     attempted.push_back(tempPath);
     attemptedConfigs.push_back(ctest->GetConfigType());
   } else {
     // no config specified - try some options...
-    tempPath = filepath;
-    tempPath += "Release/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Release/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Release");
-    tempPath = filepath;
-    tempPath += "Debug/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Debug/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Debug");
-    tempPath = filepath;
-    tempPath += "MinSizeRel/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "MinSizeRel/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("MinSizeRel");
-    tempPath = filepath;
-    tempPath += "RelWithDebInfo/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "RelWithDebInfo/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("RelWithDebInfo");
-    tempPath = filepath;
-    tempPath += "Deployment/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Deployment/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Deployment");
-    tempPath = filepath;
-    tempPath += "Development/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Development/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Deployment");
   }
@@ -1649,8 +1626,8 @@ std::string cmCTestTestHandler::FindExecutable(
     // then try with the exe extension
     else {
       failed.push_back(attempted[ai]);
-      tempPath = attempted[ai];
-      tempPath += cmSystemTools::GetExecutableExtension();
+      tempPath =
+        cmStrCat(attempted[ai], cmSystemTools::GetExecutableExtension());
       if (cmSystemTools::FileExists(tempPath) &&
           !cmSystemTools::FileIsDirectory(tempPath)) {
         fullPath = cmSystemTools::CollapseFullPath(tempPath);

+ 7 - 12
Source/CTest/cmCTestUpdateHandler.cxx

@@ -12,6 +12,7 @@
 #include "cmCTestSVN.h"
 #include "cmCTestVC.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 #include "cmXMLWriter.h"
@@ -266,33 +267,27 @@ int cmCTestUpdateHandler::DetectVCS(const char* dir)
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_SVN;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/CVS";
+  sourceDirectory = cmStrCat(dir, "/CVS");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_CVS;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.bzr";
+  sourceDirectory = cmStrCat(dir, "/.bzr");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_BZR;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.git";
+  sourceDirectory = cmStrCat(dir, "/.git");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_GIT;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.hg";
+  sourceDirectory = cmStrCat(dir, "/.hg");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_HG;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.p4";
+  sourceDirectory = cmStrCat(dir, "/.p4");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_P4;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.p4config";
+  sourceDirectory = cmStrCat(dir, "/.p4config");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_P4;
   }

+ 2 - 3
Source/CTest/cmParseCacheCoverage.cxx

@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/Directory.hxx"
@@ -30,9 +31,7 @@ bool cmParseCacheCoverage::LoadCoverageData(const char* d)
   for (i = 0; i < numf; i++) {
     std::string file = dir.GetFile(i);
     if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
-      std::string path = d;
-      path += "/";
-      path += file;
+      std::string path = cmStrCat(d, '/', file);
       if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") {
         if (!this->ReadCMCovFile(path.c_str())) {
           return false;

+ 1 - 3
Source/CTest/cmParseGTMCoverage.cxx

@@ -31,9 +31,7 @@ bool cmParseGTMCoverage::LoadCoverageData(const char* d)
   for (i = 0; i < numf; i++) {
     std::string file = dir.GetFile(i);
     if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
-      std::string path = d;
-      path += "/";
-      path += file;
+      std::string path = cmStrCat(d, '/', file);
       if (cmSystemTools::GetFilenameLastExtension(path) == ".mcov") {
         if (!this->ReadMCovFile(path.c_str())) {
           return false;

+ 1 - 3
Source/CTest/cmParseJacocoCoverage.cxx

@@ -104,9 +104,7 @@ protected:
                                 std::string const& baseDir)
   {
     // Search for the file in the baseDir and its subdirectories.
-    std::string packageGlob = baseDir;
-    packageGlob += "/";
-    packageGlob += fileName;
+    std::string packageGlob = cmStrCat(baseDir, '/', fileName);
     cmsys::Glob gl;
     gl.RecurseOn();
     gl.RecurseThroughSymlinksOn();

+ 2 - 2
Source/CTest/cmParseMumpsCoverage.cxx

@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/FStream.hxx"
@@ -107,8 +108,7 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
 {
   cmsys::Glob glob;
   glob.RecurseOn();
-  std::string pat = d;
-  pat += "/*.m";
+  std::string pat = cmStrCat(d, "/*.m");
   glob.FindFiles(pat);
   for (std::string& file : glob.GetFiles()) {
     std::string name = cmSystemTools::GetFilenameName(file);

+ 2 - 3
Source/CTest/cmParsePHPCoverage.cxx

@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/Directory.hxx"
@@ -210,9 +211,7 @@ bool cmParsePHPCoverage::ReadPHPCoverageDirectory(const char* d)
   for (i = 0; i < numf; i++) {
     std::string file = dir.GetFile(i);
     if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
-      std::string path = d;
-      path += "/";
-      path += file;
+      std::string path = cmStrCat(d, '/', file);
       if (!this->ReadPHPData(path.c_str())) {
         return false;
       }

+ 2 - 2
Source/CTest/cmProcess.cxx

@@ -7,6 +7,7 @@
 #include "cmCTestRunTest.h"
 #include "cmCTestTestHandler.h"
 #include "cmGetPipes.h"
+#include "cmStringAlgorithms.h"
 #include "cmsys/Process.h"
 
 #include <iostream>
@@ -694,8 +695,7 @@ std::string cmProcess::GetExitExceptionString()
 #    endif
 #  endif
     default:
-      exception_str = "Signal ";
-      exception_str += std::to_string(this->Signal);
+      exception_str = cmStrCat("Signal ", this->Signal);
   }
 #endif
   return exception_str;

+ 2 - 2
Source/CursesDialog/cmCursesMainForm.cxx

@@ -48,8 +48,8 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
     cmSystemTools::GetCMakeCursesCommand());
 
   // create the arguments for the cmake object
-  std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0]);
-  whereCMake += "/cmake";
+  std::string whereCMake =
+    cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
   this->Args[0] = whereCMake;
   this->CMakeInstance->SetArgs(this->Args);
   this->SearchString = "";

+ 4 - 4
Source/QtDialog/FirstConfigure.cxx

@@ -2,6 +2,7 @@
 #include "FirstConfigure.h"
 
 #include "Compilers.h"
+#include "cmStringAlgorithms.h"
 
 #include <QComboBox>
 #include <QRadioButton>
@@ -183,10 +184,9 @@ void StartCompilerSetup::onGeneratorChanged(QString const& name)
   if (GeneratorsSupportingPlatform.contains(name)) {
 
     // Change the label title to include the default platform
-    std::string label = "Optional platform for generator";
-    label += "(if empty, generator uses: ";
-    label += this->GeneratorDefaultPlatform[name].toStdString();
-    label += ")";
+    std::string label =
+      cmStrCat("Optional platform for generator(if empty, generator uses: ",
+               this->GeneratorDefaultPlatform[name].toStdString(), ')');
     this->PlatformLabel->setText(tr(label.c_str()));
 
     // Regenerate the list of supported platform

+ 2 - 2
Source/cmAddCustomCommandCommand.cxx

@@ -14,6 +14,7 @@
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
@@ -202,8 +203,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
             // and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt".
             // This is fairly obscure so we can wait for someone to
             // complain.
-            filename = mf.GetCurrentBinaryDirectory();
-            filename += "/";
+            filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
           }
           filename += copy;
           cmSystemTools::ConvertToUnixSlashes(filename);

+ 2 - 2
Source/cmAddCustomTargetCommand.cxx

@@ -12,6 +12,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
@@ -122,8 +123,7 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
         case doing_byproducts: {
           std::string filename;
           if (!cmSystemTools::FileIsFullPath(copy)) {
-            filename = mf.GetCurrentBinaryDirectory();
-            filename += "/";
+            filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
           }
           filename += copy;
           cmSystemTools::ConvertToUnixSlashes(filename);

+ 5 - 9
Source/cmAddSubDirectoryCommand.cxx

@@ -8,6 +8,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
@@ -45,14 +46,11 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
   if (cmSystemTools::FileIsFullPath(srcArg)) {
     srcPath = srcArg;
   } else {
-    srcPath = mf.GetCurrentSourceDirectory();
-    srcPath += "/";
-    srcPath += srcArg;
+    srcPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', srcArg);
   }
   if (!cmSystemTools::FileIsDirectory(srcPath)) {
-    std::string error = "given source \"";
-    error += srcArg;
-    error += "\" which is not an existing directory.";
+    std::string error = cmStrCat("given source \"", srcArg,
+                                 "\" which is not an existing directory.");
     status.SetError(error);
     return false;
   }
@@ -95,9 +93,7 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
     if (cmSystemTools::FileIsFullPath(binArg)) {
       binPath = binArg;
     } else {
-      binPath = mf.GetCurrentBinaryDirectory();
-      binPath += "/";
-      binPath += binArg;
+      binPath = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', binArg);
     }
   }
   binPath = cmSystemTools::CollapseFullPath(binPath);

+ 39 - 47
Source/cmArchiveWrite.cxx

@@ -3,12 +3,14 @@
 #include "cmArchiveWrite.h"
 
 #include "cmLocale.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cm_get_date.h"
 #include "cm_libarchive.h"
 #include "cmsys/Directory.hxx"
 #include "cmsys/Encoding.hxx"
 #include "cmsys/FStream.hxx"
+
 #include <iostream>
 #include <sstream>
 #include <string.h>
@@ -85,22 +87,22 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
   switch (c) {
     case CompressNone:
       if (archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_none: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_none: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressCompress:
       if (archive_write_add_filter_compress(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_compress: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_compress: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressGZip: {
       if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_gzip: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_gzip: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       std::string source_date_epoch;
@@ -110,60 +112,60 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
         // The next best thing is to omit the timestamp entirely.
         if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp",
                                             nullptr) != ARCHIVE_OK) {
-          this->Error = "archive_write_set_filter_option: ";
-          this->Error += cm_archive_error_string(this->Archive);
+          this->Error = cmStrCat("archive_write_set_filter_option: ",
+                                 cm_archive_error_string(this->Archive));
           return;
         }
       }
     } break;
     case CompressBZip2:
       if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_bzip2: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_bzip2: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressLZMA:
       if (archive_write_add_filter_lzma(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_lzma: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_lzma: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressXZ:
       if (archive_write_add_filter_xz(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_xz: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_xz: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressZstd:
       if (archive_write_add_filter_zstd(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_zstd: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_zstd: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
   }
 #if !defined(_WIN32) || defined(__CYGWIN__)
   if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) {
-    this->Error = "archive_read_disk_set_standard_lookup: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_read_disk_set_standard_lookup: ",
+                           cm_archive_error_string(this->Archive));
     return;
   }
 #endif
 
   if (archive_write_set_format_by_name(this->Archive, format.c_str()) !=
       ARCHIVE_OK) {
-    this->Error = "archive_write_set_format_by_name: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_write_set_format_by_name: ",
+                           cm_archive_error_string(this->Archive));
     return;
   }
 
   // do not pad the last block!!
   if (archive_write_set_bytes_in_last_block(this->Archive, 1)) {
-    this->Error = "archive_write_set_bytes_in_last_block: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_write_set_bytes_in_last_block: ",
+                           cm_archive_error_string(this->Archive));
     return;
   }
 
@@ -171,8 +173,8 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
         this->Archive, this, nullptr,
         reinterpret_cast<archive_write_callback*>(&Callback::Write),
         nullptr) != ARCHIVE_OK) {
-    this->Error = "archive_write_open: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error =
+      cmStrCat("archive_write_open: ", cm_archive_error_string(this->Archive));
     return;
   }
 }
@@ -205,8 +207,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
   }
   cmsys::Directory d;
   if (d.Load(path)) {
-    std::string next = path;
-    next += "/";
+    std::string next = cmStrCat(path, '/');
     std::string::size_type end = next.size();
     unsigned long n = d.GetNumberOfFiles();
     for (unsigned long i = 0; i < n; ++i) {
@@ -237,8 +238,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
   static_cast<void>(localeRAII);
 
   // Meta-data.
-  std::string dest = prefix ? prefix : "";
-  dest += out;
+  std::string dest = cmStrCat(prefix ? prefix : "", out);
   if (this->Verbose) {
     std::cout << dest << "\n";
   }
@@ -247,10 +247,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
   cm_archive_entry_copy_pathname(e, dest);
   if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) !=
       ARCHIVE_OK) {
-    this->Error = "Unable to read from file '";
-    this->Error += file;
-    this->Error += "': ";
-    this->Error += cm_archive_error_string(this->Disk);
+    this->Error = cmStrCat("Unable to read from file '", file,
+                           "': ", cm_archive_error_string(this->Disk));
     return false;
   }
   if (!this->MTime.empty()) {
@@ -258,9 +256,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
     time(&now);
     time_t t = cm_get_date(now, this->MTime.c_str());
     if (t == -1) {
-      this->Error = "unable to parse mtime '";
-      this->Error += this->MTime;
-      this->Error += "'";
+      this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\'');
       return false;
     }
     archive_entry_set_mtime(e, t, 0);
@@ -310,8 +306,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
   }
 
   if (archive_write_header(this->Archive, e) != ARCHIVE_OK) {
-    this->Error = "archive_write_header: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_write_header: ",
+                           cm_archive_error_string(this->Archive));
     return false;
   }
 
@@ -329,10 +325,8 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
 {
   cmsys::ifstream fin(file, std::ios::in | std::ios::binary);
   if (!fin) {
-    this->Error = "Error opening \"";
-    this->Error += file;
-    this->Error += "\": ";
-    this->Error += cmSystemTools::GetLastSystemError();
+    this->Error = cmStrCat("Error opening \"", file,
+                           "\": ", cmSystemTools::GetLastSystemError());
     return false;
   }
 
@@ -350,17 +344,15 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
       break;
     }
     if (archive_write_data(this->Archive, buffer, nnext) != nnext_s) {
-      this->Error = "archive_write_data: ";
-      this->Error += cm_archive_error_string(this->Archive);
+      this->Error = cmStrCat("archive_write_data: ",
+                             cm_archive_error_string(this->Archive));
       return false;
     }
     nleft -= nnext;
   }
   if (nleft > 0) {
-    this->Error = "Error reading \"";
-    this->Error += file;
-    this->Error += "\": ";
-    this->Error += cmSystemTools::GetLastSystemError();
+    this->Error = cmStrCat("Error reading \"", file,
+                           "\": ", cmSystemTools::GetLastSystemError());
     return false;
   }
   return true;

+ 2 - 6
Source/cmAuxSourceDirectoryCommand.cxx

@@ -27,9 +27,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
   std::string const& templateDirectory = args[0];
   std::string tdir;
   if (!cmSystemTools::FileIsFullPath(templateDirectory)) {
-    tdir = mf.GetCurrentSourceDirectory();
-    tdir += "/";
-    tdir += templateDirectory;
+    tdir = cmStrCat(mf.GetCurrentSourceDirectory(), '/', templateDirectory);
   } else {
     tdir = templateDirectory;
   }
@@ -56,9 +54,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
         // Process only source files
         auto cm = mf.GetCMakeInstance();
         if (!base.empty() && cm->IsSourceExtension(ext)) {
-          std::string fullname = templateDirectory;
-          fullname += "/";
-          fullname += file;
+          std::string fullname = cmStrCat(templateDirectory, '/', file);
           // add the file as a class file so
           // depends can be done
           cmSourceFile* sf = mf.GetOrCreateSource(fullname);

+ 2 - 6
Source/cmCPluginAPI.cxx

@@ -690,9 +690,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
 
   // Next, try the various source extensions
   for (std::string const& ext : sourceExts) {
-    hname = pathname;
-    hname += ".";
-    hname += ext;
+    hname = cmStrCat(pathname, '.', ext);
     if (cmSystemTools::FileExists(hname)) {
       sf->SourceExtension = ext;
       sf->FullPath = hname;
@@ -702,9 +700,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
 
   // Finally, try the various header extensions
   for (std::string const& ext : headerExts) {
-    hname = pathname;
-    hname += ".";
-    hname += ext;
+    hname = cmStrCat(pathname, '.', ext);
     if (cmSystemTools::FileExists(hname)) {
       sf->SourceExtension = ext;
       sf->FullPath = hname;

+ 11 - 18
Source/cmCTest.cxx

@@ -641,12 +641,10 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
   cmMakefile* mf = command->GetMakefile();
   std::string fname;
 
-  std::string src_dir_fname = src_dir;
-  src_dir_fname += "/CTestConfig.cmake";
+  std::string src_dir_fname = cmStrCat(src_dir, "/CTestConfig.cmake");
   cmSystemTools::ConvertToUnixSlashes(src_dir_fname);
 
-  std::string bld_dir_fname = bld_dir;
-  bld_dir_fname += "/CTestConfig.cmake";
+  std::string bld_dir_fname = cmStrCat(bld_dir, "/CTestConfig.cmake");
   cmSystemTools::ConvertToUnixSlashes(bld_dir_fname);
 
   if (cmSystemTools::FileExists(bld_dir_fname)) {
@@ -662,8 +660,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
                        command->ShouldBeQuiet());
     bool readit = mf->ReadDependentFile(fname);
     if (!readit) {
-      std::string m = "Could not find include file: ";
-      m += fname;
+      std::string m = cmStrCat("Could not find include file: ", fname);
       command->SetError(m);
       return false;
     }
@@ -856,8 +853,7 @@ bool cmCTest::AddIfExists(Part part, const char* file)
   if (this->CTestFileExists(file)) {
     this->AddSubmitFile(part, file);
   } else {
-    std::string name = file;
-    name += ".gz";
+    std::string name = cmStrCat(file, ".gz");
     if (this->CTestFileExists(name)) {
       this->AddSubmitFile(part, file);
     } else {
@@ -1320,15 +1316,15 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
       OutputTestErrors(tempOutput);
     }
     *retVal = cmsysProcess_GetExitException(cp);
-    std::string outerr = "\n*** Exception executing: ";
-    outerr += cmsysProcess_GetExceptionString(cp);
+    std::string outerr = cmStrCat("\n*** Exception executing: ",
+                                  cmsysProcess_GetExceptionString(cp));
     if (output) {
       *output += outerr;
     }
     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
   } else if (result == cmsysProcess_State_Error) {
-    std::string outerr = "\n*** ERROR executing: ";
-    outerr += cmsysProcess_GetErrorString(cp);
+    std::string outerr =
+      cmStrCat("\n*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
     if (output) {
       *output += outerr;
     }
@@ -2499,8 +2495,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
              "* Read custom CTest configuration directory: " << dir
                                                              << std::endl);
 
-  std::string fname = dir;
-  fname += "/CTestCustom.cmake";
+  std::string fname = cmStrCat(dir, "/CTestCustom.cmake");
   cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl);
   if (cmSystemTools::FileExists(fname)) {
     cmCTestLog(this, DEBUG,
@@ -2520,8 +2515,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
     }
   }
 
-  std::string rexpr = dir;
-  rexpr += "/CTestCustom.ctest";
+  std::string rexpr = cmStrCat(dir, "/CTestCustom.ctest");
   cmCTestLog(this, DEBUG, "* Check for file: " << rexpr << std::endl);
   if (!found && cmSystemTools::FileExists(rexpr)) {
     cmsys::Glob gl;
@@ -2673,8 +2667,7 @@ std::string cmCTest::GetSubmitURL()
     std::string site = this->GetCTestConfiguration("DropSite");
     std::string location = this->GetCTestConfiguration("DropLocation");
 
-    url = method.empty() ? "http" : method;
-    url += "://";
+    url = cmStrCat(method.empty() ? "http" : method, "://");
     if (!user.empty()) {
       url += user;
       if (!password.empty()) {

+ 16 - 26
Source/cmCacheManager.cxx

@@ -26,8 +26,7 @@ cmCacheManager::cmCacheManager()
 
 void cmCacheManager::CleanCMakeFiles(const std::string& path)
 {
-  std::string glob = path;
-  glob += "/CMakeFiles/*.cmake";
+  std::string glob = cmStrCat(path, "/CMakeFiles/*.cmake");
   cmsys::Glob globIt;
   globIt.FindFiles(glob);
   std::vector<std::string> files = globIt.GetFiles();
@@ -38,8 +37,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
                                std::set<std::string>& excludes,
                                std::set<std::string>& includes)
 {
-  std::string cacheFile = path;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
   // clear the old cache, if we are reading in internal values
   if (internal) {
     this->Cache.clear();
@@ -104,12 +102,10 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
           // not visible in the gui
           if (!internal) {
             e.Type = cmStateEnums::INTERNAL;
-            helpString = "DO NOT EDIT, ";
-            helpString += entryKey;
-            helpString += " loaded from external file.  "
-                          "To change this value edit this file: ";
-            helpString += path;
-            helpString += "/CMakeCache.txt";
+            helpString = cmStrCat("DO NOT EDIT, ", entryKey,
+                                  " loaded from external file.  "
+                                  "To change this value edit this file: ",
+                                  path, "/CMakeCache.txt");
             e.SetProperty("HELPSTRING", helpString.c_str());
           }
           if (!this->ReadPropertyEntry(entryKey, e)) {
@@ -214,14 +210,11 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
 {
   for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) {
     if (const char* value = i.GetProperty(*p)) {
-      std::string helpstring = *p;
-      helpstring += " property for variable: ";
-      helpstring += i.GetName();
+      std::string helpstring =
+        cmStrCat(*p, " property for variable: ", i.GetName());
       cmCacheManager::OutputHelpString(os, helpstring);
 
-      std::string key = i.GetName();
-      key += "-";
-      key += *p;
+      std::string key = cmStrCat(i.GetName(), '-', *p);
       cmCacheManager::OutputKey(os, key);
       os << ":INTERNAL=";
       cmCacheManager::OutputValue(os, value);
@@ -234,8 +227,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
 
 bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
 {
-  std::string cacheFile = path;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
   cmGeneratedFileStream fout(cacheFile);
   fout.SetCopyIfDifferent(true);
   if (!fout) {
@@ -356,8 +348,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
   }
   fout << "\n";
   fout.Close();
-  std::string checkCacheFile = path;
-  checkCacheFile += "/CMakeFiles";
+  std::string checkCacheFile = cmStrCat(path, "/CMakeFiles");
   cmSystemTools::MakeDirectory(checkCacheFile);
   checkCacheFile += "/cmake.check_cache";
   cmsys::ofstream checkCache(checkCacheFile.c_str());
@@ -473,15 +464,14 @@ void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout,
 {
   if (value.find('\n') != std::string::npos) {
     if (messenger) {
-      std::string message = "Value of ";
-      message += key;
-      message += " contained a newline; truncating";
+      std::string message =
+        cmStrCat("Value of ", key, " contained a newline; truncating");
       messenger->IssueMessage(MessageType::WARNING, message);
     }
 
-    std::string comment = "WARNING: Value of ";
-    comment += key;
-    comment += " contained a newline and was truncated. Original value:";
+    std::string comment =
+      cmStrCat("WARNING: Value of ", key,
+               " contained a newline and was truncated. Original value:");
 
     OutputWarningComment(fout, comment, true);
     OutputWarningComment(fout, value, false);

+ 1 - 3
Source/cmCommandArgumentParserHelper.cxx

@@ -124,9 +124,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
   // - this->ReplaceAtSyntax is false
   // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
   //   and the variable was not defined
-  std::string ref = "@";
-  ref += var;
-  ref += "@";
+  std::string ref = cmStrCat('@', var, '@');
   return this->AddString(ref);
 }
 

+ 8 - 12
Source/cmCommonTargetGenerator.cxx

@@ -59,10 +59,11 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(
 
   // Append the flag and value.  Use ConvertToLinkReference to help
   // vs6's "cl -link" pass it to the linker.
-  std::string flag = defFileFlag;
-  flag += this->LocalCommonGenerator->ConvertToOutputFormat(
-    linkLineComputer->ConvertToLinkReference(mdi->DefFile),
-    cmOutputConverter::SHELL);
+  std::string flag =
+    cmStrCat(defFileFlag,
+             this->LocalCommonGenerator->ConvertToOutputFormat(
+               linkLineComputer->ConvertToLinkReference(mdi->DefFile),
+               cmOutputConverter::SHELL));
   this->LocalCommonGenerator->AppendFlags(flags, flag);
 }
 
@@ -155,9 +156,8 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
           && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
           emitted.insert(linkee).second) {
         cmLocalGenerator* lg = linkee->GetLocalGenerator();
-        std::string di = lg->GetCurrentBinaryDirectory();
-        di += "/";
-        di += lg->GetTargetDirectory(linkee);
+        std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+                                  lg->GetTargetDirectory(linkee));
         dirs.push_back(std::move(di));
       }
     }
@@ -210,11 +210,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
                                                const char* name, bool so)
 {
   // Lookup the flag to specify the version.
-  std::string fvar = "CMAKE_";
-  fvar += lang;
-  fvar += "_OSX_";
-  fvar += name;
-  fvar += "_VERSION_FLAG";
+  std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG");
   const char* flag = this->Makefile->GetDefinition(fvar);
 
   // Skip if no such flag.

+ 2 - 4
Source/cmComputeLinkDepends.cxx

@@ -319,8 +319,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
     this->BFSQueue.push(qe);
   } else {
     // Look for an old-style <item>_LIB_DEPENDS variable.
-    std::string var = entry.Item;
-    var += "_LIB_DEPENDS";
+    std::string var = cmStrCat(entry.Item, "_LIB_DEPENDS");
     if (const char* val = this->Makefile->GetDefinition(var)) {
       // The item dependencies are known.  Follow them.
       BFSEntry qe = { index, val };
@@ -461,8 +460,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
       // the export_library_dependencies command from CMake 2.4 and
       // lower.
       if (!haveLLT) {
-        std::string var = d;
-        var += "_LINK_TYPE";
+        std::string var = cmStrCat(d, "_LINK_TYPE");
         if (const char* val = this->Makefile->GetDefinition(var)) {
           if (strcmp(val, "debug") == 0) {
             llt = DEBUG_LibraryType;

+ 30 - 63
Source/cmComputeLinkInformation.cxx

@@ -279,9 +279,8 @@ cmComputeLinkInformation::cmComputeLinkInformation(
   this->LoaderFlag = nullptr;
   if (!this->Target->IsDLLPlatform() &&
       this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
-    std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
-    loader_flag_var += this->LinkLanguage;
-    loader_flag_var += "_FLAG";
+    std::string loader_flag_var =
+      cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG");
     this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var);
   }
 
@@ -304,11 +303,8 @@ cmComputeLinkInformation::cmComputeLinkInformation(
     const char* tType = ((this->Target->GetType() == cmStateEnums::EXECUTABLE)
                            ? "EXECUTABLE"
                            : "SHARED_LIBRARY");
-    std::string rtVar = "CMAKE_";
-    rtVar += tType;
-    rtVar += "_RUNTIME_";
-    rtVar += this->LinkLanguage;
-    rtVar += "_FLAG";
+    std::string rtVar =
+      cmStrCat("CMAKE_", tType, "_RUNTIME_", this->LinkLanguage, "_FLAG");
     std::string rtSepVar = rtVar + "_SEP";
     this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar);
     this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar);
@@ -318,19 +314,15 @@ cmComputeLinkInformation::cmComputeLinkInformation(
     this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config);
 
     // Get options needed to help find dependent libraries.
-    std::string rlVar = "CMAKE_";
-    rlVar += tType;
-    rlVar += "_RPATH_LINK_";
-    rlVar += this->LinkLanguage;
-    rlVar += "_FLAG";
+    std::string rlVar =
+      cmStrCat("CMAKE_", tType, "_RPATH_LINK_", this->LinkLanguage, "_FLAG");
     this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar);
   }
 
   // Check if we need to include the runtime search path at link time.
   {
-    std::string var = "CMAKE_SHARED_LIBRARY_LINK_";
-    var += this->LinkLanguage;
-    var += "_WITH_RUNTIME_PATH";
+    std::string var = cmStrCat("CMAKE_SHARED_LIBRARY_LINK_",
+                               this->LinkLanguage, "_WITH_RUNTIME_PATH");
     this->LinkWithRuntimePath = this->Makefile->IsOn(var);
   }
 
@@ -547,9 +539,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
 {
   // Add libraries for this language that are not implied by the
   // linker language.
-  std::string libVar = "CMAKE_";
-  libVar += lang;
-  libVar += "_IMPLICIT_LINK_LIBRARIES";
+  std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES");
   if (const char* libs = this->Makefile->GetDefinition(libVar)) {
     std::vector<std::string> libsVec;
     cmExpandList(libs, libsVec);
@@ -562,9 +552,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
 
   // Add linker search paths for this language that are not
   // implied by the linker language.
-  std::string dirVar = "CMAKE_";
-  dirVar += lang;
-  dirVar += "_IMPLICIT_LINK_DIRECTORIES";
+  std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES");
   if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
     std::vector<std::string> dirsVec;
     cmExpandList(dirs, dirsVec);
@@ -760,19 +748,15 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
       break;
   }
   if (target_type_str) {
-    std::string static_link_type_flag_var = "CMAKE_";
-    static_link_type_flag_var += target_type_str;
-    static_link_type_flag_var += "_LINK_STATIC_";
-    static_link_type_flag_var += this->LinkLanguage;
-    static_link_type_flag_var += "_FLAGS";
+    std::string static_link_type_flag_var =
+      cmStrCat("CMAKE_", target_type_str, "_LINK_STATIC_", this->LinkLanguage,
+               "_FLAGS");
     static_link_type_flag =
       this->Makefile->GetDefinition(static_link_type_flag_var);
 
-    std::string shared_link_type_flag_var = "CMAKE_";
-    shared_link_type_flag_var += target_type_str;
-    shared_link_type_flag_var += "_LINK_DYNAMIC_";
-    shared_link_type_flag_var += this->LinkLanguage;
-    shared_link_type_flag_var += "_FLAGS";
+    std::string shared_link_type_flag_var =
+      cmStrCat("CMAKE_", target_type_str, "_LINK_DYNAMIC_", this->LinkLanguage,
+               "_FLAGS");
     shared_link_type_flag =
       this->Makefile->GetDefinition(shared_link_type_flag_var);
   }
@@ -848,8 +832,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
   reg += "([^/:]*)";
 
   // Create a regex to match any library name.
-  std::string reg_any = reg;
-  reg_any += libext;
+  std::string reg_any = cmStrCat(reg, libext);
 #ifdef CM_COMPUTE_LINK_INFO_DEBUG
   fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
 #endif
@@ -857,9 +840,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
 
   // Create a regex to match static library names.
   if (!this->StaticLinkExtensions.empty()) {
-    std::string reg_static = reg;
-    reg_static +=
-      this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic);
+    std::string reg_static = cmStrCat(
+      reg, this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic));
 #ifdef CM_COMPUTE_LINK_INFO_DEBUG
     fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
 #endif
@@ -1215,9 +1197,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
   }
 
   // Create an option to ask the linker to search for the library.
-  std::string out = this->LibLinkFlag;
-  out += lib;
-  out += this->LibLinkSuffix;
+  std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix);
   this->Items.emplace_back(out, false);
 
   // Here we could try to find the library the linker will find and
@@ -1239,12 +1219,7 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
 
   std::string fw_path = this->SplitFramework.match(1);
   std::string fw = this->SplitFramework.match(2);
-  std::string full_fw = fw_path;
-  full_fw += "/";
-  full_fw += fw;
-  full_fw += ".framework";
-  full_fw += "/";
-  full_fw += fw;
+  std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw);
 
   // Add the directory portion to the framework search path.
   this->AddFrameworkPath(fw_path);
@@ -1293,9 +1268,8 @@ void cmComputeLinkInformation::ComputeFrameworkInfo()
   }
 
   // Get language-specific implicit directories.
-  std::string implicitDirVar = "CMAKE_";
-  implicitDirVar += this->LinkLanguage;
-  implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES";
+  std::string implicitDirVar = cmStrCat(
+    "CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES");
   if (const char* implicitDirs =
         this->Makefile->GetDefinition(implicitDirVar)) {
     cmExpandList(implicitDirs, implicitDirVec);
@@ -1368,8 +1342,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
   switch (this->Target->GetPolicyStatusCMP0008()) {
     case cmPolicies::WARN: {
       // Print the warning at most once for this item.
-      std::string wid = "CMP0008-WARNING-GIVEN-";
-      wid += item;
+      std::string wid = cmStrCat("CMP0008-WARNING-GIVEN-", item);
       if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(wid)) {
         this->CMakeInstance->GetState()->SetGlobalProperty(wid, "1");
         std::ostringstream w;
@@ -1530,9 +1503,8 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
   }
 
   // Get language-specific implicit directories.
-  std::string implicitDirVar = "CMAKE_";
-  implicitDirVar += this->LinkLanguage;
-  implicitDirVar += "_IMPLICIT_LINK_DIRECTORIES";
+  std::string implicitDirVar =
+    cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_DIRECTORIES");
   if (const char* implicitDirs =
         this->Makefile->GetDefinition(implicitDirVar)) {
     cmExpandList(implicitDirs, implicitDirVec);
@@ -1543,9 +1515,8 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
 
   // Get language-specific implicit libraries.
   std::vector<std::string> implicitLibVec;
-  std::string implicitLibVar = "CMAKE_";
-  implicitLibVar += this->LinkLanguage;
-  implicitLibVar += "_IMPLICIT_LINK_LIBRARIES";
+  std::string implicitLibVar =
+    cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_LIBRARIES");
   if (const char* implicitLibs =
         this->Makefile->GetDefinition(implicitLibVar)) {
     cmExpandList(implicitLibs, implicitLibVec);
@@ -1749,9 +1720,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
           d = d.substr(rootPath.size());
         } else if (stagePath && *stagePath && d.find(stagePath) == 0) {
           std::string suffix = d.substr(strlen(stagePath));
-          d = installPrefix;
-          d += "/";
-          d += suffix;
+          d = cmStrCat(installPrefix, '/', suffix);
           cmSystemTools::ConvertToUnixSlashes(d);
         } else if (use_relative_build_rpath) {
           // If expansion of the $ORIGIN token is supported and permitted per
@@ -1782,9 +1751,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
             d = d.substr(rootPath.size());
           } else if (stagePath && *stagePath && d.find(stagePath) == 0) {
             std::string suffix = d.substr(strlen(stagePath));
-            d = installPrefix;
-            d += "/";
-            d += suffix;
+            d = cmStrCat(installPrefix, '/', suffix);
             cmSystemTools::ConvertToUnixSlashes(d);
           }
           if (emitted.insert(d).second) {

+ 3 - 2
Source/cmConfigureFileCommand.cxx

@@ -8,6 +8,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmNewLineStyle.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 // cmConfigureFileCommand
@@ -88,8 +89,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
     }
   }
   if (!unknown_args.empty()) {
-    std::string msg = "configure_file called with unknown argument(s):\n";
-    msg += unknown_args;
+    std::string msg = cmStrCat(
+      "configure_file called with unknown argument(s):\n", unknown_args);
     status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, msg);
   }
 

+ 3 - 7
Source/cmCoreTryCompile.cxx

@@ -1045,16 +1045,14 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
     this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
   // if a config was specified try that first
   if (config && config[0]) {
-    std::string tmp = "/";
-    tmp += config;
+    std::string tmp = cmStrCat('/', config);
     searchDirs.push_back(std::move(tmp));
   }
   searchDirs.emplace_back("/Debug");
 #if defined(__APPLE__)
   std::string app = "/" + targetName + ".app";
   if (config && config[0]) {
-    std::string tmp = "/";
-    tmp += config + app;
+    std::string tmp = cmStrCat('/', config, app);
     searchDirs.push_back(std::move(tmp));
   }
   std::string tmp = "/Debug" + app;
@@ -1064,9 +1062,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
   searchDirs.emplace_back("/Development");
 
   for (std::string const& sdir : searchDirs) {
-    std::string command = this->BinaryDirectory;
-    command += sdir;
-    command += tmpOutputFile;
+    std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile);
     if (cmSystemTools::FileExists(command)) {
       this->OutputFile = cmSystemTools::CollapseFullPath(command);
       return;

+ 5 - 8
Source/cmCreateTestSourceList.cxx

@@ -6,6 +6,7 @@
 
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -31,17 +32,14 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
         this->SetError("incorrect arguments to EXTRA_INCLUDE");
         return false;
       }
-      extraInclude = "#include \"";
-      extraInclude += *i;
-      extraInclude += "\"\n";
+      extraInclude = cmStrCat("#include \"", *i, "\"\n");
     } else if (*i == "FUNCTION") {
       ++i;
       if (i == args.end()) {
         this->SetError("incorrect arguments to FUNCTION");
         return false;
       }
-      function = *i;
-      function += "(&ac, &av);\n";
+      function = cmStrCat(*i, "(&ac, &av);\n");
     } else {
       tests.push_back(*i);
     }
@@ -60,9 +58,8 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
       "You must specify a file extension for the test driver file.");
     return false;
   }
-  std::string driver = this->Makefile->GetCurrentBinaryDirectory();
-  driver += "/";
-  driver += *i;
+  std::string driver =
+    cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', *i);
   ++i;
 
   std::string configFile = cmSystemTools::GetCMakeRoot();

+ 3 - 2
Source/cmCurl.cxx

@@ -7,6 +7,7 @@
 #  define CMAKE_FIND_CAFILE
 #  include "cmSystemTools.h"
 #endif
+#include "cmStringAlgorithms.h"
 
 // curl versions before 7.21.5 did not provide this error code
 #if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505
@@ -72,8 +73,8 @@ std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
     } else if (netrc_level == "IGNORED") {
       curl_netrc_level = CURL_NETRC_IGNORED;
     } else {
-      e = "NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ";
-      e += netrc_level;
+      e = cmStrCat("NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ",
+                   netrc_level);
       return e;
     }
   }

+ 1 - 3
Source/cmCustomCommandGenerator.cxx

@@ -169,9 +169,7 @@ std::string escapeForShellOldStyle(const std::string& str)
   std::string temp = str;
   if (temp.find(" ") != std::string::npos &&
       temp.find("\"") == std::string::npos) {
-    result = "\"";
-    result += str;
-    result += "\"";
+    result = cmStrCat('"', str, '"');
     return result;
   }
   return str;

+ 3 - 6
Source/cmDepends.cxx

@@ -236,18 +236,15 @@ void cmDepends::SetIncludePathFromLanguage(const std::string& lang)
 {
   // Look for the new per "TARGET_" variant first:
   const char* includePath = nullptr;
-  std::string includePathVar = "CMAKE_";
-  includePathVar += lang;
-  includePathVar += "_TARGET_INCLUDE_PATH";
+  std::string includePathVar =
+    cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH");
   cmMakefile* mf = this->LocalGenerator->GetMakefile();
   includePath = mf->GetDefinition(includePathVar);
   if (includePath) {
     cmExpandList(includePath, this->IncludePath);
   } else {
     // Fallback to the old directory level variable if no per-target var:
-    includePathVar = "CMAKE_";
-    includePathVar += lang;
-    includePathVar += "_INCLUDE_PATH";
+    includePathVar = cmStrCat("CMAKE_", lang, "_INCLUDE_PATH");
     includePath = mf->GetDefinition(includePathVar);
     if (includePath) {
       cmExpandList(includePath, this->IncludePath);

+ 9 - 14
Source/cmDependsC.cxx

@@ -36,15 +36,12 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
   std::string scanRegex = "^.*$";
   std::string complainRegex = "^$";
   {
-    std::string scanRegexVar = "CMAKE_";
-    scanRegexVar += lang;
-    scanRegexVar += "_INCLUDE_REGEX_SCAN";
+    std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN");
     if (const char* sr = mf->GetDefinition(scanRegexVar)) {
       scanRegex = sr;
     }
-    std::string complainRegexVar = "CMAKE_";
-    complainRegexVar += lang;
-    complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
+    std::string complainRegexVar =
+      cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN");
     if (const char* cr = mf->GetDefinition(complainRegexVar)) {
       complainRegex = cr;
     }
@@ -54,17 +51,15 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
   this->IncludeRegexScan.compile(scanRegex);
   this->IncludeRegexComplain.compile(complainRegex);
   this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE;
-  this->IncludeRegexScanString = INCLUDE_REGEX_SCAN_MARKER;
-  this->IncludeRegexScanString += scanRegex;
-  this->IncludeRegexComplainString = INCLUDE_REGEX_COMPLAIN_MARKER;
-  this->IncludeRegexComplainString += complainRegex;
+  this->IncludeRegexScanString =
+    cmStrCat(INCLUDE_REGEX_SCAN_MARKER, scanRegex);
+  this->IncludeRegexComplainString =
+    cmStrCat(INCLUDE_REGEX_COMPLAIN_MARKER, complainRegex);
 
   this->SetupTransforms();
 
-  this->CacheFileName = this->TargetDirectory;
-  this->CacheFileName += "/";
-  this->CacheFileName += lang;
-  this->CacheFileName += ".includecache";
+  this->CacheFileName =
+    cmStrCat(this->TargetDirectory, '/', lang, ".includecache");
 
   this->ReadCacheFile();
 }

+ 12 - 31
Source/cmDependsFortran.cxx

@@ -180,8 +180,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
   }
 
   // Store the list of modules provided by this target.
-  std::string fiName = this->TargetDirectory;
-  fiName += "/fortran.internal";
+  std::string fiName = cmStrCat(this->TargetDirectory, "/fortran.internal");
   cmGeneratedFileStream fiStream(fiName);
   fiStream << "# The fortran modules provided by this target.\n";
   fiStream << "provides\n";
@@ -192,23 +191,18 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
 
   // Create a script to clean the modules.
   if (!provides.empty()) {
-    std::string fcName = this->TargetDirectory;
-    fcName += "/cmake_clean_Fortran.cmake";
+    std::string fcName =
+      cmStrCat(this->TargetDirectory, "/cmake_clean_Fortran.cmake");
     cmGeneratedFileStream fcStream(fcName);
     fcStream << "# Remove fortran modules provided by this target.\n";
     fcStream << "FILE(REMOVE";
     std::string currentBinDir =
       this->LocalGenerator->GetCurrentBinaryDirectory();
     for (std::string const& i : provides) {
-      std::string mod_upper = mod_dir;
-      mod_upper += "/";
-      std::string mod_lower = mod_dir;
-      mod_lower += "/";
+      std::string mod_upper = cmStrCat(mod_dir, '/');
+      std::string mod_lower = cmStrCat(mod_dir, '/');
       cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower);
-      std::string stamp = stamp_dir;
-      stamp += "/";
-      stamp += i;
-      stamp += ".stamp";
+      std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp");
       fcStream << "\n";
       fcStream << "  \""
                << this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
@@ -315,10 +309,7 @@ void cmDependsFortran::ConsiderModule(const std::string& name,
   if (required != this->Internal->TargetRequires.end() &&
       required->second.empty()) {
     // The module is provided by a CMake target.  It will have a stamp file.
-    std::string stampFile = stampDir;
-    stampFile += "/";
-    stampFile += name;
-    stampFile += ".stamp";
+    std::string stampFile = cmStrCat(stampDir, '/', name, ".stamp");
     required->second = stampFile;
   }
 }
@@ -392,16 +383,11 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
       // Always use lower case for the mod stamp file name.  The
       // cmake_copy_f90_mod will call back to this class, which will
       // try various cases for the real mod file name.
-      std::string modFile = mod_dir;
-      modFile += "/";
-      modFile += i;
+      std::string modFile = cmStrCat(mod_dir, '/', i);
       modFile = this->LocalGenerator->ConvertToOutputFormat(
         this->MaybeConvertToRelativePath(binDir, modFile),
         cmOutputConverter::SHELL);
-      std::string stampFile = stamp_dir;
-      stampFile += "/";
-      stampFile += i;
-      stampFile += ".stamp";
+      std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp");
       stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
       std::string const stampFileForShell =
         this->LocalGenerator->ConvertToOutputFormat(stampFile,
@@ -435,8 +421,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
 
     // Make sure the module timestamp rule is evaluated by the time
     // the target finishes building.
-    std::string driver = this->TargetDirectory;
-    driver += "/build";
+    std::string driver = cmStrCat(this->TargetDirectory, "/build");
     driver = cmSystemTools::ConvertToOutputPath(
       this->MaybeConvertToRelativePath(binDir, driver));
     makeDepends << driver << ": " << obj_m << ".provides.build\n";
@@ -456,18 +441,14 @@ bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
   std::string fullName;
   for (std::string const& ip : this->IncludePath) {
     // Try the lower-case name.
-    fullName = ip;
-    fullName += "/";
-    fullName += mod_lower;
+    fullName = cmStrCat(ip, '/', mod_lower);
     if (cmSystemTools::FileExists(fullName, true)) {
       module = fullName;
       return true;
     }
 
     // Try the upper-case name.
-    fullName = ip;
-    fullName += "/";
-    fullName += mod_upper;
+    fullName = cmStrCat(ip, '/', mod_upper);
     if (cmSystemTools::FileExists(fullName, true)) {
       module = fullName;
       return true;

+ 4 - 7
Source/cmExecProgramCommand.cxx

@@ -8,6 +8,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 typedef cmProcessOutput::Encoding Encoding;
@@ -74,9 +75,8 @@ bool cmExecProgramCommand(std::vector<std::string> const& args,
 
   std::string command;
   if (!arguments.empty()) {
-    command = cmSystemTools::ConvertToRunCommandPath(args[0]);
-    command += " ";
-    command += arguments;
+    command = cmStrCat(cmSystemTools::ConvertToRunCommandPath(args[0]), ' ',
+                       arguments);
   } else {
     command = args[0];
   }
@@ -192,10 +192,7 @@ bool RunCommand(std::string command, std::string& output, int& retVal,
 #else
   std::string commandInDir;
   if (dir) {
-    commandInDir = "cd \"";
-    commandInDir += dir;
-    commandInDir += "\" && ";
-    commandInDir += command;
+    commandInDir = cmStrCat("cd \"", dir, "\" && ", command);
   } else {
     commandInDir = command;
   }

+ 1 - 2
Source/cmExportBuildAndroidMKGenerator.cxx

@@ -41,8 +41,7 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
   std::ostream& os, cmGeneratorTarget const* target,
   cmStateEnums::TargetType /*targetType*/)
 {
-  std::string targetName = this->Namespace;
-  targetName += target->GetExportName();
+  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
   os << "include $(CLEAR_VARS)\n";
   os << "LOCAL_MODULE := ";
   os << targetName << "\n";

+ 3 - 6
Source/cmExportBuildFileGenerator.cxx

@@ -202,8 +202,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
   cmMakefile* mf = target->Makefile;
 
   if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-    std::string prop = "IMPORTED_OBJECTS";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
 
     // Compute all the object files inside this target and setup
     // IMPORTED_OBJECTS as a list of object files
@@ -221,8 +220,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
   } else {
     // Add the main target file.
     {
-      std::string prop = "IMPORTED_LOCATION";
-      prop += suffix;
+      std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
       std::string value;
       if (target->IsAppBundleOnApple()) {
         value =
@@ -236,8 +234,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
 
     // Add the import library for windows DLLs.
     if (target->HasImportLibrary(config)) {
-      std::string prop = "IMPORTED_IMPLIB";
-      prop += suffix;
+      std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
       std::string value =
         target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
       if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {

+ 2 - 5
Source/cmExportCommand.cxx

@@ -299,8 +299,7 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
                                               const char* content,
                                               const char* hash)
 {
-  std::string key = "Software\\Kitware\\CMake\\Packages\\";
-  key += package;
+  std::string key = cmStrCat("Software\\Kitware\\CMake\\Packages\\", package);
   HKEY hKey;
   LONG err =
     RegCreateKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(key).c_str(), 0,
@@ -334,9 +333,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
       B_OK) {
     return;
   }
-  std::string fname = dir;
-  fname += "/cmake/packages/";
-  fname += package;
+  std::string fname = cmStrCat(dir, "/cmake/packages/", package);
 #  else
   std::string fname;
   if (!cmSystemTools::GetEnv("HOME", fname)) {

+ 7 - 10
Source/cmExportFileGenerator.cxx

@@ -584,8 +584,8 @@ void cmExportFileGenerator::GenerateInterfaceProperties(
   const ImportPropertyMap& properties)
 {
   if (!properties.empty()) {
-    std::string targetName = this->Namespace;
-    targetName += target->GetExportName();
+    std::string targetName =
+      cmStrCat(this->Namespace, target->GetExportName());
     os << "set_target_properties(" << targetName << " PROPERTIES\n";
     for (auto const& property : properties) {
       os << "  " << property.first << " "
@@ -841,8 +841,8 @@ void cmExportFileGenerator::SetImportDetailProperties(
                                 "IMPORTED_LINK_DEPENDENT_LIBRARIES",
                                 iface->SharedDeps, properties, dummy);
     if (iface->Multiplicity > 0) {
-      std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
-      prop += suffix;
+      std::string prop =
+        cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
       std::ostringstream m;
       m << iface->Multiplicity;
       properties[prop] = m.str();
@@ -852,8 +852,7 @@ void cmExportFileGenerator::SetImportDetailProperties(
   // Add information if this target is a managed target
   if (target->GetManagedType(config) !=
       cmGeneratorTarget::ManagedType::Native) {
-    std::string prop = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix);
     std::string propval;
     if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
       propval = p;
@@ -904,8 +903,7 @@ void cmExportFileGenerator::SetImportLinkProperty(
   }
 
   // Store the property.
-  std::string prop = propName;
-  prop += suffix;
+  std::string prop = cmStrCat(propName, suffix);
   properties[prop] = link_entries;
 }
 
@@ -1182,8 +1180,7 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
   const std::set<std::string>& importedLocations)
 {
   // Construct the imported target name.
-  std::string targetName = this->Namespace;
-  targetName += target->GetExportName();
+  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
 
   os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName
      << " )\n"

+ 2 - 2
Source/cmExportInstallAndroidMKGenerator.cxx

@@ -11,6 +11,7 @@
 #include "cmInstallExportGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetExport.h"
@@ -58,8 +59,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
   std::ostream& os, cmGeneratorTarget const* target,
   cmStateEnums::TargetType /*targetType*/)
 {
-  std::string targetName = this->Namespace;
-  targetName += target->GetExportName();
+  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
   os << "include $(CLEAR_VARS)\n";
   os << "LOCAL_MODULE := ";
   os << targetName << "\n";

+ 5 - 13
Source/cmExportInstallFileGenerator.cxx

@@ -30,9 +30,7 @@ cmExportInstallFileGenerator::cmExportInstallFileGenerator(
 
 std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
 {
-  std::string glob = this->FileBase;
-  glob += "-*";
-  glob += this->FileExt;
+  std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
   return glob;
 }
 
@@ -277,10 +275,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig(
   }
 
   // Construct the name of the file to generate.
-  std::string fileName = this->FileDir;
-  fileName += "/";
-  fileName += this->FileBase;
-  fileName += "-";
+  std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-');
   if (!config.empty()) {
     fileName += cmSystemTools::LowerCase(config);
   } else {
@@ -392,8 +387,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
 
   if (itgen->IsImportLibrary()) {
     // Construct the property name.
-    std::string prop = "IMPORTED_IMPLIB";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
 
     // Append the installed file name.
     value += cmInstallTargetGenerator::GetInstallFilename(
@@ -404,8 +398,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
     importedLocations.insert(prop);
   } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
     // Construct the property name.
-    std::string prop = "IMPORTED_OBJECTS";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
 
     // Compute all the object files inside this target and setup
     // IMPORTED_OBJECTS as a list of object files
@@ -420,8 +413,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
     importedLocations.insert(prop);
   } else {
     // Construct the property name.
-    std::string prop = "IMPORTED_LOCATION";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
 
     // Append the installed file name.
     if (target->IsAppBundleOnApple()) {

+ 3 - 4
Source/cmExportLibraryDependenciesCommand.cxx

@@ -12,6 +12,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetLinkLibraryType.h"
@@ -61,8 +62,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename,
       }
 
       // Construct the dependency variable name.
-      std::string targetEntry = target.GetName();
-      targetEntry += "_LIB_DEPENDS";
+      std::string targetEntry = cmStrCat(target.GetName(), "_LIB_DEPENDS");
 
       // Construct the dependency variable value with the direct link
       // dependencies.
@@ -71,8 +71,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename,
       cmTarget::LinkLibraryVectorType const& libs =
         target.GetOriginalLinkLibraries();
       for (cmTarget::LibraryID const& li : libs) {
-        std::string ltVar = li.first;
-        ltVar += "_LINK_TYPE";
+        std::string ltVar = cmStrCat(li.first, "_LINK_TYPE");
         std::string ltValue;
         switch (li.second) {
           case GENERAL_LibraryType:

+ 5 - 7
Source/cmExprParserHelper.cxx

@@ -3,6 +3,7 @@
 #include "cmExprParserHelper.h"
 
 #include "cmExprLexer.h"
+#include "cmStringAlgorithms.h"
 
 #include <iostream>
 #include <sstream>
@@ -41,16 +42,13 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
   try {
     int res = cmExpr_yyparse(yyscanner);
     if (res != 0) {
-      std::string e = "cannot parse the expression: \"" + InputBuffer + "\": ";
-      e += ErrorString;
-      e += ".";
+      std::string e = cmStrCat("cannot parse the expression: \"", InputBuffer,
+                               "\": ", ErrorString, '.');
       this->SetError(std::move(e));
     }
   } catch (std::runtime_error const& fail) {
-    std::string e =
-      "cannot evaluate the expression: \"" + InputBuffer + "\": ";
-    e += fail.what();
-    e += ".";
+    std::string e = cmStrCat("cannot evaluate the expression: \"", InputBuffer,
+                             "\": ", fail.what(), '.');
     this->SetError(std::move(e));
   } catch (std::out_of_range const&) {
     std::string e = "cannot evaluate the expression: \"" + InputBuffer +

+ 3 - 2
Source/cmExternalMakefileProjectGenerator.cxx

@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExternalMakefileProjectGenerator.h"
 
+#include "cmStringAlgorithms.h"
+
 #include <utility>
 
 class cmMakefile;
@@ -18,8 +20,7 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
   std::string fullName;
   if (!globalGenerator.empty()) {
     if (!extraGenerator.empty()) {
-      fullName = extraGenerator;
-      fullName += " - ";
+      fullName = cmStrCat(extraGenerator, " - ");
     }
     fullName += globalGenerator;
   }

+ 13 - 20
Source/cmExtraCodeBlocksGenerator.cxx

@@ -74,10 +74,9 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile(
   std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
   std::string projectName = lgs[0]->GetProjectName();
 
-  std::string filename = outputDir + "/";
-  filename += projectName + ".cbp";
-  std::string sessionFilename = outputDir + "/";
-  sessionFilename += projectName + ".layout";
+  std::string filename = cmStrCat(outputDir, '/', projectName, ".cbp");
+  std::string sessionFilename =
+    cmStrCat(outputDir, '/', projectName, ".layout");
 
   this->CreateNewProjectFile(lgs, filename);
 }
@@ -319,8 +318,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
           cmGeneratorTarget* gt = target;
           this->AppendTarget(xml, targetName, gt, make, lg, compiler,
                              makeArgs);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           this->AppendTarget(xml, fastTarget, gt, make, lg, compiler,
                              makeArgs);
         } break;
@@ -413,15 +411,13 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
   // A very similar version of that code exists also in the CodeLite
   // project generator.
   for (std::string const& fileName : cFiles) {
-    std::string headerBasename = cmSystemTools::GetFilenamePath(fileName);
-    headerBasename += "/";
-    headerBasename += cmSystemTools::GetFilenameWithoutExtension(fileName);
+    std::string headerBasename =
+      cmStrCat(cmSystemTools::GetFilenamePath(fileName), '/',
+               cmSystemTools::GetFilenameWithoutExtension(fileName));
 
     // check if there's a matching header around
     for (std::string const& ext : headerExts) {
-      std::string hname = headerBasename;
-      hname += ".";
-      hname += ext;
+      std::string hname = cmStrCat(headerBasename, '.', ext);
       // if it's already in the set, don't check if it exists on disk
       if (allFiles.find(hname) != allFiles.end()) {
         break;
@@ -466,12 +462,9 @@ std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
   // this file doesn't seem to be used by C::B in custom makefile mode,
   // but we generate a unique file for each OBJECT library so in case
   // C::B uses it in some way, the targets don't interfere with each other.
-  std::string filename = lg->GetCurrentBinaryDirectory();
-  filename += "/";
-  filename += lg->GetTargetDirectory(target);
-  filename += "/";
-  filename += target->GetName();
-  filename += ".objlib";
+  std::string filename = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+                                  lg->GetTargetDirectory(target), '/',
+                                  target->GetName(), ".objlib");
   cmGeneratedFileStream fout(filename);
   if (fout) {
     /* clang-format off */
@@ -491,8 +484,8 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
   const std::string& compiler, const std::string& makeFlags)
 {
   cmMakefile const* makefile = lg->GetMakefile();
-  std::string makefileName = lg->GetCurrentBinaryDirectory();
-  makefileName += "/Makefile";
+  std::string makefileName =
+    cmStrCat(lg->GetCurrentBinaryDirectory(), "/Makefile");
 
   xml.StartElement("Target");
   xml.Attribute("title", targetName);

+ 6 - 8
Source/cmExtraCodeLiteGenerator.cxx

@@ -68,8 +68,8 @@ void cmExtraCodeLiteGenerator::Generate()
       workspaceOutputDir = lg->GetCurrentBinaryDirectory();
       workspaceProjectName = lg->GetProjectName();
       workspaceSourcePath = lg->GetSourceDirectory();
-      workspaceFileName = workspaceOutputDir + "/";
-      workspaceFileName += workspaceProjectName + ".workspace";
+      workspaceFileName =
+        cmStrCat(workspaceOutputDir, '/', workspaceProjectName, ".workspace");
       this->WorkspacePath = lg->GetCurrentBinaryDirectory();
       break;
     }
@@ -299,15 +299,13 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
   // A very similar version of that code exists also in the CodeBlocks
   // project generator.
   for (auto const& sit : cFiles) {
-    std::string headerBasename = cmSystemTools::GetFilenamePath(sit.first);
-    headerBasename += "/";
-    headerBasename += cmSystemTools::GetFilenameWithoutExtension(sit.first);
+    std::string headerBasename =
+      cmStrCat(cmSystemTools::GetFilenamePath(sit.first), '/',
+               cmSystemTools::GetFilenameWithoutExtension(sit.first));
 
     // check if there's a matching header around
     for (std::string const& ext : headerExts) {
-      std::string hname = headerBasename;
-      hname += ".";
-      hname += ext;
+      std::string hname = cmStrCat(headerBasename, '.', ext);
       // if it's already in the set, don't check if it exists on disk
       std::set<std::string>::const_iterator headerIt = otherFiles.find(hname);
       if (headerIt != otherFiles.end()) {

+ 13 - 26
Source/cmExtraEclipseCDT4Generator.cxx

@@ -240,8 +240,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
   std::string envVarValue;
   const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
 
-  std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_";
-  cacheEntryName += envVar;
+  std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar);
   const std::string* cacheValue =
     lg->GetState()->GetInitializedCacheValue(cacheEntryName);
 
@@ -464,9 +463,7 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
   cmXMLWriter& xml)
 {
   for (cmSourceGroup const& sg : sourceGroups) {
-    std::string linkName3 = linkName;
-    linkName3 += "/";
-    linkName3 += sg.GetFullName();
+    std::string linkName3 = cmStrCat(linkName, '/', sg.GetFullName());
 
     std::replace(linkName3.begin(), linkName3.end(), '\\', '/');
 
@@ -481,9 +478,8 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
       std::string const& fullPath = file->GetFullPath();
 
       if (!cmSystemTools::FileIsDirectory(fullPath)) {
-        std::string linkName4 = linkName3;
-        linkName4 += "/";
-        linkName4 += cmSystemTools::GetFilenameName(fullPath);
+        std::string linkName4 =
+          cmStrCat(linkName3, '/', cmSystemTools::GetFilenameName(fullPath));
         cmExtraEclipseCDT4Generator::AppendLinkedResource(
           xml, linkName4,
           cmExtraEclipseCDT4Generator::GetEclipsePath(fullPath), LinkToFile);
@@ -503,8 +499,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
     const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
 
     for (cmGeneratorTarget* target : targets) {
-      std::string linkName2 = linkName;
-      linkName2 += "/";
+      std::string linkName2 = cmStrCat(linkName, '/');
       switch (target->GetType()) {
         case cmStateEnums::EXECUTABLE:
         case cmStateEnums::STATIC_LIBRARY:
@@ -566,8 +561,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
     // .project itself
     if ((baseDir != linkSourceDirectory) &&
         !cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) {
-      std::string linkName = "[Subprojects]/";
-      linkName += it.first;
+      std::string linkName = cmStrCat("[Subprojects]/", it.first);
       cmExtraEclipseCDT4Generator::AppendLinkedResource(
         xml, linkName,
         cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory),
@@ -970,28 +964,21 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
                                                            : "[lib] ");
           cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
                                                     makeArgs, subdir, prefix);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           cmExtraEclipseCDT4Generator::AppendTarget(xml, fastTarget, make,
                                                     makeArgs, subdir, prefix);
 
           // Add Build and Clean targets in the virtual folder of targets:
           if (this->SupportsVirtualFolders) {
-            std::string virtDir = "[Targets]/";
-            virtDir += prefix;
-            virtDir += targetName;
-            std::string buildArgs = "-C \"";
-            buildArgs += lgen->GetBinaryDirectory();
-            buildArgs += "\" ";
-            buildArgs += makeArgs;
+            std::string virtDir = cmStrCat("[Targets]/", prefix, targetName);
+            std::string buildArgs =
+              cmStrCat("-C \"", lgen->GetBinaryDirectory(), "\" ", makeArgs);
             cmExtraEclipseCDT4Generator::AppendTarget(
               xml, "Build", make, buildArgs, virtDir, "", targetName.c_str());
 
-            std::string cleanArgs = "-E chdir \"";
-            cleanArgs += lgen->GetCurrentBinaryDirectory();
-            cleanArgs += "\" \"";
-            cleanArgs += cmSystemTools::GetCMakeCommand();
-            cleanArgs += "\" -P \"";
+            std::string cleanArgs =
+              cmStrCat("-E chdir \"", lgen->GetCurrentBinaryDirectory(),
+                       "\" \"", cmSystemTools::GetCMakeCommand(), "\" -P \"");
             cmGeneratorTarget* gt = target;
             cleanArgs += lgen->GetTargetDirectory(gt);
             cleanArgs += "/cmake_clean.cmake\"";

+ 8 - 14
Source/cmExtraKateGenerator.cxx

@@ -9,6 +9,7 @@
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <ostream>
@@ -53,8 +54,7 @@ void cmExtraKateGenerator::Generate()
 void cmExtraKateGenerator::CreateKateProjectFile(
   const cmLocalGenerator* lg) const
 {
-  std::string filename = lg->GetBinaryDirectory();
-  filename += "/.kateproject";
+  std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject");
   cmGeneratedFileStream fout(filename);
   if (!fout) {
     return;
@@ -164,8 +164,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
         case cmStateEnums::OBJECT_LIBRARY: {
           this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
                              homeOutputDir);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir,
                              homeOutputDir);
 
@@ -208,10 +207,8 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout,
 void cmExtraKateGenerator::CreateDummyKateProjectFile(
   const cmLocalGenerator* lg) const
 {
-  std::string filename = lg->GetBinaryDirectory();
-  filename += "/";
-  filename += this->ProjectName;
-  filename += ".kateproject";
+  std::string filename =
+    cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject");
   cmGeneratedFileStream fout(filename);
   if (!fout) {
     return;
@@ -224,20 +221,17 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile(
 std::string cmExtraKateGenerator::GenerateFilesString(
   const cmLocalGenerator* lg) const
 {
-  std::string s = lg->GetSourceDirectory();
-  s += "/.git";
+  std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git");
   if (cmSystemTools::FileExists(s)) {
     return "\"git\": 1 ";
   }
 
-  s = lg->GetSourceDirectory();
-  s += "/.svn";
+  s = cmStrCat(lg->GetSourceDirectory(), "/.svn");
   if (cmSystemTools::FileExists(s)) {
     return "\"svn\": 1 ";
   }
 
-  s = lg->GetSourceDirectory();
-  s += "/";
+  s = cmStrCat(lg->GetSourceDirectory(), '/');
 
   std::set<std::string> files;
   std::string tmp;

+ 4 - 6
Source/cmExtraSublimeTextGenerator.cxx

@@ -219,8 +219,7 @@ void cmExtraSublimeTextGenerator::AppendAllTargets(
           this->AppendTarget(fout, targetName, lg, target, make.c_str(),
                              makefile, compiler.c_str(), sourceFileFlags,
                              false);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           this->AppendTarget(fout, fastTarget, lg, target, make.c_str(),
                              makefile, compiler.c_str(), sourceFileFlags,
                              false);
@@ -311,8 +310,7 @@ void cmExtraSublimeTextGenerator::AppendTarget(
 std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
   const std::string& make, const char* makefile, const std::string& target)
 {
-  std::string command = "\"";
-  command += make + "\"";
+  std::string command = cmStrCat('"', make, '"');
   std::string generator = this->GlobalGenerator->GetName();
   if (generator == "NMake Makefiles") {
     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
@@ -393,8 +391,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
       defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS));
   }
 
-  std::string defPropName = "COMPILE_DEFINITIONS_";
-  defPropName += cmSystemTools::UpperCase(config);
+  std::string defPropName =
+    cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
   if (const char* config_compile_defs = source->GetProperty(defPropName)) {
     lg->AppendDefines(
       defines,

+ 5 - 6
Source/cmFLTKWrapUICommand.cxx

@@ -21,12 +21,11 @@ static void FinalAction(cmMakefile& makefile, std::string const& name)
   // they didn;t then print a warning and add then anyhow
   cmTarget* target = makefile.FindLocalNonAliasTarget(name);
   if (!target) {
-    std::string msg =
-      "FLTK_WRAP_UI was called with a target that was never created: ";
-    msg += name;
-    msg += ".  The problem was found while processing the source directory: ";
-    msg += makefile.GetCurrentSourceDirectory();
-    msg += ".  This FLTK_WRAP_UI call will be ignored.";
+    std::string msg = cmStrCat(
+      "FLTK_WRAP_UI was called with a target that was never created: ", name,
+      ".  The problem was found while processing the source directory: ",
+      makefile.GetCurrentSourceDirectory(),
+      ".  This FLTK_WRAP_UI call will be ignored.");
     cmSystemTools::Message(msg, "Warning");
   }
 }

+ 1 - 3
Source/cmFileAPI.cxx

@@ -407,9 +407,7 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind)
 
 std::string cmFileAPI::ObjectName(Object const& o)
 {
-  std::string name = ObjectKindName(o.Kind);
-  name += "-v";
-  name += std::to_string(o.Version);
+  std::string name = cmStrCat(ObjectKindName(o.Kind), "-v", o.Version);
   return name;
 }
 

+ 40 - 51
Source/cmFileCommand.cxx

@@ -97,8 +97,8 @@ bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
 
   std::string fileName = *i;
   if (!cmsys::SystemTools::FileIsFullPath(*i)) {
-    fileName = status.GetMakefile().GetCurrentSourceDirectory();
-    fileName += "/" + *i;
+    fileName =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
   }
 
   i++;
@@ -134,20 +134,18 @@ bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
   cmsys::ofstream file(fileName.c_str(),
                        append ? std::ios::app : std::ios::out);
   if (!file) {
-    std::string error = "failed to open for writing (";
-    error += cmSystemTools::GetLastSystemError();
-    error += "):\n  ";
-    error += fileName;
+    std::string error =
+      cmStrCat("failed to open for writing (",
+               cmSystemTools::GetLastSystemError(), "):\n  ", fileName);
     status.SetError(error);
     return false;
   }
   std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
   file << message;
   if (!file) {
-    std::string error = "write failed (";
-    error += cmSystemTools::GetLastSystemError();
-    error += "):\n  ";
-    error += fileName;
+    std::string error =
+      cmStrCat("write failed (", cmSystemTools::GetLastSystemError(), "):\n  ",
+               fileName);
     status.SetError(error);
     return false;
   }
@@ -198,8 +196,8 @@ bool HandleReadCommand(std::vector<std::string> const& args,
 
   std::string fileName = fileNameArg;
   if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
-    fileName = status.GetMakefile().GetCurrentSourceDirectory();
-    fileName += "/" + fileNameArg;
+    fileName = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+                        fileNameArg);
   }
 
 // Open the specified file.
@@ -212,10 +210,9 @@ bool HandleReadCommand(std::vector<std::string> const& args,
 #endif
 
   if (!file) {
-    std::string error = "failed to open for reading (";
-    error += cmSystemTools::GetLastSystemError();
-    error += "):\n  ";
-    error += fileName;
+    std::string error =
+      cmStrCat("failed to open for reading (",
+               cmSystemTools::GetLastSystemError(), "):\n  ", fileName);
     status.SetError(error);
     return false;
   }
@@ -315,8 +312,8 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
   // Get the file to read.
   std::string fileName = args[1];
   if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
-    fileName = status.GetMakefile().GetCurrentSourceDirectory();
-    fileName += "/" + args[1];
+    fileName =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
   }
 
   // Get the variable in which to store the results.
@@ -468,8 +465,8 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
   if (hex_conversion_enabled) {
     // TODO: should work without temp file, but just on a memory buffer
     std::string binaryFileName =
-      status.GetMakefile().GetCurrentBinaryDirectory();
-    binaryFileName += "/CMakeFiles/FileCommandStringsBinaryFile";
+      cmStrCat(status.GetMakefile().GetCurrentBinaryDirectory(),
+               "/CMakeFiles/FileCommandStringsBinaryFile");
     if (cmHexFileConverter::TryConvert(fileName, binaryFileName)) {
       fileName = binaryFileName;
     }
@@ -872,8 +869,8 @@ bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
   {
     const std::string* cdir = &arg;
     if (!cmsys::SystemTools::FileIsFullPath(arg)) {
-      expr = status.GetMakefile().GetCurrentSourceDirectory();
-      expr += "/" + arg;
+      expr =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
       cdir = &expr;
     }
     if (!status.GetMakefile().CanIWriteThisFile(*cdir)) {
@@ -903,8 +900,8 @@ bool HandleTouchImpl(std::vector<std::string> const& args, bool create,
   {
     std::string tfile = arg;
     if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
-      tfile = status.GetMakefile().GetCurrentSourceDirectory();
-      tfile += "/" + arg;
+      tfile =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
     }
     if (!status.GetMakefile().CanIWriteThisFile(tfile)) {
       std::string e =
@@ -1074,11 +1071,8 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
   }
   if (success) {
     if (changed) {
-      std::string message = "Set runtime path of \"";
-      message += file;
-      message += "\" to \"";
-      message += newRPath;
-      message += "\"";
+      std::string message =
+        cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
       status.GetMakefile().DisplayStatus(message, -1);
     }
     ft.Store(file);
@@ -1136,9 +1130,8 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
   }
   if (success) {
     if (removed) {
-      std::string message = "Removed runtime path from \"";
-      message += file;
-      message += "\"";
+      std::string message =
+        cmStrCat("Removed runtime path from \"", file, '"');
       status.GetMakefile().DisplayStatus(message, -1);
     }
     ft.Store(file);
@@ -1307,13 +1300,13 @@ bool HandleRename(std::vector<std::string> const& args,
   // Compute full path for old and new names.
   std::string oldname = args[1];
   if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
-    oldname = status.GetMakefile().GetCurrentSourceDirectory();
-    oldname += "/" + args[1];
+    oldname =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
   }
   std::string newname = args[2];
   if (!cmsys::SystemTools::FileIsFullPath(newname)) {
-    newname = status.GetMakefile().GetCurrentSourceDirectory();
-    newname += "/" + args[2];
+    newname =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
   }
 
   if (!cmSystemTools::RenameFile(oldname, newname)) {
@@ -1349,8 +1342,8 @@ bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
       continue;
     }
     if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
-      fileName = status.GetMakefile().GetCurrentSourceDirectory();
-      fileName += "/" + arg;
+      fileName =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
     }
 
     if (cmSystemTools::FileIsDirectory(fileName) &&
@@ -1704,8 +1697,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
       std::string::size_type pos = i->find("=");
       if (pos == std::string::npos) {
         std::string err =
-          "DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ";
-        err += *i;
+          cmStrCat("DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ", *i);
         status.SetError(err);
         return false;
       }
@@ -1713,8 +1705,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
       expectedHash = cmSystemTools::LowerCase(i->substr(pos + 1));
       hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo));
       if (!hash) {
-        std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: ";
-        err += algo;
+        std::string err =
+          cmStrCat("DOWNLOAD EXPECTED_HASH given unknown ALGO: ", algo);
         status.SetError(err);
         return false;
       }
@@ -1735,8 +1727,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
       curl_headers.push_back(*i);
     } else {
       // Do not return error for compatibility reason.
-      std::string err = "Unexpected argument: ";
-      err += *i;
+      std::string err = cmStrCat("Unexpected argument: ", *i);
       status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err);
     }
     ++i;
@@ -1749,9 +1740,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
     std::string msg;
     std::string actualHash = hash->HashFile(file);
     if (actualHash == expectedHash) {
-      msg = "returning early; file already exists with expected ";
-      msg += hashMatchMSG;
-      msg += "\"";
+      msg = cmStrCat("returning early; file already exists with expected ",
+                     hashMatchMSG, '"');
       if (!statusVar.empty()) {
         std::ostringstream result;
         result << 0 << ";\"" << msg;
@@ -2050,8 +2040,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
       curl_headers.push_back(*i);
     } else {
       // Do not return error for compatibility reason.
-      std::string err = "Unexpected argument: ";
-      err += *i;
+      std::string err = cmStrCat("Unexpected argument: ", *i);
       status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err);
     }
 
@@ -2062,8 +2051,8 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
   //
   FILE* fin = cmsys::SystemTools::Fopen(filename, "rb");
   if (!fin) {
-    std::string errStr = "UPLOAD cannot open file '";
-    errStr += filename + "' for reading.";
+    std::string errStr =
+      cmStrCat("UPLOAD cannot open file '", filename, "' for reading.");
     status.SetError(errStr);
     return false;
   }

+ 8 - 13
Source/cmFileCopier.cxx

@@ -314,8 +314,8 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       if (arg.empty() || cmSystemTools::FileIsFullPath(arg)) {
         this->Destination = arg;
       } else {
-        this->Destination = this->Makefile->GetCurrentBinaryDirectory();
-        this->Destination += "/" + arg;
+        this->Destination =
+          cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', arg);
       }
       this->Doing = DoingNone;
       break;
@@ -323,8 +323,8 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       if (cmSystemTools::FileIsFullPath(arg)) {
         this->FilesFromDir = arg;
       } else {
-        this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
-        this->FilesFromDir += "/" + arg;
+        this->FilesFromDir =
+          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg);
       }
       cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
       this->Doing = DoingNone;
@@ -334,9 +334,8 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       // leading slash and trailing end-of-string in the matched
       // string to make sure the pattern matches only whole file
       // names.
-      std::string regex = "/";
-      regex += cmsys::Glob::PatternToRegex(arg, false);
-      regex += "$";
+      std::string regex =
+        cmStrCat('/', cmsys::Glob::PatternToRegex(arg, false), '$');
       this->MatchRules.emplace_back(regex);
       this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
       if (this->CurrentMatchRule->Regex.is_valid()) {
@@ -699,12 +698,8 @@ bool cmFileCopier::InstallDirectory(const std::string& source,
   for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) {
     if (!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
           strcmp(dir.GetFile(fileNum), "..") == 0)) {
-      std::string fromPath = source;
-      fromPath += "/";
-      fromPath += dir.GetFile(fileNum);
-      std::string toPath = destination;
-      toPath += "/";
-      toPath += dir.GetFile(fileNum);
+      std::string fromPath = cmStrCat(source, '/', dir.GetFile(fileNum));
+      std::string toPath = cmStrCat(destination, '/', dir.GetFile(fileNum));
       if (!this->Install(fromPath, toPath)) {
         return false;
       }

+ 7 - 7
Source/cmFileInstaller.cxx

@@ -59,8 +59,8 @@ void cmFileInstaller::ReportCopy(const std::string& toFile, Type type,
                                  bool copy)
 {
   if (!this->MessageNever && (copy || !this->MessageLazy)) {
-    std::string message = (copy ? "Installing: " : "Up-to-date: ");
-    message += toFile;
+    std::string message =
+      cmStrCat((copy ? "Installing: " : "Up-to-date: "), toFile);
     this->Makefile->DisplayStatus(message, -1);
   }
   if (type != TypeDir) {
@@ -311,11 +311,11 @@ bool cmFileInstaller::HandleInstallDestination()
       if (ch2 == '/') {
         // looks like a network path.
         std::string message =
-          "called with network path DESTINATION. This "
-          "does not make sense when using DESTDIR. Specify local "
-          "absolute path or remove DESTDIR environment variable."
-          "\nDESTINATION=\n";
-        message += destination;
+          cmStrCat("called with network path DESTINATION. This "
+                   "does not make sense when using DESTDIR. Specify local "
+                   "absolute path or remove DESTDIR environment variable."
+                   "\nDESTINATION=\n",
+                   destination);
         this->Status.SetError(message);
         return false;
       }

+ 3 - 9
Source/cmFindBase.cxx

@@ -189,9 +189,7 @@ void cmFindBase::FillCMakeEnvironmentPath()
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
 
   // Add CMAKE_*_PATH environment variables
-  std::string var = "CMAKE_";
-  var += this->CMakePathName;
-  var += "_PATH";
+  std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH");
   paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH");
   paths.AddEnvPath(var);
 
@@ -223,9 +221,7 @@ void cmFindBase::FillCMakeVariablePath()
   // Add CMake variables of the same name as the previous environment
   // variables CMAKE_*_PATH to be used most of the time with -D
   // command line options
-  std::string var = "CMAKE_";
-  var += this->CMakePathName;
-  var += "_PATH";
+  std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH");
   paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH");
   paths.AddCMakePath(var);
 
@@ -257,9 +253,7 @@ void cmFindBase::FillCMakeSystemVariablePath()
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
 
-  std::string var = "CMAKE_SYSTEM_";
-  var += this->CMakePathName;
-  var += "_PATH";
+  std::string var = cmStrCat("CMAKE_SYSTEM_", this->CMakePathName, "_PATH");
   paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
   paths.AddCMakePath(var);
 

+ 3 - 4
Source/cmFindCommon.cxx

@@ -92,8 +92,8 @@ void cmFindCommon::InitializeSearchPathGroups()
 void cmFindCommon::SelectDefaultRootPathMode()
 {
   // Check the policy variable for this find command type.
-  std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_";
-  findRootPathVar += this->CMakePathName;
+  std::string findRootPathVar =
+    cmStrCat("CMAKE_FIND_ROOT_PATH_MODE_", this->CMakePathName);
   std::string rootPathMode =
     this->Makefile->GetSafeDefinition(findRootPathVar);
   if (rootPathMode == "NEVER") {
@@ -229,8 +229,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
         rootedDir = up;
       } else if (!up.empty() && up[0] != '~') {
         // Start with the new root.
-        rootedDir = r;
-        rootedDir += "/";
+        rootedDir = cmStrCat(r, '/');
 
         // Append the original path with its old root removed.
         rootedDir += cmSystemTools::SplitPathRootComponent(up);

+ 5 - 12
Source/cmFindLibraryCommand.cxx

@@ -312,8 +312,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
   entry.Raw = name;
 
   // Build a regular expression to match library names.
-  std::string regex = "^";
-  regex += this->PrefixRegexStr;
+  std::string regex = cmStrCat('^', this->PrefixRegexStr);
   this->RegexFromLiteral(regex, name);
   regex += this->SuffixRegexStr;
   if (this->OpenBSD) {
@@ -349,8 +348,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
   // one cannot tell just from the library name whether it is a static
   // library or an import library).
   if (name.TryRaw) {
-    this->TestPath = path;
-    this->TestPath += name.Raw;
+    this->TestPath = cmStrCat(path, name.Raw);
     if (cmSystemTools::FileExists(this->TestPath, true)) {
       this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
       cmSystemTools::ConvertToUnixSlashes(this->BestPath);
@@ -375,8 +373,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
     std::string const& testName = origName;
 #endif
     if (name.Regex.find(testName)) {
-      this->TestPath = path;
-      this->TestPath += origName;
+      this->TestPath = cmStrCat(path, origName);
       if (!cmSystemTools::FileIsDirectory(this->TestPath)) {
         // This is a matching file.  Check if it is better than the
         // best name found so far.  Earlier prefixes are preferred,
@@ -466,9 +463,7 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
   // Search for all names in each search path.
   for (std::string const& d : this->SearchPaths) {
     for (std::string const& n : this->Names) {
-      fwPath = d;
-      fwPath += n;
-      fwPath += ".framework";
+      fwPath = cmStrCat(d, n, ".framework");
       if (cmSystemTools::FileIsDirectory(fwPath)) {
         return cmSystemTools::CollapseFullPath(fwPath);
       }
@@ -485,9 +480,7 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
   // Search for each name in all search paths.
   for (std::string const& n : this->Names) {
     for (std::string const& d : this->SearchPaths) {
-      fwPath = d;
-      fwPath += n;
-      fwPath += ".framework";
+      fwPath = cmStrCat(d, n, ".framework");
       if (cmSystemTools::FileIsDirectory(fwPath)) {
         return cmSystemTools::CollapseFullPath(fwPath);
       }

+ 43 - 79
Source/cmFindPackageCommand.cxx

@@ -408,19 +408,16 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
   if (this->Version.empty() || components.empty()) {
     // Check whether we are recursing inside "Find<name>.cmake" within
     // another find_package(<name>) call.
-    std::string mod = this->Name;
-    mod += "_FIND_MODULE";
+    std::string mod = cmStrCat(this->Name, "_FIND_MODULE");
     if (this->Makefile->IsOn(mod)) {
       if (this->Version.empty()) {
         // Get version information from the outer call if necessary.
         // Requested version string.
-        std::string ver = this->Name;
-        ver += "_FIND_VERSION";
+        std::string ver = cmStrCat(this->Name, "_FIND_VERSION");
         this->Version = this->Makefile->GetSafeDefinition(ver);
 
         // Whether an exact version is required.
-        std::string exact = this->Name;
-        exact += "_FIND_VERSION_EXACT";
+        std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
         this->VersionExact = this->Makefile->IsOn(exact);
       }
       if (components.empty()) {
@@ -458,8 +455,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
     }
   }
 
-  std::string disableFindPackageVar = "CMAKE_DISABLE_FIND_PACKAGE_";
-  disableFindPackageVar += this->Name;
+  std::string disableFindPackageVar =
+    cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
   if (this->Makefile->IsOn(disableFindPackageVar)) {
     if (this->Required) {
       std::ostringstream e;
@@ -589,8 +586,7 @@ bool cmFindPackageCommand::FindPackageUsingModuleMode()
 
 bool cmFindPackageCommand::FindPackageUsingConfigMode()
 {
-  this->Variable = this->Name;
-  this->Variable += "_DIR";
+  this->Variable = cmStrCat(this->Name, "_DIR");
 
   // Add the default name.
   if (this->Names.empty()) {
@@ -600,12 +596,10 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode()
   // Add the default configs.
   if (this->Configs.empty()) {
     for (std::string const& n : this->Names) {
-      std::string config = n;
-      config += "Config.cmake";
+      std::string config = cmStrCat(n, "Config.cmake");
       this->Configs.push_back(config);
 
-      config = cmSystemTools::LowerCase(n);
-      config += "-config.cmake";
+      config = cmStrCat(cmSystemTools::LowerCase(n), "-config.cmake");
       this->Configs.push_back(std::move(config));
     }
   }
@@ -634,24 +628,21 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
   if (this->Quiet) {
     // Tell the module that is about to be read that it should find
     // quietly.
-    std::string quietly = this->Name;
-    quietly += "_FIND_QUIETLY";
+    std::string quietly = cmStrCat(this->Name, "_FIND_QUIETLY");
     this->AddFindDefinition(quietly, "1");
   }
 
   if (this->Required) {
     // Tell the module that is about to be read that it should report
     // a fatal error if the package is not found.
-    std::string req = this->Name;
-    req += "_FIND_REQUIRED";
+    std::string req = cmStrCat(this->Name, "_FIND_REQUIRED");
     this->AddFindDefinition(req, "1");
   }
 
   if (!this->Version.empty()) {
     // Tell the module that is about to be read what version of the
     // package has been requested.
-    std::string ver = this->Name;
-    ver += "_FIND_VERSION";
+    std::string ver = cmStrCat(this->Name, "_FIND_VERSION");
     this->AddFindDefinition(ver, this->Version.c_str());
     char buf[64];
     sprintf(buf, "%u", this->VersionMajor);
@@ -666,8 +657,7 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
     this->AddFindDefinition(ver + "_COUNT", buf);
 
     // Tell the module whether an exact version has been requested.
-    std::string exact = this->Name;
-    exact += "_FIND_VERSION_EXACT";
+    std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
     this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
   }
 }
@@ -700,9 +690,7 @@ void cmFindPackageCommand::RestoreFindDefinitions()
 
 bool cmFindPackageCommand::FindModule(bool& found)
 {
-  std::string module = "Find";
-  module += this->Name;
-  module += ".cmake";
+  std::string module = cmStrCat("Find", this->Name, ".cmake");
   bool system = false;
   std::string mfile = this->Makefile->GetModulesFile(module, system);
   if (!mfile.empty()) {
@@ -731,8 +719,7 @@ bool cmFindPackageCommand::FindModule(bool& found)
     // Load the module we found, and set "<name>_FIND_MODULE" to true
     // while inside it.
     found = true;
-    std::string var = this->Name;
-    var += "_FIND_MODULE";
+    std::string var = cmStrCat(this->Name, "_FIND_MODULE");
     this->Makefile->AddDefinition(var, "1");
     bool result = this->ReadListFile(mfile, DoPolicyScope);
     this->Makefile->RemoveDefinition(var);
@@ -785,10 +772,8 @@ bool cmFindPackageCommand::HandlePackageMode(
     }
   }
 
-  std::string foundVar = this->Name;
-  foundVar += "_FOUND";
-  std::string notFoundMessageVar = this->Name;
-  notFoundMessageVar += "_NOT_FOUND_MESSAGE";
+  std::string foundVar = cmStrCat(this->Name, "_FOUND");
+  std::string notFoundMessageVar = cmStrCat(this->Name, "_NOT_FOUND_MESSAGE");
   std::string notFoundMessage;
 
   // If the directory for the config file was found, try to read the file.
@@ -878,9 +863,8 @@ bool cmFindPackageCommand::HandlePackageMode(
       } else {
         std::string requestedVersionString;
         if (!this->Version.empty()) {
-          requestedVersionString = " (requested version ";
-          requestedVersionString += this->Version;
-          requestedVersionString += ")";
+          requestedVersionString =
+            cmStrCat(" (requested version ", this->Version, ')');
         }
 
         if (this->UseConfigFiles) {
@@ -962,18 +946,17 @@ bool cmFindPackageCommand::HandlePackageMode(
   this->Makefile->AddDefinition(foundVar, found ? "1" : "0");
 
   // Set a variable naming the configuration file that was found.
-  std::string fileVar = this->Name;
-  fileVar += "_CONFIG";
+  std::string fileVar = cmStrCat(this->Name, "_CONFIG");
   if (found) {
     this->Makefile->AddDefinition(fileVar, this->FileFound);
   } else {
     this->Makefile->RemoveDefinition(fileVar);
   }
 
-  std::string consideredConfigsVar = this->Name;
-  consideredConfigsVar += "_CONSIDERED_CONFIGS";
-  std::string consideredVersionsVar = this->Name;
-  consideredVersionsVar += "_CONSIDERED_VERSIONS";
+  std::string consideredConfigsVar =
+    cmStrCat(this->Name, "_CONSIDERED_CONFIGS");
+  std::string consideredVersionsVar =
+    cmStrCat(this->Name, "_CONSIDERED_VERSIONS");
 
   std::string consideredConfigFiles;
   std::string consideredVersions;
@@ -1035,9 +1018,8 @@ bool cmFindPackageCommand::FindConfig()
     init = this->Variable + "-NOTFOUND";
   }
   std::string help =
-    "The directory containing a CMake configuration file for ";
-  help += this->Name;
-  help += ".";
+    cmStrCat("The directory containing a CMake configuration file for ",
+             this->Name, '.');
   // We force the value since we do not get here if it was already set.
   this->Makefile->AddCacheDefinition(this->Variable, init.c_str(),
                                      help.c_str(), cmStateEnums::PATH, true);
@@ -1084,9 +1066,7 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f,
   if (this->Makefile->ReadDependentFile(f, noPolicyScope)) {
     return true;
   }
-  std::string e = "Error reading CMake code from \"";
-  e += f;
-  e += "\".";
+  std::string e = cmStrCat("Error reading CMake code from \"", f, "\".");
   this->SetError(e);
   return false;
 }
@@ -1138,12 +1118,11 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
 void cmFindPackageCommand::AppendSuccessInformation()
 {
   {
-    std::string transitivePropName = "_CMAKE_";
-    transitivePropName += this->Name + "_TRANSITIVE_DEPENDENCY";
+    std::string transitivePropName =
+      cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY");
     this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False");
   }
-  std::string found = this->Name;
-  found += "_FOUND";
+  std::string found = cmStrCat(this->Name, "_FOUND");
   std::string upperFound = cmSystemTools::UpperCase(found);
 
   const char* upperResult = this->Makefile->GetDefinition(upperFound);
@@ -1154,28 +1133,23 @@ void cmFindPackageCommand::AppendSuccessInformation()
 
   // Record whether the find was quiet or not, so this can be used
   // e.g. in FeatureSummary.cmake
-  std::string quietInfoPropName = "_CMAKE_";
-  quietInfoPropName += this->Name;
-  quietInfoPropName += "_QUIET";
+  std::string quietInfoPropName = cmStrCat("_CMAKE_", this->Name, "_QUIET");
   this->Makefile->GetState()->SetGlobalProperty(
     quietInfoPropName, this->Quiet ? "TRUE" : "FALSE");
 
   // set a global property to record the required version of this package
-  std::string versionInfoPropName = "_CMAKE_";
-  versionInfoPropName += this->Name;
-  versionInfoPropName += "_REQUIRED_VERSION";
+  std::string versionInfoPropName =
+    cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION");
   std::string versionInfo;
   if (!this->Version.empty()) {
-    versionInfo = this->VersionExact ? "==" : ">=";
-    versionInfo += " ";
-    versionInfo += this->Version;
+    versionInfo =
+      cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version);
   }
   this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
                                                 versionInfo.c_str());
   if (this->Required) {
-    std::string requiredInfoPropName = "_CMAKE_";
-    requiredInfoPropName += this->Name;
-    requiredInfoPropName += "_TYPE";
+    std::string requiredInfoPropName =
+      cmStrCat("_CMAKE_", this->Name, "_TYPE");
     this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
                                                   "REQUIRED");
   }
@@ -1285,9 +1259,7 @@ void cmFindPackageCommand::FillPrefixesUserRegistry()
   char dir[B_PATH_NAME_LENGTH];
   if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) ==
       B_OK) {
-    std::string fname = dir;
-    fname += "/cmake/packages/";
-    fname += Name;
+    std::string fname = cmStrCat(dir, "/cmake/packages/", Name);
     this->LoadPackageRegistryDir(fname,
                                  this->LabeledPaths[PathLabel::UserRegistry]);
   }
@@ -1428,9 +1400,7 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
 
   std::string fname;
   for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) {
-    fname = dir;
-    fname += "/";
-    fname += files.GetFile(i);
+    fname = cmStrCat(dir, '/', files.GetFile(i));
 
     if (!cmSystemTools::FileIsDirectory(fname)) {
       // Hold this file hostage until it behaves.
@@ -1545,9 +1515,7 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
   }
 
   for (std::string const& c : this->Configs) {
-    file = dir;
-    file += "/";
-    file += c;
+    file = cmStrCat(dir, '/', c);
     if (this->DebugMode) {
       fprintf(stderr, "Checking file [%s]\n", file.c_str());
     }
@@ -1573,16 +1541,14 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
   std::string version_file_base = config_file.substr(0, pos);
 
   // Look for foo-config-version.cmake
-  std::string version_file = version_file_base;
-  version_file += "-version.cmake";
+  std::string version_file = cmStrCat(version_file_base, "-version.cmake");
   if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
     result = this->CheckVersionFile(version_file, version);
     haveResult = true;
   }
 
   // Look for fooConfigVersion.cmake
-  version_file = version_file_base;
-  version_file += "Version.cmake";
+  version_file = cmStrCat(version_file_base, "Version.cmake");
   if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
     result = this->CheckVersionFile(version_file, version);
     haveResult = true;
@@ -1690,8 +1656,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
 void cmFindPackageCommand::StoreVersionFound()
 {
   // Store the whole version string.
-  std::string ver = this->Name;
-  ver += "_VERSION";
+  std::string ver = cmStrCat(this->Name, "_VERSION");
   if (this->VersionFound.empty()) {
     this->Makefile->RemoveDefinition(ver);
   } else {
@@ -2039,8 +2004,7 @@ private:
   bool Search(std::string const& parent, cmFileList& lister) override
   {
     // Glob the set of matching files.
-    std::string expr = parent;
-    expr += this->Pattern;
+    std::string expr = cmStrCat(parent, this->Pattern);
     cmsys::Glob g;
     if (!g.FindFiles(expr)) {
       return false;

+ 5 - 11
Source/cmFindPathCommand.cxx

@@ -6,6 +6,7 @@
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -88,12 +89,8 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
       frameWorkName.clear();
     }
     if (!frameWorkName.empty()) {
-      std::string fpath = dir;
-      fpath += frameWorkName;
-      fpath += ".framework";
-      std::string intPath = fpath;
-      intPath += "/Headers/";
-      intPath += fileName;
+      std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
+      std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
       if (cmSystemTools::FileExists(intPath)) {
         if (this->IncludeFileInPath) {
           return intPath;
@@ -104,9 +101,7 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
   }
   // if it is not found yet or not a framework header, then do a glob search
   // for all frameworks in the directory: dir/*.framework/Headers/<file>
-  std::string glob = dir;
-  glob += "*.framework/Headers/";
-  glob += file;
+  std::string glob = cmStrCat(dir, "*.framework/Headers/", file);
   cmsys::Glob globIt;
   globIt.FindFiles(glob);
   std::vector<std::string> files = globIt.GetFiles();
@@ -126,8 +121,7 @@ std::string cmFindPathCommand::FindNormalHeader()
   std::string tryPath;
   for (std::string const& n : this->Names) {
     for (std::string const& sp : this->SearchPaths) {
-      tryPath = sp;
-      tryPath += n;
+      tryPath = cmStrCat(sp, n);
       if (cmSystemTools::FileExists(tryPath)) {
         if (this->IncludeFileInPath) {
           return tryPath;

+ 1 - 2
Source/cmFindProgramCommand.cxx

@@ -75,8 +75,7 @@ struct cmFindProgramHelper
       if (!ext.empty() && cmHasSuffix(name, ext)) {
         continue;
       }
-      this->TestNameExt = name;
-      this->TestNameExt += ext;
+      this->TestNameExt = cmStrCat(name, ext);
       this->TestPath =
         cmSystemTools::CollapseFullPath(this->TestNameExt, path);
 

+ 4 - 6
Source/cmFortranParserImpl.cxx

@@ -1,6 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFortranParser.h"
+
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <assert.h>
@@ -22,9 +24,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
   }
   // Check for the file in the directory containing the including
   // file.
-  std::string fullName = dir;
-  fullName += "/";
-  fullName += includeName;
+  std::string fullName = cmStrCat(dir, '/', includeName);
   if (cmSystemTools::FileExists(fullName, true)) {
     fileName = fullName;
     return true;
@@ -32,9 +32,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
 
   // Search the include path for the file.
   for (std::string const& i : this->IncludePath) {
-    fullName = i;
-    fullName += "/";
-    fullName += includeName;
+    fullName = cmStrCat(i, '/', includeName);
     if (cmSystemTools::FileExists(fullName, true)) {
       fileName = fullName;
       return true;

+ 3 - 3
Source/cmFunctionCommand.cxx

@@ -51,9 +51,9 @@ bool cmFunctionHelperCommand::operator()(
   // make sure the number of arguments passed is at least the number
   // required by the signature
   if (expandedArgs.size() < this->Args.size() - 1) {
-    std::string errorMsg =
-      "Function invoked with incorrect arguments for function named: ";
-    errorMsg += this->Args[0];
+    std::string errorMsg = cmStrCat(
+      "Function invoked with incorrect arguments for function named: ",
+      this->Args[0]);
     inStatus.SetError(errorMsg);
     return false;
   }

+ 6 - 8
Source/cmGeneratorExpressionNode.cxx

@@ -909,8 +909,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
         // for this (possibly mapped) config.
         // Check if there is a proper config mapping for the tested config.
         std::vector<std::string> mappedConfigs;
-        std::string mapProp = "MAP_IMPORTED_CONFIG_";
-        mapProp += cmSystemTools::UpperCase(context->Config);
+        std::string mapProp = cmStrCat(
+          "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config));
         if (const char* mapValue =
               context->CurrentTarget->GetProperty(mapProp)) {
           cmExpandList(cmSystemTools::UpperCase(mapValue), mappedConfigs);
@@ -1695,9 +1695,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
                     "SHARED libraries.");
       return std::string();
     }
-    std::string result = target->GetDirectory(context->Config);
-    result += "/";
-    result += target->GetSOName(context->Config);
+    std::string result = cmStrCat(target->GetDirectory(context->Config), '/',
+                                  target->GetSOName(context->Config));
     return result;
   }
 };
@@ -1736,9 +1735,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
       return std::string();
     }
 
-    std::string result = target->GetPDBDirectory(context->Config);
-    result += "/";
-    result += target->GetPDBName(context->Config);
+    std::string result = cmStrCat(target->GetPDBDirectory(context->Config),
+                                  '/', target->GetPDBName(context->Config));
     return result;
   }
 };

+ 73 - 107
Source/cmGeneratorTarget.cxx

@@ -39,6 +39,7 @@
 #include "cmTarget.h"
 #include "cmTargetLinkLibraryType.h"
 #include "cmTargetPropertyComputer.h"
+#include "cm_string_view.hxx"
 #include "cmake.h"
 
 class cmMessenger;
@@ -552,8 +553,8 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
 {
   const char* postfix = nullptr;
   if (!config.empty()) {
-    std::string configProp = cmSystemTools::UpperCase(config);
-    configProp += "_POSTFIX";
+    std::string configProp =
+      cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
     postfix = this->GetProperty(configProp);
     // Mac application bundles and frameworks have no postfix.
     if (!this->IsImported() && postfix &&
@@ -793,9 +794,8 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
                                           const std::string& config) const
 {
   if (!config.empty()) {
-    std::string featureConfig = feature;
-    featureConfig += "_";
-    featureConfig += cmSystemTools::UpperCase(config);
+    std::string featureConfig =
+      cmStrCat(feature, '_', cmSystemTools::UpperCase(config));
     if (const char* value = this->GetProperty(featureConfig)) {
       return value;
     }
@@ -1703,8 +1703,7 @@ std::string cmGeneratorTarget::GetCompilePDBName(
 
   // Check for a per-configuration output directory target property.
   std::string configUpper = cmSystemTools::UpperCase(config);
-  std::string configProp = "COMPILE_PDB_NAME_";
-  configProp += configUpper;
+  std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
   const char* config_name = this->GetProperty(configProp);
   if (config_name && *config_name) {
     return prefix + config_name + ".pdb";
@@ -1776,9 +1775,8 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
   // Check for rpath support on this platform.
   std::string ll = this->GetLinkerLanguage(config);
   if (!ll.empty()) {
-    std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
-    flagVar += ll;
-    flagVar += "_FLAG";
+    std::string flagVar =
+      cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG");
     if (!this->Makefile->IsSet(flagVar)) {
       // There is no rpath support on this platform so nothing needs
       // relinking.
@@ -1856,9 +1854,8 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
   // binaries.
   std::string ll = this->GetLinkerLanguage(config);
   if (!ll.empty()) {
-    std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
-    sepVar += ll;
-    sepVar += "_FLAG_SEP";
+    std::string sepVar =
+      cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
     const char* sep = this->Makefile->GetDefinition(sepVar);
     if (sep && *sep) {
       // TODO: Add ELF check to ABI detection and get rid of
@@ -2055,9 +2052,8 @@ bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level)
 std::string cmGeneratorTarget::GetAppBundleDirectory(
   const std::string& config, BundleDirectoryLevel level) const
 {
-  std::string fpath =
-    this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
-  fpath += ".";
+  std::string fpath = cmStrCat(
+    this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     ext = "app";
@@ -2082,9 +2078,8 @@ bool cmGeneratorTarget::IsBundleOnApple() const
 std::string cmGeneratorTarget::GetCFBundleDirectory(
   const std::string& config, BundleDirectoryLevel level) const
 {
-  std::string fpath;
-  fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
-  fpath += ".";
+  std::string fpath = cmStrCat(
+    this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     if (this->IsXCTestOnApple()) {
@@ -2107,9 +2102,8 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(
 std::string cmGeneratorTarget::GetFrameworkDirectory(
   const std::string& config, BundleDirectoryLevel level) const
 {
-  std::string fpath;
-  fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
-  fpath += ".";
+  std::string fpath = cmStrCat(
+    this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     ext = "framework";
@@ -2166,8 +2160,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
 
     if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
       if (install_name_dir && *install_name_dir) {
-        dir = install_name_dir;
-        dir += "/";
+        dir = cmStrCat(install_name_dir, '/');
       }
     }
     if (!install_name_dir) {
@@ -2208,8 +2201,7 @@ const std::string* cmGeneratorTarget::GetExportMacro() const
     if (const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
       this->ExportMacro = custom_export_name;
     } else {
-      std::string in = this->GetName();
-      in += "_EXPORTS";
+      std::string in = cmStrCat(this->GetName(), "_EXPORTS");
       this->ExportMacro = cmSystemTools::MakeCidentifier(in);
     }
     return &this->ExportMacro;
@@ -2430,8 +2422,7 @@ std::string cmGeneratorTarget::GetMacContentDirectory(
   const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   // Start with the output directory for the target.
-  std::string fpath = this->GetDirectory(config, artifact);
-  fpath += "/";
+  std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
   BundleDirectoryLevel level = ContentLevel;
   if (this->IsFrameworkOnApple()) {
     // additional files with a framework go into the version specific
@@ -2467,10 +2458,9 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
   }
 
   if (this->GetType() > cmStateEnums::OBJECT_LIBRARY) {
-    std::string msg = "cmTarget::GetCompileInfo called for ";
-    msg += this->GetName();
-    msg += " which has type ";
-    msg += cmState::GetTargetTypeName(this->GetType());
+    std::string msg = cmStrCat("cmTarget::GetCompileInfo called for ",
+                               this->GetName(), " which has type ",
+                               cmState::GetTargetTypeName(this->GetType()));
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
     return nullptr;
   }
@@ -2898,8 +2888,8 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
 {
   const char* archs = nullptr;
   if (!config.empty()) {
-    std::string defVarName = "OSX_ARCHITECTURES_";
-    defVarName += cmSystemTools::UpperCase(config);
+    std::string defVarName =
+      cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config));
     archs = this->GetProperty(defVarName);
   }
   if (!archs) {
@@ -3694,33 +3684,25 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
   // Add each name.
   std::string f;
   if (!targetNames.Output.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.Output;
+    f = cmStrCat(dir, '/', targetNames.Output);
     gg->AddToManifest(f);
   }
   if (!targetNames.SharedObject.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.SharedObject;
+    f = cmStrCat(dir, '/', targetNames.SharedObject);
     gg->AddToManifest(f);
   }
   if (!targetNames.Real.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.Real;
+    f = cmStrCat(dir, '/', targetNames.Real);
     gg->AddToManifest(f);
   }
   if (!targetNames.PDB.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.PDB;
+    f = cmStrCat(dir, '/', targetNames.PDB);
     gg->AddToManifest(f);
   }
   if (!targetNames.ImportLibrary.empty()) {
-    f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
-    f += "/";
-    f += targetNames.ImportLibrary;
+    f =
+      cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact),
+               '/', targetNames.ImportLibrary);
     gg->AddToManifest(f);
   }
 }
@@ -3760,11 +3742,10 @@ std::string cmGeneratorTarget::NormalGetFullPath(
   const std::string& config, cmStateEnums::ArtifactType artifact,
   bool realname) const
 {
-  std::string fpath = this->GetDirectory(config, artifact);
-  fpath += "/";
+  std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
   if (this->IsAppBundleOnApple()) {
-    fpath = this->BuildBundleDirectory(fpath, config, FullLevel);
-    fpath += "/";
+    fpath =
+      cmStrCat(this->BuildBundleDirectory(fpath, config, FullLevel), '/');
   }
 
   // Add the full name of the target.
@@ -3791,8 +3772,8 @@ std::string cmGeneratorTarget::NormalGetRealName(
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
   if (this->IsImported()) {
-    std::string msg = "NormalGetRealName called on imported target: ";
-    msg += this->GetName();
+    std::string msg = cmStrCat("NormalGetRealName called on imported target: ",
+                               this->GetName());
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
   }
 
@@ -3813,8 +3794,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
   if (this->IsImported()) {
-    std::string msg = "GetLibraryNames called on imported target: ";
-    msg += this->GetName();
+    std::string msg =
+      cmStrCat("GetLibraryNames called on imported target: ", this->GetName());
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
   }
 
@@ -3890,8 +3871,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
   if (this->IsImported()) {
-    std::string msg = "GetExecutableNames called on imported target: ";
-    msg += this->GetName();
+    std::string msg = cmStrCat(
+      "GetExecutableNames called on imported target: ", this->GetName());
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
   }
 
@@ -4012,15 +3993,14 @@ void cmGeneratorTarget::GetFullNameInternal(
   // frameworks have directory prefix but no suffix
   std::string fw_prefix;
   if (this->IsFrameworkOnApple()) {
-    fw_prefix = this->GetFrameworkDirectory(config, ContentLevel);
-    fw_prefix += "/";
+    fw_prefix =
+      cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
     targetPrefix = fw_prefix.c_str();
     targetSuffix = nullptr;
   }
 
   if (this->IsCFBundleOnApple()) {
-    fw_prefix = this->GetCFBundleDirectory(config, FullLevel);
-    fw_prefix += "/";
+    fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
     targetPrefix = fw_prefix.c_str();
     targetSuffix = nullptr;
   }
@@ -4376,8 +4356,8 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,
 
   std::vector<std::string> props;
   cmExpandList(prop, props);
-  std::string pdir = cmSystemTools::GetCMakeRoot();
-  pdir += "/Help/prop_tgt/";
+  std::string pdir =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/");
 
   for (std::string const& p : props) {
     std::string pname = cmSystemTools::HelpFileName(p);
@@ -4523,8 +4503,8 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
     }
     std::sort(props.begin(), props.end());
 
-    std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", ");
-    propsString += " and the " + props.back();
+    std::string propsString = cmStrCat(
+      cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back());
 
     std::ostringstream e;
     e << "Property \"" << prop << "\" appears in both the " << propsString
@@ -4794,8 +4774,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
   }
   bool propInitialized = explicitlySet;
 
-  std::string report = " * Target \"";
-  report += tgt->GetName();
+  std::string report = cmStrCat(" * Target \"", tgt->GetName());
   if (explicitlySet) {
     report += "\" has property content \"";
     report += valueAsString<PropertyType>(propContent);
@@ -5051,9 +5030,8 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory(
       mod_dir = target_mod_dir;
     } else {
       // Interpret relative to the current output directory.
-      mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
-      mod_dir += "/";
-      mod_dir += target_mod_dir;
+      mod_dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+                         '/', target_mod_dir);
     }
 
     // Make sure the module output directory exists.
@@ -5116,12 +5094,9 @@ void cmGeneratorTarget::ReportPropertyOrigin(
     return;
   }
 
-  std::string areport = compatibilityType;
-  areport += std::string(" of property \"") + p + "\" for target \"";
-  areport += std::string(this->GetName());
-  areport += "\" (result: \"";
-  areport += result;
-  areport += "\"):\n" + report;
+  std::string areport =
+    cmStrCat(compatibilityType, " of property \"", p, "\" for target \"",
+             this->GetName(), "\" (result: \"", result, "\"):\n", report);
 
   this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG,
                                                          areport);
@@ -5261,8 +5236,7 @@ void cmGeneratorTarget::ComputeLinkInterface(
 
     // How many repetitions are needed if this library has cyclic
     // dependencies?
-    std::string propName = "LINK_INTERFACE_MULTIPLICITY";
-    propName += suffix;
+    std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix);
     if (const char* config_reps = this->GetProperty(propName)) {
       sscanf(config_reps, "%u", &iface.Multiplicity);
     } else if (const char* reps =
@@ -5348,10 +5322,9 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
 
   // Only libraries and executables have well-defined output files.
   if (!this->HaveWellDefinedOutputFiles()) {
-    std::string msg = "cmGeneratorTarget::GetOutputInfo called for ";
-    msg += this->GetName();
-    msg += " which has type ";
-    msg += cmState::GetTargetTypeName(this->GetType());
+    std::string msg = cmStrCat("cmGeneratorTarget::GetOutputInfo called for ",
+                               this->GetName(), " which has type ",
+                               cmState::GetTargetTypeName(this->GetType()));
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
     return nullptr;
   }
@@ -5600,8 +5573,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
     // shared lib or executable.
 
     // Lookup the per-configuration property.
-    linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
-    linkIfaceProp += suffix;
+    linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix);
     explicitLibraries = this->GetProperty(linkIfaceProp);
 
     // If not set, try the generic property.
@@ -5807,8 +5779,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
     if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
       if (!propertyLibs) {
-        linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
-        linkProp += suffix;
+        linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix);
         propertyLibs = this->GetProperty(linkProp);
       }
 
@@ -5836,8 +5807,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
   if (loc) {
     info.Location = loc;
   } else {
-    std::string impProp = "IMPORTED_LOCATION";
-    impProp += suffix;
+    std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
     if (const char* config_location = this->GetProperty(impProp)) {
       info.Location = config_location;
     } else if (const char* location = this->GetProperty("IMPORTED_LOCATION")) {
@@ -5847,8 +5817,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the soname.
   if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
-    std::string soProp = "IMPORTED_SONAME";
-    soProp += suffix;
+    std::string soProp = cmStrCat("IMPORTED_SONAME", suffix);
     if (const char* config_soname = this->GetProperty(soProp)) {
       info.SOName = config_soname;
     } else if (const char* soname = this->GetProperty("IMPORTED_SONAME")) {
@@ -5858,8 +5827,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the "no-soname" mark.
   if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
-    std::string soProp = "IMPORTED_NO_SONAME";
-    soProp += suffix;
+    std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix);
     if (const char* config_no_soname = this->GetProperty(soProp)) {
       info.NoSOName = cmIsOn(config_no_soname);
     } else if (const char* no_soname =
@@ -5873,8 +5841,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
     info.ImportLibrary = imp;
   } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
              this->IsExecutableWithExports()) {
-    std::string impProp = "IMPORTED_IMPLIB";
-    impProp += suffix;
+    std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
     if (const char* config_implib = this->GetProperty(impProp)) {
       info.ImportLibrary = config_implib;
     } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) {
@@ -5884,8 +5851,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the link dependencies.
   {
-    std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
-    linkProp += suffix;
+    std::string linkProp =
+      cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix);
     if (const char* config_libs = this->GetProperty(linkProp)) {
       info.SharedDeps = config_libs;
     } else if (const char* libs =
@@ -5896,8 +5863,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the link languages.
   if (this->LinkLanguagePropagatesToDependents()) {
-    std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
-    linkProp += suffix;
+    std::string linkProp =
+      cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix);
     if (const char* config_libs = this->GetProperty(linkProp)) {
       info.Languages = config_libs;
     } else if (const char* libs =
@@ -5918,8 +5885,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the cyclic repetition count.
   if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
-    std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
-    linkProp += suffix;
+    std::string linkProp =
+      cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
     if (const char* config_reps = this->GetProperty(linkProp)) {
       sscanf(config_reps, "%u", &info.Multiplicity);
     } else if (const char* reps =
@@ -6397,8 +6364,8 @@ bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config,
 {
   if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 &&
       gnuName.substr(gnuName.size() - 6) == ".dll.a") {
-    out = gnuName.substr(0, gnuName.size() - 6);
-    out += newExt ? newExt : ".lib";
+    out = cmStrCat(cm::string_view(gnuName).substr(0, gnuName.size() - 6),
+                   newExt ? newExt : ".lib");
     return true;
   }
   return false;
@@ -6433,9 +6400,8 @@ bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const
 
 std::string cmGeneratorTarget::GetSupportDirectory() const
 {
-  std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/CMakeFiles/";
-  dir += this->GetName();
+  std::string dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+                             "/CMakeFiles/", this->GetName());
 #if defined(__VMS)
   dir += "_dir";
 #else

+ 2 - 3
Source/cmGetDirectoryPropertyCommand.cxx

@@ -7,6 +7,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 namespace {
@@ -39,9 +40,7 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
     std::string sd = *i;
     // make sure the start dir is a full path
     if (!cmSystemTools::FileIsFullPath(sd)) {
-      sd = status.GetMakefile().GetCurrentSourceDirectory();
-      sd += "/";
-      sd += *i;
+      sd = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
     }
 
     // The local generators are associated with collapsed paths.

+ 3 - 3
Source/cmGetPropertyCommand.cxx

@@ -15,6 +15,7 @@
 #include "cmPropertyDefinition.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetPropertyComputer.h"
@@ -261,9 +262,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
     // respect to the current directory.
     std::string dir = name;
     if (!cmSystemTools::FileIsFullPath(dir)) {
-      dir = status.GetMakefile().GetCurrentSourceDirectory();
-      dir += "/";
-      dir += name;
+      dir =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', name);
     }
 
     // The local generators are associated with collapsed paths.

+ 24 - 32
Source/cmGhsMultiTargetGenerator.cxx

@@ -75,8 +75,8 @@ void cmGhsMultiTargetGenerator::Generate()
       break;
     }
     case cmStateEnums::SHARED_LIBRARY: {
-      std::string msg = "add_library(<name> SHARED ...) not supported: ";
-      msg += this->Name;
+      std::string msg =
+        cmStrCat("add_library(<name> SHARED ...) not supported: ", this->Name);
       cmSystemTools::Message(msg);
       return;
     }
@@ -87,8 +87,8 @@ void cmGhsMultiTargetGenerator::Generate()
       break;
     }
     case cmStateEnums::MODULE_LIBRARY: {
-      std::string msg = "add_library(<name> MODULE ...) not supported: ";
-      msg += this->Name;
+      std::string msg =
+        cmStrCat("add_library(<name> MODULE ...) not supported: ", this->Name);
       cmSystemTools::Message(msg);
       return;
     }
@@ -123,10 +123,9 @@ void cmGhsMultiTargetGenerator::Generate()
 void cmGhsMultiTargetGenerator::GenerateTarget()
 {
   // Open the target file in copy-if-different mode.
-  std::string fproj = this->LocalGenerator->GetCurrentBinaryDirectory();
-  fproj += "/";
-  fproj += this->Name;
-  fproj += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
+  std::string fproj =
+    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION);
   cmGeneratedFileStream fout(fproj);
   fout.SetCopyIfDifferent(true);
 
@@ -347,12 +346,11 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper(
   for (cmCustomCommand const& cc : ccv) {
     cmCustomCommandGenerator ccg(cc, this->ConfigName, this->LocalGenerator);
     // Open the filestream for this custom command
-    std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory();
-    fname +=
-      "/" + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-    fname += "/" + this->Name + "_" + name;
-    fname += std::to_string(cmdcount++);
-    fname += this->CmdWindowsShell ? ".bat" : ".sh";
+    std::string fname =
+      cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+               this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+               '/', this->Name, '_', name, cmdcount++,
+               this->CmdWindowsShell ? ".bat" : ".sh");
     cmGeneratedFileStream f(fname);
     f.SetCopyIfDifferent(true);
     this->WriteCustomCommandsHelper(f, ccg);
@@ -395,8 +393,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
   // Echo the custom command's comment text.
   const char* comment = ccg.GetComment();
   if (comment && *comment) {
-    std::string echocmd = "echo ";
-    echocmd += comment;
+    std::string echocmd = cmStrCat("echo ", comment);
     cmdLines.push_back(std::move(echocmd));
   }
 
@@ -569,14 +566,11 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
       // Open the filestream in copy-if-different mode.
       std::string gname = sg;
       cmsys::SystemTools::ReplaceString(gname, "\\", "_");
-      std::string lpath =
-        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-      lpath += "/";
-      lpath += gname;
-      lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
-      std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory();
-      fpath += "/";
-      fpath += lpath;
+      std::string lpath = cmStrCat(
+        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
+        gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION);
+      std::string fpath = cmStrCat(
+        this->LocalGenerator->GetCurrentBinaryDirectory(), '/', lpath);
       cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath);
       f->SetCopyIfDifferent(true);
       gfiles.push_back(f);
@@ -668,14 +662,12 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
                                        this->LocalGenerator);
 
           // Open the filestream for this custom command
-          std::string fname =
-            this->LocalGenerator->GetCurrentBinaryDirectory();
-          fname += "/" +
-            this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-          fname += "/" + this->Name + "_cc";
-          fname += std::to_string(cmdcount++) + "_";
-          fname += (sf->GetLocation()).GetName();
-          fname += this->CmdWindowsShell ? ".bat" : ".sh";
+          std::string fname = cmStrCat(
+            this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+            this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+            '/', this->Name, "_cc", cmdcount++, '_',
+            (sf->GetLocation()).GetName(),
+            this->CmdWindowsShell ? ".bat" : ".sh");
           cmGeneratedFileStream f(fname);
           f.SetCopyIfDifferent(true);
           this->WriteCustomCommandsHelper(f, ccg);

+ 2 - 2
Source/cmGlobVerificationManager.cxx

@@ -7,6 +7,7 @@
 
 #include "cmGeneratedFileStream.h"
 #include "cmListFileCache.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
@@ -16,8 +17,7 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
     return true;
   }
 
-  std::string scriptFile = path;
-  scriptFile += "/CMakeFiles";
+  std::string scriptFile = cmStrCat(path, "/CMakeFiles");
   std::string stampFile = scriptFile;
   cmSystemTools::MakeDirectory(scriptFile);
   scriptFile += "/VerifyGlobs.cmake";

+ 62 - 101
Source/cmGlobalGenerator.cxx

@@ -205,9 +205,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
                                                 cmMakefile* mf,
                                                 bool optional) const
 {
-  std::string langComp = "CMAKE_";
-  langComp += lang;
-  langComp += "_COMPILER";
+  std::string langComp = cmStrCat("CMAKE_", lang, "_COMPILER");
 
   if (!mf->GetDefinition(langComp)) {
     if (!optional) {
@@ -408,9 +406,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
     std::string saveFile = file;
     cmSystemTools::GetShortPath(makeProgram, makeProgram);
     cmSystemTools::SplitProgramPath(makeProgram, dir, file);
-    makeProgram = dir;
-    makeProgram += "/";
-    makeProgram += saveFile;
+    makeProgram = cmStrCat(dir, '/', saveFile);
     mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
                            "make program", cmStateEnums::FILEPATH);
   }
@@ -512,8 +508,8 @@ void cmGlobalGenerator::EnableLanguage(
   bool fatalError = false;
 
   mf->AddDefinitionBool("RUN_CONFIGURE", true);
-  std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory();
-  rootBin += "/CMakeFiles";
+  std::string rootBin =
+    cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
 
   // If the configuration files path has been set,
   // then we are in a try compile and need to copy the enable language
@@ -592,8 +588,7 @@ void cmGlobalGenerator::EnableLanguage(
     mf->ReadListFile(systemFile);
     // load the CMakeSystem.cmake from the binary directory
     // this file is configured by the CMakeDetermineSystem.cmake file
-    fpath = rootBin;
-    fpath += "/CMakeSystem.cmake";
+    fpath = cmStrCat(rootBin, "/CMakeSystem.cmake");
     mf->ReadListFile(fpath);
   }
 
@@ -659,14 +654,9 @@ void cmGlobalGenerator::EnableLanguage(
       this->SetLanguageEnabled("NONE", mf);
       continue;
     }
-    std::string loadedLang = "CMAKE_";
-    loadedLang += lang;
-    loadedLang += "_COMPILER_LOADED";
+    std::string loadedLang = cmStrCat("CMAKE_", lang, "_COMPILER_LOADED");
     if (!mf->GetDefinition(loadedLang)) {
-      fpath = rootBin;
-      fpath += "/CMake";
-      fpath += lang;
-      fpath += "Compiler.cmake";
+      fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
 
       // If the existing build tree was already configured with this
       // version of CMake then try to load the configured file first
@@ -693,9 +683,8 @@ void cmGlobalGenerator::EnableLanguage(
       }
       // if the CMake(LANG)Compiler.cmake file was not found then
       // load CMakeDetermine(LANG)Compiler.cmake
-      std::string determineCompiler = "CMakeDetermine";
-      determineCompiler += lang;
-      determineCompiler += "Compiler.cmake";
+      std::string determineCompiler =
+        cmStrCat("CMakeDetermine", lang, "Compiler.cmake");
       std::string determineFile = mf->GetModulesFile(determineCompiler);
       if (!mf->ReadListFile(determineFile)) {
         cmSystemTools::Error("Could not find cmake module file: " +
@@ -711,27 +700,19 @@ void cmGlobalGenerator::EnableLanguage(
         // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
         // into the environment, in case user scripts want to run
         // configure, or sub cmakes
-        std::string compilerName = "CMAKE_";
-        compilerName += lang;
-        compilerName += "_COMPILER";
-        std::string compilerEnv = "CMAKE_";
-        compilerEnv += lang;
-        compilerEnv += "_COMPILER_ENV_VAR";
+        std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
+        std::string compilerEnv =
+          cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
         const std::string& envVar = mf->GetRequiredDefinition(compilerEnv);
         const std::string& envVarValue =
           mf->GetRequiredDefinition(compilerName);
-        std::string env = envVar;
-        env += "=";
-        env += envVarValue;
+        std::string env = cmStrCat(envVar, '=', envVarValue);
         cmSystemTools::PutEnv(env);
       }
 
       // if determineLanguage was called then load the file it
       // configures CMake(LANG)Compiler.cmake
-      fpath = rootBin;
-      fpath += "/CMake";
-      fpath += lang;
-      fpath += "Compiler.cmake";
+      fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
       if (!mf->ReadListFile(fpath)) {
         cmSystemTools::Error("Could not find cmake module file: " + fpath);
       }
@@ -762,12 +743,8 @@ void cmGlobalGenerator::EnableLanguage(
     }
 
     // Check that the compiler was found.
-    std::string compilerName = "CMAKE_";
-    compilerName += lang;
-    compilerName += "_COMPILER";
-    std::string compilerEnv = "CMAKE_";
-    compilerEnv += lang;
-    compilerEnv += "_COMPILER_ENV_VAR";
+    std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
+    std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
     std::ostringstream noCompiler;
     const char* compilerFile = mf->GetDefinition(compilerName);
     if (!compilerFile || !*compilerFile || cmIsNOTFOUND(compilerFile)) {
@@ -801,10 +778,8 @@ void cmGlobalGenerator::EnableLanguage(
       if (!optional) {
         // The compiler was not found and it is not optional.  Remove
         // CMake(LANG)Compiler.cmake so we try again next time CMake runs.
-        std::string compilerLangFile = rootBin;
-        compilerLangFile += "/CMake";
-        compilerLangFile += lang;
-        compilerLangFile += "Compiler.cmake";
+        std::string compilerLangFile =
+          cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
         cmSystemTools::RemoveFile(compilerLangFile);
         if (!this->CMakeInstance->GetIsInTryCompile()) {
           this->PrintCompilerAdvice(noCompiler, lang,
@@ -815,13 +790,10 @@ void cmGlobalGenerator::EnableLanguage(
       }
     }
 
-    std::string langLoadedVar = "CMAKE_";
-    langLoadedVar += lang;
-    langLoadedVar += "_INFORMATION_LOADED";
+    std::string langLoadedVar =
+      cmStrCat("CMAKE_", lang, "_INFORMATION_LOADED");
     if (!mf->GetDefinition(langLoadedVar)) {
-      fpath = "CMake";
-      fpath += lang;
-      fpath += "Information.cmake";
+      fpath = cmStrCat("CMake", lang, "Information.cmake");
       std::string informationFile = mf->GetModulesFile(fpath);
       if (informationFile.empty()) {
         cmSystemTools::Error("Could not find cmake module file: " + fpath);
@@ -842,33 +814,27 @@ void cmGlobalGenerator::EnableLanguage(
     // If the language is untested then test it now with a try compile.
     if (needTestLanguage[lang]) {
       if (!this->CMakeInstance->GetIsInTryCompile()) {
-        std::string testLang = "CMakeTest";
-        testLang += lang;
-        testLang += "Compiler.cmake";
+        std::string testLang = cmStrCat("CMakeTest", lang, "Compiler.cmake");
         std::string ifpath = mf->GetModulesFile(testLang);
         if (!mf->ReadListFile(ifpath)) {
           cmSystemTools::Error("Could not find cmake module file: " +
                                testLang);
         }
-        std::string compilerWorks = "CMAKE_";
-        compilerWorks += lang;
-        compilerWorks += "_COMPILER_WORKS";
+        std::string compilerWorks =
+          cmStrCat("CMAKE_", lang, "_COMPILER_WORKS");
         // if the compiler did not work, then remove the
         // CMake(LANG)Compiler.cmake file so that it will get tested the
         // next time cmake is run
         if (!mf->IsOn(compilerWorks)) {
-          std::string compilerLangFile = rootBin;
-          compilerLangFile += "/CMake";
-          compilerLangFile += lang;
-          compilerLangFile += "Compiler.cmake";
+          std::string compilerLangFile =
+            cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
           cmSystemTools::RemoveFile(compilerLangFile);
         }
       } // end if in try compile
     }   // end need test language
     // Store the shared library flags so that we can satisfy CMP0018
-    std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_";
-    sharedLibFlagsVar += lang;
-    sharedLibFlagsVar += "_FLAGS";
+    std::string sharedLibFlagsVar =
+      cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS");
     this->LanguageToOriginalSharedLibFlags[lang] =
       mf->GetSafeDefinition(sharedLibFlagsVar);
 
@@ -879,10 +845,9 @@ void cmGlobalGenerator::EnableLanguage(
   // Now load files that can override any settings on the platform or for
   // the project First load the project compatibility file if it is in
   // cmake
-  std::string projectCompatibility = cmSystemTools::GetCMakeRoot();
-  projectCompatibility += "/Modules/";
-  projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
-  projectCompatibility += "Compatibility.cmake";
+  std::string projectCompatibility =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/",
+             mf->GetSafeDefinition("PROJECT_NAME"), "Compatibility.cmake");
   if (cmSystemTools::FileExists(projectCompatibility)) {
     mf->ReadListFile(projectCompatibility);
   }
@@ -1118,8 +1083,8 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
   }
 
   if (preference < 0) {
-    std::string msg = linkerPrefVar;
-    msg += " is negative, adjusting it to 0";
+    std::string msg =
+      cmStrCat(linkerPrefVar, " is negative, adjusting it to 0");
     cmSystemTools::Message(msg, "Warning");
     preference = 0;
   }
@@ -1274,9 +1239,8 @@ void cmGlobalGenerator::Configure()
       msg << "Configuring incomplete, errors occurred!";
       const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr };
       for (const char** log = logs; *log; ++log) {
-        std::string f = this->CMakeInstance->GetHomeOutputDirectory();
-        f += "/CMakeFiles/";
-        f += *log;
+        std::string f = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+                                 "/CMakeFiles/", *log);
         if (cmSystemTools::FileExists(f)) {
           msg << "\nSee also \"" << f << "\".";
         }
@@ -1602,8 +1566,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
         mf->GetConfigurations(configs);
 
         for (std::string const& c : configs) {
-          std::string defPropName = "COMPILE_DEFINITIONS_";
-          defPropName += cmSystemTools::UpperCase(c);
+          std::string defPropName =
+            cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c));
           t->AppendProperty(defPropName, mf->GetProperty(defPropName));
         }
       }
@@ -1710,11 +1674,10 @@ void cmGlobalGenerator::CheckTargetProperties()
           if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
             varName += " (ADVANCED)";
           }
-          std::string text = notFoundMap[varName];
-          text += "\n    linked by target \"";
-          text += target.second.GetName();
-          text += "\" in directory ";
-          text += this->Makefiles[i]->GetCurrentSourceDirectory();
+          std::string text =
+            cmStrCat(notFoundMap[varName], "\n    linked by target \"",
+                     target.second.GetName(), "\" in directory ",
+                     this->Makefiles[i]->GetCurrentSourceDirectory());
           notFoundMap[varName] = text;
         }
       }
@@ -1736,9 +1699,10 @@ void cmGlobalGenerator::CheckTargetProperties()
           if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
             varName += " (ADVANCED)";
           }
-          std::string text = notFoundMap[varName];
-          text += "\n   used as include directory in directory ";
-          text += this->Makefiles[i]->GetCurrentSourceDirectory();
+          std::string text =
+            cmStrCat(notFoundMap[varName],
+                     "\n   used as include directory in directory ",
+                     this->Makefiles[i]->GetCurrentSourceDirectory());
           notFoundMap[varName] = text;
         }
       }
@@ -1837,8 +1801,8 @@ int cmGlobalGenerator::Build(
   output += "\n";
   if (workdir.Failed()) {
     cmSystemTools::SetRunCommandHideConsole(hideconsole);
-    std::string err = "Failed to change directory: ";
-    err += std::strerror(workdir.GetLastResult());
+    std::string err = cmStrCat("Failed to change directory: ",
+                               std::strerror(workdir.GetLastResult()));
     cmSystemTools::Error(err);
     output += err;
     output += "\n";
@@ -1943,8 +1907,8 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
   const std::string& native, bool ignoreErrors)
 {
   std::string makeCommand = cmSystemTools::GetCMakeCommand();
-  makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand);
-  makeCommand += " --build .";
+  makeCommand =
+    cmStrCat(cmSystemTools::ConvertToOutputPath(makeCommand), " --build .");
   if (!config.empty()) {
     makeCommand += " --config \"";
     makeCommand += config;
@@ -2047,8 +2011,8 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
   if (!gen->ConfiguredFilesPath.empty()) {
     this->ConfiguredFilesPath = gen->ConfiguredFilesPath;
   } else {
-    this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory();
-    this->ConfiguredFilesPath += "/CMakeFiles";
+    this->ConfiguredFilesPath =
+      cmStrCat(gen->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
   }
 }
 
@@ -2318,8 +2282,8 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
   std::vector<GlobalTargetInfo>& targets)
 {
   cmMakefile* mf = this->Makefiles[0];
-  std::string configFile = mf->GetCurrentBinaryDirectory();
-  configFile += "/CPackConfig.cmake";
+  std::string configFile =
+    cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake");
   if (!cmSystemTools::FileExists(configFile)) {
     return;
   }
@@ -2367,8 +2331,8 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource(
   }
 
   cmMakefile* mf = this->Makefiles[0];
-  std::string configFile = mf->GetCurrentBinaryDirectory();
-  configFile += "/CPackSourceConfig.cmake";
+  std::string configFile =
+    cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake");
   if (!cmSystemTools::FileExists(configFile)) {
     return;
   }
@@ -2647,8 +2611,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
 std::string cmGlobalGenerator::GenerateRuleFile(
   std::string const& output) const
 {
-  std::string ruleFile = output;
-  ruleFile += ".rule";
+  std::string ruleFile = cmStrCat(output, ".rule");
   const char* dir = this->GetCMakeCFGIntDir();
   if (dir && dir[0] == '$') {
     cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles");
@@ -2846,8 +2809,7 @@ void cmGlobalGenerator::CheckRuleHashes()
 {
 #if !defined(CMAKE_BOOTSTRAP)
   std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
-  std::string pfile = home;
-  pfile += "/CMakeFiles/CMakeRuleHashes.txt";
+  std::string pfile = cmStrCat(home, "/CMakeFiles/CMakeRuleHashes.txt");
   this->CheckRuleHashes(pfile, home);
   this->WriteRuleHashes(pfile);
 #endif
@@ -2923,8 +2885,8 @@ void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
 void cmGlobalGenerator::WriteSummary()
 {
   // Record all target directories in a central location.
-  std::string fname = this->CMakeInstance->GetHomeOutputDirectory();
-  fname += "/CMakeFiles/TargetDirectories.txt";
+  std::string fname = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+                               "/CMakeFiles/TargetDirectories.txt");
   cmGeneratedFileStream fout(fname);
 
   for (cmLocalGenerator* lg : this->LocalGenerators) {
@@ -2942,8 +2904,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
 {
   // Place the labels file in a per-target support directory.
   std::string dir = target->GetSupportDirectory();
-  std::string file = dir;
-  file += "/Labels.txt";
+  std::string file = cmStrCat(dir, "/Labels.txt");
   std::string json_file = dir + "/Labels.json";
 
 #ifndef CMAKE_BOOTSTRAP
@@ -3111,8 +3072,8 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile()
   std::vector<std::string> configs;
   std::string config = mf->GetConfigurations(configs, false);
 
-  std::string path = this->CMakeInstance->GetHomeOutputDirectory();
-  path += "/CPackProperties.cmake";
+  std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+                              "/CPackProperties.cmake");
 
   if (!cmSystemTools::FileExists(path) && installedFiles.empty()) {
     return true;

+ 26 - 39
Source/cmGlobalGhsMultiGenerator.cxx

@@ -57,11 +57,9 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   // Compute full path to object file directory for this target.
-  std::string dir;
-  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += gt->LocalGenerator->GetTargetDirectory(gt);
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             gt->LocalGenerator->GetTargetDirectory(gt), '/');
   gt->ObjectDirectory = dir;
 }
 
@@ -78,10 +76,9 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
   }
   if (ts.empty()) {
     std::string message;
-    message =
-      "Green Hills MULTI: -T <toolset> not specified; defaulting to \"";
-    message += tsp;
-    message += "\"";
+    message = cmStrCat(
+      "Green Hills MULTI: -T <toolset> not specified; defaulting to \"", tsp,
+      '"');
     cmSystemTools::Message(message);
 
     /* store the full toolset for later use
@@ -99,12 +96,11 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
 
   /* check if the toolset changed from last generate */
   if (prevTool != nullptr && (gbuild != prevTool)) {
-    std::string message = "toolset build tool: ";
-    message += gbuild;
-    message += "\nDoes not match the previously used build tool: ";
-    message += prevTool;
-    message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
-               "directory or choose a different binary directory.";
+    std::string message =
+      cmStrCat("toolset build tool: ", gbuild,
+               "\nDoes not match the previously used build tool: ", prevTool,
+               "\nEither remove the CMakeCache.txt file and CMakeFiles "
+               "directory or choose a different binary directory.");
     cmSystemTools::Error(message);
     return false;
   }
@@ -143,19 +139,17 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
   if (cmIsOff(osdir) && platform.find("integrity") != std::string::npos) {
     if (!this->CMakeInstance->GetIsInTryCompile()) {
       /* required OS location is not found */
-      std::string m =
-        "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"";
-      m += mf->GetSafeDefinition("GHS_OS_ROOT");
-      m += "\"";
+      std::string m = cmStrCat(
+        "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"",
+        mf->GetSafeDefinition("GHS_OS_ROOT"), '"');
       cmSystemTools::Message(m);
     }
     osdir = "GHS_OS_DIR-NOT-SPECIFIED";
   } else if (!this->CMakeInstance->GetIsInTryCompile() &&
              cmIsOff(this->OsDir) && !cmIsOff(osdir)) {
     /* OS location was updated by auto-selection */
-    std::string m = "Green Hills MULTI: GHS_OS_DIR not specified; found \"";
-    m += osdir;
-    m += "\"";
+    std::string m = cmStrCat(
+      "Green Hills MULTI: GHS_OS_DIR not specified; found \"", osdir, '"');
     cmSystemTools::Message(m);
   }
   this->OsDir = osdir;
@@ -169,10 +163,9 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
     mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(),
                            "Name of GHS target platform.",
                            cmStateEnums::STRING, true);
-    std::string m =
-      "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"";
-    m += bspName;
-    m += "\"";
+    std::string m = cmStrCat(
+      "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"",
+      bspName, '"');
     cmSystemTools::Message(m);
   }
 
@@ -403,8 +396,8 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine(
 
 void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
 {
-  std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
-  rootBinaryDir += "/CMakeFiles";
+  std::string rootBinaryDir =
+    cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles");
 
   // All known targets
   for (cmGeneratorTarget const* target : this->ProjectTargets) {
@@ -479,8 +472,8 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget(
     cmSystemTools::Error(message);
   } else {
     // determine the targets for ALL target
-    std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
-    rootBinaryDir += "/CMakeFiles";
+    std::string rootBinaryDir =
+      cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles");
     for (cmGeneratorTarget const* target : build) {
       if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
           target->GetType() == cmStateEnums::MODULE_LIBRARY ||
@@ -538,11 +531,8 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
    * with target projects.  This avoid the issue where the project has
    * the same name as the executable target.
    */
-  fname = root->GetCurrentBinaryDirectory();
-  fname += "/";
-  fname += root->GetProjectName();
-  fname += ".top";
-  fname += FILE_EXTENSION;
+  fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+                   root->GetProjectName(), ".top", FILE_EXTENSION);
 
   cmGeneratedFileStream top(fname);
   top.SetCopyIfDifferent(true);
@@ -643,10 +633,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
       this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
     const char* p =
       this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM");
-    tgt = (a ? a : "");
-    tgt += "_";
-    tgt += (p ? p : "");
-    tgt += ".tgt";
+    tgt = cmStrCat((a ? a : ""), '_', (p ? p : ""), ".tgt");
   }
 
   fout << "primaryTarget=" << tgt << std::endl;

+ 2 - 4
Source/cmGlobalMSYSMakefileGenerator.cxx

@@ -24,8 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm)
 std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
   std::string const& makeloc)
 {
-  std::string fstab = makeloc;
-  fstab += "/../etc/fstab";
+  std::string fstab = cmStrCat(makeloc, "/../etc/fstab");
   cmsys::ifstream fin(fstab.c_str());
   std::string path;
   std::string mount;
@@ -34,8 +33,7 @@ std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
     fin >> path;
     fin >> mount;
     if (mount == "/mingw") {
-      mingwBin = path;
-      mingwBin += "/bin";
+      mingwBin = cmStrCat(path, "/bin");
     }
   }
   return mingwBin;

+ 24 - 29
Source/cmGlobalNinjaGenerator.cxx

@@ -704,11 +704,9 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   // Compute full path to object file directory for this target.
-  std::string dir;
-  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += gt->LocalGenerator->GetTargetDirectory(gt);
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             gt->LocalGenerator->GetTargetDirectory(gt), '/');
   gt->ObjectDirectory = dir;
 }
 
@@ -718,9 +716,8 @@ bool cmGlobalNinjaGenerator::OpenBuildFileStream()
 {
   // Compute Ninja's build file path.
   std::string buildFilePath =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  buildFilePath += "/";
-  buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
+             cmGlobalNinjaGenerator::NINJA_BUILD_FILE);
 
   // Get a stream where to generate things.
   if (!this->BuildFileStream) {
@@ -757,9 +754,8 @@ bool cmGlobalNinjaGenerator::OpenRulesFileStream()
 {
   // Compute Ninja's build file path.
   std::string rulesFilePath =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  rulesFilePath += "/";
-  rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
+             cmGlobalNinjaGenerator::NINJA_RULES_FILE);
 
   // Get a stream where to generate things.
   if (!this->RulesFileStream) {
@@ -1314,13 +1310,13 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
 
   {
     cmNinjaRule rule("RERUN_CMAKE");
-    rule.Command = CMakeCmd();
-    rule.Command += " -S";
-    rule.Command += lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
-                                              cmOutputConverter::SHELL);
-    rule.Command += " -B";
-    rule.Command += lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
-                                              cmOutputConverter::SHELL);
+    rule.Command =
+      cmStrCat(CMakeCmd(), " -S",
+               lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
+                                         cmOutputConverter::SHELL),
+               " -B",
+               lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
+                                         cmOutputConverter::SHELL));
     rule.Description = "Re-running CMake...";
     rule.Comment = "Rule for re-running cmake.";
     rule.Generator = true;
@@ -1348,10 +1344,10 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
   if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) {
     {
       cmNinjaRule rule("VERIFY_GLOBS");
-      rule.Command = CMakeCmd();
-      rule.Command += " -P ";
-      rule.Command += lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
-                                                cmOutputConverter::SHELL);
+      rule.Command =
+        cmStrCat(CMakeCmd(), " -P ",
+                 lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+                                           cmOutputConverter::SHELL));
       rule.Description = "Re-checking globbed directories...";
       rule.Comment = "Rule for re-checking globbed directories.";
       rule.Generator = true;
@@ -1457,9 +1453,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
 {
   cmLocalGenerator* lgr = this->LocalGenerators.at(0);
   std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
-  std::string cleanScriptAbs = lgr->GetBinaryDirectory();
-  cleanScriptAbs += '/';
-  cleanScriptAbs += cleanScriptRel;
+  std::string cleanScriptAbs =
+    cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel);
 
   // Check if there are additional files to clean
   if (this->AdditionalCleanFiles.empty()) {
@@ -1489,10 +1484,10 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
   // Write rule
   {
     cmNinjaRule rule("CLEAN_ADDITIONAL");
-    rule.Command = CMakeCmd();
-    rule.Command += " -P ";
-    rule.Command += lgr->ConvertToOutputFormat(
-      this->NinjaOutputPath(cleanScriptRel), cmOutputConverter::SHELL);
+    rule.Command = cmStrCat(
+      CMakeCmd(), " -P ",
+      lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
+                                 cmOutputConverter::SHELL));
     rule.Description = "Cleaning additional files...";
     rule.Comment = "Rule for cleaning additional files.";
     WriteRule(*this->RulesFileStream, rule);

+ 46 - 69
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -108,11 +108,9 @@ void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   // Compute full path to object file directory for this target.
-  std::string dir;
-  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += gt->LocalGenerator->GetTargetDirectory(gt);
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             gt->LocalGenerator->GetTargetDirectory(gt), '/');
   gt->ObjectDirectory = dir;
 }
 
@@ -147,8 +145,8 @@ void cmGlobalUnixMakefileGenerator3::Generate()
     pmi.second.WriteProgressVariables(total, current);
   }
   for (cmLocalGenerator* lg : this->LocalGenerators) {
-    std::string markFileName = lg->GetCurrentBinaryDirectory();
-    markFileName += "/CMakeFiles/progress.marks";
+    std::string markFileName =
+      cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks");
     cmGeneratedFileStream markFile(markFileName);
     markFile << this->CountProgressMarksInAll(lg) << "\n";
   }
@@ -196,8 +194,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
   // because the check-build-system step compares the makefile time to
   // see if the build system must be regenerated.
   std::string makefileName =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  makefileName += "/CMakeFiles/Makefile2";
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+             "/CMakeFiles/Makefile2");
   cmGeneratedFileStream makefileStream(makefileName, false,
                                        this->GetMakefileEncoding());
   if (!makefileStream) {
@@ -255,16 +253,15 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   // because the check-build-system step compares the makefile time to
   // see if the build system must be regenerated.
   std::string cmakefileName =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  cmakefileName += "/CMakeFiles/Makefile.cmake";
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+             "/CMakeFiles/Makefile.cmake");
   cmGeneratedFileStream cmakefileStream(cmakefileName);
   if (!cmakefileStream) {
     return;
   }
 
   std::string makefileName =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  makefileName += "/Makefile";
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile");
 
   // get a local generator for some useful methods
   cmLocalUnixMakefileGenerator3* lg =
@@ -316,8 +313,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   cmakefileStream << "  )\n\n";
 
   // Build the path to the cache check file.
-  std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
-  check += "/CMakeFiles/cmake.check_cache";
+  std::string check =
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+             "/CMakeFiles/cmake.check_cache");
 
   // Set the corresponding makefile in the cmake file.
   cmakefileStream << "# The corresponding makefile is:\n"
@@ -347,8 +345,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     std::string tmpStr;
     for (cmLocalGenerator* localGen : this->LocalGenerators) {
       lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
-      tmpStr = lg->GetCurrentBinaryDirectory();
-      tmpStr += "/CMakeFiles/CMakeDirectoryInformation.cmake";
+      tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(),
+                        "/CMakeFiles/CMakeDirectoryInformation.cmake");
       cmakefileStream << "  \""
                       << lg->MaybeConvertToRelativePath(binDir, tmpStr)
                       << "\"\n";
@@ -380,8 +378,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
           (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
           (tgt->GetType() == cmStateEnums::UTILITY)) {
         cmGeneratorTarget* gt = tgt;
-        std::string tname = lg->GetRelativeTargetDirectory(gt);
-        tname += "/DependInfo.cmake";
+        std::string tname =
+          cmStrCat(lg->GetRelativeTargetDirectory(gt), "/DependInfo.cmake");
         cmSystemTools::ConvertToUnixSlashes(tname);
         cmakefileStream << "  \"" << tname << "\"\n";
       }
@@ -396,9 +394,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   std::vector<std::string> const& commands)
 {
   // Get the relative path to the subdirectory from the top.
-  std::string makeTarget = lg->GetCurrentBinaryDirectory();
-  makeTarget += '/';
-  makeTarget += pass;
+  std::string makeTarget =
+    cmStrCat(lg->GetCurrentBinaryDirectory(), '/', pass);
 
   // The directory-level rule should depend on the target-level rules
   // for all targets in the directory.
@@ -415,9 +412,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
       if ((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
           (!check_relink ||
            gtarget->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
-        std::string tname = lg->GetRelativeTargetDirectory(gtarget);
-        tname += "/";
-        tname += pass;
+        std::string tname =
+          cmStrCat(lg->GetRelativeTargetDirectory(gtarget), '/', pass);
         depends.push_back(std::move(tname));
       }
     }
@@ -426,9 +422,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   // The directory-level rule should depend on the directory-level
   // rules of the subdirectories.
   for (cmStateSnapshot const& c : lg->GetStateSnapshot().GetChildren()) {
-    std::string subdir = c.GetDirectory().GetCurrentBinary();
-    subdir += '/';
-    subdir += pass;
+    std::string subdir =
+      cmStrCat(c.GetDirectory().GetCurrentBinary(), '/', pass);
     depends.push_back(std::move(subdir));
   }
 
@@ -441,13 +436,9 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   // Write the rule.
   std::string doc;
   if (lg->IsRootMakefile()) {
-    doc = "The main recursive \"";
-    doc += pass;
-    doc += "\" target.";
+    doc = cmStrCat("The main recursive \"", pass, "\" target.");
   } else {
-    doc = "Recursive \"";
-    doc += pass;
-    doc += "\" directory target.";
+    doc = cmStrCat("Recursive \"", pass, "\" directory target.");
   }
   lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, commands,
                     true);
@@ -578,8 +569,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
 
         // Write the rule.
         commands.clear();
-        std::string tmp = "CMakeFiles/";
-        tmp += "Makefile2";
+        std::string tmp = "CMakeFiles/Makefile2";
         commands.push_back(lg->GetRecursiveMakeCall(tmp, name));
         depends.clear();
         if (regenerate) {
@@ -591,14 +581,11 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
         // Add a fast rule to build the target
         std::string localName = lg->GetRelativeTargetDirectory(gtarget);
         std::string makefileName;
-        makefileName = localName;
-        makefileName += "/build.make";
+        makefileName = cmStrCat(localName, "/build.make");
         depends.clear();
         commands.clear();
-        std::string makeTargetName = localName;
-        makeTargetName += "/build";
-        localName = name;
-        localName += "/fast";
+        std::string makeTargetName = cmStrCat(localName, "/build");
+        localName = cmStrCat(name, "/fast");
         commands.push_back(
           lg->GetRecursiveMakeCall(makefileName, makeTargetName));
         lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
@@ -607,10 +594,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
         // Add a local name for the rule to relink the target before
         // installation.
         if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
-          makeTargetName = lg->GetRelativeTargetDirectory(gtarget);
-          makeTargetName += "/preinstall";
-          localName = name;
-          localName += "/preinstall";
+          makeTargetName =
+            cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall");
+          localName = cmStrCat(name, "/preinstall");
           depends.clear();
           commands.clear();
           commands.push_back(
@@ -654,20 +640,17 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       std::string makefileName;
       // Add a rule to build the target by name.
       localName = lg->GetRelativeTargetDirectory(gtarget);
-      makefileName = localName;
-      makefileName += "/build.make";
+      makefileName = cmStrCat(localName, "/build.make");
 
       lg->WriteDivider(ruleFileStream);
       ruleFileStream << "# Target rules for target " << localName << "\n\n";
 
       commands.clear();
-      makeTargetName = localName;
-      makeTargetName += "/depend";
+      makeTargetName = cmStrCat(localName, "/depend");
       commands.push_back(
         lg->GetRecursiveMakeCall(makefileName, makeTargetName));
 
-      makeTargetName = localName;
-      makeTargetName += "/build";
+      makeTargetName = cmStrCat(localName, "/build");
       commands.push_back(
         lg->GetRecursiveMakeCall(makefileName, makeTargetName));
 
@@ -676,8 +659,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       depends.clear();
 
       cmLocalUnixMakefileGenerator3::EchoProgress progress;
-      progress.Dir = lg->GetBinaryDirectory();
-      progress.Dir += "/CMakeFiles";
+      progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles");
       {
         std::ostringstream progressArg;
         const char* sep = "";
@@ -720,8 +702,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
         progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted);
         commands.push_back(progCmd.str());
       }
-      std::string tmp = "CMakeFiles/";
-      tmp += "Makefile2";
+      std::string tmp = "CMakeFiles/Makefile2";
       commands.push_back(lg->GetRecursiveMakeCall(tmp, localName));
       {
         std::ostringstream progCmd;
@@ -736,8 +717,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       if (regenerate) {
         depends.emplace_back("cmake_check_build_system");
       }
-      localName = lg->GetRelativeTargetDirectory(gtarget);
-      localName += "/rule";
+      localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/rule");
       lg->WriteMakeRule(ruleFileStream,
                         "Build rule for subdir invocation for target.",
                         localName, depends, commands, true);
@@ -751,8 +731,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
 
       // Add rules to prepare the target for installation.
       if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
-        localName = lg->GetRelativeTargetDirectory(gtarget);
-        localName += "/preinstall";
+        localName =
+          cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall");
         depends.clear();
         commands.clear();
         commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName));
@@ -771,8 +751,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
 
       // add the clean rule
       localName = lg->GetRelativeTargetDirectory(gtarget);
-      makeTargetName = localName;
-      makeTargetName += "/clean";
+      makeTargetName = cmStrCat(localName, "/clean");
       depends.clear();
       commands.clear();
       commands.push_back(
@@ -891,9 +870,9 @@ void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends(
     }
     cmLocalUnixMakefileGenerator3* lg3 =
       static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
-    std::string tgtName =
-      lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep));
-    tgtName += "/all";
+    std::string tgtName = cmStrCat(
+      lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)),
+      "/all");
     depends.push_back(tgtName);
   }
 }
@@ -936,8 +915,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
             (type == cmStateEnums::UTILITY)) {
           std::string const& name = target->GetName();
           if (emittedTargets.insert(name).second) {
-            path = "... ";
-            path += name;
+            path = cmStrCat("... ", name);
             lg->AppendEcho(commands, path);
           }
         }
@@ -945,8 +923,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
     }
   }
   for (std::string const& o : lg->GetLocalHelp()) {
-    path = "... ";
-    path += o;
+    path = cmStrCat("... ", o);
     lg->AppendEcho(commands, path);
   }
   lg->WriteMakeRule(ruleFileStream, "Help Target", "help", no_depends,

+ 13 - 16
Source/cmGlobalVisualStudio10Generator.cxx

@@ -678,9 +678,9 @@ std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand()
   std::string mskey;
 
   // Search in standard location.
-  mskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\";
-  mskey += this->GetToolsVersion();
-  mskey += ";MSBuildToolsPath";
+  mskey = cmStrCat(
+    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\",
+    this->GetToolsVersion(), ";MSBuildToolsPath");
   if (cmSystemTools::ReadRegistryValue(mskey.c_str(), msbuild,
                                        cmSystemTools::KeyWOW64_32)) {
     cmSystemTools::ConvertToUnixSlashes(msbuild);
@@ -720,8 +720,8 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
     // In a try-compile we are given the outer CMakeFiles directory.
     wd = this->ConfiguredFilesPath;
   } else {
-    wd = this->GetCMakeInstance()->GetHomeOutputDirectory();
-    wd += "/CMakeFiles";
+    wd = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+                  "/CMakeFiles");
   }
   wd += "/";
   wd += cmVersion::GetCMakeVersion();
@@ -905,8 +905,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   {
     std::string slnFile;
     if (!projectDir.empty()) {
-      slnFile = projectDir;
-      slnFile += "/";
+      slnFile = cmStrCat(projectDir, '/');
     }
     slnFile += projectName;
     slnFile += ".sln";
@@ -953,8 +952,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
       makeCommand.Add(std::string(projectName) + ".sln");
       makeCommand.Add("/t:Clean");
     } else {
-      std::string targetProject(tname);
-      targetProject += ".vcxproj";
+      std::string targetProject = cmStrCat(tname, ".vcxproj");
       if (targetProject.find('/') == std::string::npos) {
         // it might be in a subdir
         if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) {
@@ -1037,13 +1035,12 @@ std::string cmGlobalVisualStudio10Generator::GenerateRuleFile(
 {
   // The VS 10 generator needs to create the .rule files on disk.
   // Hide them away under the CMakeFiles directory.
-  std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory();
-  ruleDir += "/CMakeFiles/";
-  ruleDir += cmSystemTools::ComputeStringMD5(
-    cmSystemTools::GetFilenamePath(output).c_str());
-  std::string ruleFile = ruleDir + "/";
-  ruleFile += cmSystemTools::GetFilenameName(output);
-  ruleFile += ".rule";
+  std::string ruleDir = cmStrCat(
+    this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeFiles/",
+    cmSystemTools::ComputeStringMD5(
+      cmSystemTools::GetFilenamePath(output).c_str()));
+  std::string ruleFile =
+    cmStrCat(ruleDir, '/', cmSystemTools::GetFilenameName(output), ".rule");
   return ruleFile;
 }
 

Some files were not shown because too many files changed in this diff