Merge topic 'vs-fortran' into release-4.3

ec06d16178 cmSourceGroup: Constify clients
f513867bc4 VS: Fix regression causing source accumulation across Fortran projects

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !11999
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 9a5e109..7427422 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -463,7 +463,8 @@
 }
 
 void cmExtraEclipseCDT4Generator::WriteGroups(
-  SourceGroupVector const& sourceGroups, std::string& linkName,
+  SourceGroupVector const& sourceGroups,
+  cmSourceGroupFiles const& sourceGroupFiles, std::string& linkName,
   cmXMLWriter& xml)
 {
   for (auto const& sg : sourceGroups) {
@@ -475,10 +476,11 @@
       xml, linkName3, "virtual:/virtual", VirtualFolder);
     SourceGroupVector const& children = sg->GetGroupChildren();
     if (!children.empty()) {
-      this->WriteGroups(children, linkName, xml);
+      this->WriteGroups(children, sourceGroupFiles, linkName, xml);
     }
-    std::vector<cmSourceFile const*> sFiles = sg->GetSourceFiles();
-    for (cmSourceFile const* file : sFiles) {
+    std::vector<cmSourceFile const*> const& sourceFiles =
+      sourceGroupFiles.GetSourceFiles(sg.get());
+    for (cmSourceFile const* file : sourceFiles) {
       std::string const& fullPath = file->GetFullPath();
 
       if (!cmSystemTools::FileIsDirectory(fullPath)) {
@@ -521,17 +523,18 @@
             break; // skip generating the linked resources to the source files
           }
           // get the files from the source lists then add them to the groups
+          cmSourceGroupFiles sourceGroupFiles;
           std::vector<cmSourceFile*> files;
           target->GetSourceFiles(
             files, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
           for (cmSourceFile* sf : files) {
             // Add the file to the list of sources.
-            std::string const& source = sf->ResolveFullPath();
-            cmSourceGroup* sourceGroup = lg->FindSourceGroup(source);
-            sourceGroup->AssignSource(sf);
+            sourceGroupFiles.Add(lg->FindSourceGroup(sf->ResolveFullPath()),
+                                 sf);
           }
 
-          this->WriteGroups(makefile->GetSourceGroups(), linkName2, xml);
+          this->WriteGroups(makefile->GetSourceGroups(), sourceGroupFiles,
+                            linkName2, xml);
         } break;
         // ignore all others:
         default:
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index aa7cc25..fa92fb4 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -88,6 +88,7 @@
                         cmLocalGenerator& lg);
 
   void WriteGroups(SourceGroupVector const& sourceGroups,
+                   cmSourceGroupFiles const& sourceGroupFiles,
                    std::string& linkName, cmXMLWriter& xml);
   void CreateLinksToSubprojects(cmXMLWriter& xml, std::string const& baseDir);
   void CreateLinksForTargets(cmXMLWriter& xml);
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 2950c67..0d916b0 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -487,7 +487,7 @@
   void ProcessLanguages();
   void ProcessLanguage(std::string const& lang);
 
-  Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg);
+  Json::ArrayIndex AddSourceGroup(cmSourceGroup const* sg);
   CompileData BuildCompileData(cmSourceFile* sf);
   CompileData MergeCompileData(CompileData const& fd);
   Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf,
@@ -1477,7 +1477,7 @@
   }
 }
 
-Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg)
+Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup const* sg)
 {
   auto i = this->SourceGroupsMap.find(sg);
   if (i == this->SourceGroupsMap.end()) {
@@ -1829,7 +1829,8 @@
     source["fileSetIndex"] = fsit->second;
   }
 
-  if (cmSourceGroup* sg = this->GT->LocalGenerator->FindSourceGroup(path)) {
+  if (cmSourceGroup const* sg =
+        this->GT->LocalGenerator->FindSourceGroup(path)) {
     Json::ArrayIndex const groupIndex = this->AddSourceGroup(sg);
     source["sourceGroupIndex"] = groupIndex;
     this->SourceGroups[groupIndex].SourceIndexes.append(si);
@@ -1913,7 +1914,8 @@
     source["fileSetIndex"] = fsit->second;
   }
 
-  if (cmSourceGroup* sg = this->GT->LocalGenerator->FindSourceGroup(path)) {
+  if (cmSourceGroup const* sg =
+        this->GT->LocalGenerator->FindSourceGroup(path)) {
     Json::ArrayIndex const groupIndex = this->AddSourceGroup(sg);
     source["sourceGroupIndex"] = groupIndex;
     this->SourceGroups[groupIndex].InterfaceSourceIndexes.append(si);
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 16e68fd..8c9c658 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -513,7 +513,7 @@
   std::map<std::string, std::vector<cmSourceFile*>> groupFiles;
   std::set<std::string> groupNames;
   for (cmSourceFile* sf : sources) {
-    cmSourceGroup* sourceGroup =
+    cmSourceGroup const* sourceGroup =
       this->LocalGenerator->FindSourceGroup(sf->ResolveFullPath());
     std::string gn = sourceGroup->GetFullName();
     groupFiles[gn].push_back(sf);
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 074caea..f0cca84 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -1062,7 +1062,7 @@
       item =
         cmSystemTools::CollapseFullPath(item, mf->GetCurrentSourceDirectory());
     }
-    cmSourceGroup* sg =
+    cmSourceGroup const* sg =
       cmSourceGroup::FindSourceGroup(item, mf->GetSourceGroups());
     std::string folderName = sg->GetFullName();
     if (folderName.empty()) {
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 68614bb..5ac06eb 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -4516,7 +4516,7 @@
 
       auto addSourceToGroup = [this, &gtgt,
                                &generator](std::string const& source) {
-        cmSourceGroup* sourceGroup = generator->FindSourceGroup(source);
+        cmSourceGroup const* sourceGroup = generator->FindSourceGroup(source);
         cmXCodeObject* pbxgroup =
           this->CreateOrGetPBXGroup(gtgt.get(), sourceGroup);
         std::string key = GetGroupMapKeyFromPath(gtgt.get(), source);
@@ -4592,7 +4592,7 @@
 }
 
 cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
-  cmGeneratorTarget* gtgt, cmSourceGroup* sg)
+  cmGeneratorTarget* gtgt, cmSourceGroup const* sg)
 {
   std::string s;
   std::string target;
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 82bb9d5..114caec 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -161,7 +161,7 @@
                             cm::string_view attributeValue);
 
   cmXCodeObject* CreateOrGetPBXGroup(cmGeneratorTarget* gtgt,
-                                     cmSourceGroup* sg);
+                                     cmSourceGroup const* sg);
   cmXCodeObject* CreatePBXGroup(cmXCodeObject* parent,
                                 std::string const& name);
   bool CreateGroups(std::vector<cmLocalGenerator*>& generators);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 567ce3b..a6bf9c8 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1386,6 +1386,8 @@
   AllConfigSources sources;
   sources.Sources = target->GetAllConfigSources();
 
+  cmSourceGroupFiles sourceGroupFiles;
+
   // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
   if (target->GetType() != cmStateEnums::GLOBAL_TARGET &&
       target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
@@ -1423,9 +1425,7 @@
       }
     }
     // Add the file to the list of sources.
-    std::string const source = sf->GetFullPath();
-    cmSourceGroup* sourceGroup = this->FindSourceGroup(source);
-    sourceGroup->AssignSource(sf);
+    sourceGroupFiles.Add(this->FindSourceGroup(sf->GetFullPath()), sf);
   }
 
   // open the project
@@ -1438,7 +1438,8 @@
   // Loop through every source group.
   SourceGroupVector const& sourceGroups = this->Makefile->GetSourceGroups();
   for (auto const& sg : sourceGroups) {
-    this->WriteGroup(sg.get(), target, fout, libName, configs, sources);
+    this->WriteGroup(sg.get(), target, fout, libName, configs, sources,
+                     sourceGroupFiles);
   }
 
   fout << "\t</Files>\n";
@@ -1648,11 +1649,12 @@
 bool cmLocalVisualStudio7Generator::WriteGroup(
   cmSourceGroup const* sg, cmGeneratorTarget* target, std::ostream& fout,
   std::string const& libName, std::vector<std::string> const& configs,
-  AllConfigSources const& sources)
+  AllConfigSources const& sources, cmSourceGroupFiles const& sourceGroupFiles)
 {
   cmGlobalVisualStudio7Generator* gg =
     static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
-  std::vector<cmSourceFile const*> const& sourceFiles = sg->GetSourceFiles();
+  std::vector<cmSourceFile const*> const& sourceFiles =
+    sourceGroupFiles.GetSourceFiles(sg);
   SourceGroupVector const& children = sg->GetGroupChildren();
 
   // Write the children to temporary output.
@@ -1660,7 +1662,7 @@
   std::ostringstream tmpOut;
   for (auto const& child : children) {
     if (this->WriteGroup(child.get(), target, tmpOut, libName, configs,
-                         sources)) {
+                         sources, sourceGroupFiles)) {
       hasChildrenWithSources = true;
     }
   }
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 38df53b..885d8ca 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -23,6 +23,7 @@
 class cmMakefile;
 class cmSourceFile;
 class cmSourceGroup;
+class cmSourceGroupFiles;
 
 class cmVS7GeneratorOptions : public cmVisualStudioGeneratorOptions
 {
@@ -147,7 +148,8 @@
   bool WriteGroup(cmSourceGroup const* sg, cmGeneratorTarget* target,
                   std::ostream& fout, std::string const& libName,
                   std::vector<std::string> const& configs,
-                  AllConfigSources const& sources);
+                  AllConfigSources const& sources,
+                  cmSourceGroupFiles const& sourceGroupFiles);
 
   friend class cmLocalVisualStudio7GeneratorFCInfo;
   friend class cmLocalVisualStudio7GeneratorInternals;
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index 7251810..3b5feea 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -7,7 +7,6 @@
 #include <cm/memory>
 
 #include "cmGeneratorExpression.h"
-#include "cmSourceFile.h"
 #include "cmStringAlgorithms.h"
 
 class cmSourceGroupInternals
@@ -85,21 +84,11 @@
   return this->GroupFiles.find(name) != this->GroupFiles.cend();
 }
 
-void cmSourceGroup::AssignSource(cmSourceFile const* sf)
-{
-  this->SourceFiles.push_back(sf);
-}
-
 std::set<std::string> const& cmSourceGroup::GetGroupFiles() const
 {
   return this->GroupFiles;
 }
 
-std::vector<cmSourceFile const*> const& cmSourceGroup::GetSourceFiles() const
-{
-  return this->SourceFiles;
-}
-
 void cmSourceGroup::AddChild(std::unique_ptr<cmSourceGroup> child)
 {
   this->Internal->GroupChildren.push_back(std::move(child));
@@ -196,3 +185,19 @@
   // Shouldn't get here, but just in case, return the default group.
   return groups.data()->get();
 }
+
+void cmSourceGroupFiles::Add(cmSourceGroup const* sg, cmSourceFile const* sf)
+{
+  this->SourceFiles[sg].push_back(sf);
+}
+
+std::vector<cmSourceFile const*> const& cmSourceGroupFiles::GetSourceFiles(
+  cmSourceGroup const* sg) const
+{
+  auto i = this->SourceFiles.find(sg);
+  if (i != this->SourceFiles.end()) {
+    return i->second;
+  }
+  static std::vector<cmSourceFile const*> const empty;
+  return empty;
+}
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index 4ce79ed..ff7d23f 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -4,6 +4,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <map>
 #include <memory>
 #include <set>
 #include <string>
@@ -100,22 +101,10 @@
   cmSourceGroup* MatchChildrenRegex(std::string const& name) const;
 
   /**
-   * Assign the given source file to this group.  Used only by
-   * generators.
-   */
-  void AssignSource(cmSourceFile const* sf);
-
-  /**
    * Get the set of file names explicitly added to this source group.
    */
   std::set<std::string> const& GetGroupFiles() const;
 
-  /**
-   * Get the list of the source files that have been assigned to this
-   * source group.
-   */
-  std::vector<cmSourceFile const*> const& GetSourceFiles() const;
-
   SourceGroupVector const& GetGroupChildren() const;
 
   /**
@@ -142,11 +131,18 @@
    */
   std::set<std::string> GroupFiles;
 
-  /**
-   * Vector of all source files that have been assigned to
-   * this group.
-   */
-  std::vector<cmSourceFile const*> SourceFiles;
-
   std::unique_ptr<cmSourceGroupInternals> Internal;
 };
+
+/** \class cmSourceGroup
+ * \brief Used by generators to organize a target's sources into groups.
+ */
+class cmSourceGroupFiles
+{
+  std::map<cmSourceGroup const*, std::vector<cmSourceFile const*>> SourceFiles;
+
+public:
+  void Add(cmSourceGroup const* sg, cmSourceFile const* sf);
+  std::vector<cmSourceFile const*> const& GetSourceFiles(
+    cmSourceGroup const* sg) const;
+};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 364fd56..d617dc69 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2004,14 +2004,16 @@
   std::set<cmSourceGroup const*> groupsUsed;
   for (cmGeneratorTarget::AllConfigSource const& si : sources) {
     std::string const& source = si.Source->GetFullPath();
-    cmSourceGroup* sourceGroup = this->LocalGenerator->FindSourceGroup(source);
+    cmSourceGroup const* sourceGroup =
+      this->LocalGenerator->FindSourceGroup(source);
     groupsUsed.insert(sourceGroup);
   }
 
   if (cmSourceFile const* srcCMakeLists =
         this->LocalGenerator->CreateVCProjBuildRule()) {
     std::string const& source = srcCMakeLists->GetFullPath();
-    cmSourceGroup* sourceGroup = this->LocalGenerator->FindSourceGroup(source);
+    cmSourceGroup const* sourceGroup =
+      this->LocalGenerator->FindSourceGroup(source);
     groupsUsed.insert(sourceGroup);
   }
 
@@ -2170,7 +2172,8 @@
   for (ToolSource const& s : sources) {
     cmSourceFile const* sf = s.SourceFile;
     std::string const& source = sf->GetFullPath();
-    cmSourceGroup* sourceGroup = this->LocalGenerator->FindSourceGroup(source);
+    cmSourceGroup const* sourceGroup =
+      this->LocalGenerator->FindSourceGroup(source);
     std::string const& filter = sourceGroup->GetFullName();
     std::string path = this->ConvertPath(source, s.RelativePath);
     ConvertToWindowsSlash(path);
@@ -6031,7 +6034,7 @@
   std::string const& fullFileName = source->GetFullPath();
   std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory();
   std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory();
-  cmSourceGroup* sourceGroup =
+  cmSourceGroup const* sourceGroup =
     this->LocalGenerator->FindSourceGroup(fullFileName);
   if (sourceGroup && !sourceGroup->GetFullName().empty()) {
     sourceGroupedFile =