Преглед изворни кода

Merge topic 'imported-same-name'

f35be59961 Fix transitive usage requirements through same-name imported targets
1b57f49586 genex: Simplify cmGeneratorExpressionInterpreter
bea390e9bd Fix dependency propagation through same-name imported targets
fc7e4d1ed8 cmLinkItem: Convert to a "sum type" over a string and target pointer

Acked-by: Kitware Robot <[email protected]>
Merge-request: !2359
Brad King пре 7 година
родитељ
комит
b1c8d95dbe

+ 1 - 0
Source/CMakeLists.txt

@@ -265,6 +265,7 @@ set(SRCS
   cmInstallDirectoryGenerator.h
   cmInstallDirectoryGenerator.cxx
   cmLinkedTree.h
+  cmLinkItem.cxx
   cmLinkItem.h
   cmLinkLineComputer.cxx
   cmLinkLineComputer.h

+ 17 - 16
Source/cmComputeLinkDepends.cxx

@@ -279,12 +279,12 @@ cmComputeLinkDepends::Compute()
   return this->FinalLinkEntries;
 }
 
-std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
-  std::string const& item)
+std::map<cmLinkItem, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
+  cmLinkItem const& item)
 {
-  std::map<std::string, int>::value_type index_entry(
+  std::map<cmLinkItem, int>::value_type index_entry(
     item, static_cast<int>(this->EntryList.size()));
-  std::map<std::string, int>::iterator lei =
+  std::map<cmLinkItem, int>::iterator lei =
     this->LinkEntryIndex.insert(index_entry).first;
   this->EntryList.emplace_back();
   this->InferredDependSets.push_back(nullptr);
@@ -295,7 +295,7 @@ std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
 int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
 {
   // Check if the item entry has already been added.
-  std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item);
+  std::map<cmLinkItem, int>::iterator lei = this->LinkEntryIndex.find(item);
   if (lei != this->LinkEntryIndex.end()) {
     // Yes.  We do not need to follow the item's dependencies again.
     return lei->second;
@@ -307,10 +307,11 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
   // Initialize the item entry.
   int index = lei->second;
   LinkEntry& entry = this->EntryList[index];
-  entry.Item = item;
+  entry.Item = item.AsStr();
   entry.Target = item.Target;
-  entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
-                  item.substr(0, 10) != "-framework");
+  entry.IsFlag =
+    (!entry.Target && entry.Item[0] == '-' && entry.Item[1] != 'l' &&
+     entry.Item.substr(0, 10) != "-framework");
 
   // If the item has dependencies queue it to follow them.
   if (entry.Target) {
@@ -395,7 +396,7 @@ void cmComputeLinkDepends::QueueSharedDependencies(
 void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
 {
   // Check if the target already has an entry.
-  std::map<std::string, int>::iterator lei =
+  std::map<cmLinkItem, int>::iterator lei =
     this->LinkEntryIndex.find(dep.Item);
   if (lei == this->LinkEntryIndex.end()) {
     // Allocate a spot for the item entry.
@@ -403,7 +404,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
 
     // Initialize the item entry.
     LinkEntry& entry = this->EntryList[lei->second];
-    entry.Item = dep.Item;
+    entry.Item = dep.Item.AsStr();
     entry.Target = dep.Item.Target;
 
     // This item was added specifically because it is a dependent
@@ -473,9 +474,9 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
 
       // If the library is meant for this link type then use it.
       if (llt == GENERAL_LibraryType || llt == this->LinkType) {
-        actual_libs.emplace_back(d, this->FindTargetToLink(depender_index, d));
+        actual_libs.emplace_back(this->ResolveLinkItem(depender_index, d));
       } else if (this->OldLinkDirMode) {
-        cmLinkItem item(d, this->FindTargetToLink(depender_index, d));
+        cmLinkItem item = this->ResolveLinkItem(depender_index, d);
         this->CheckWrongConfigItem(item);
       }
 
@@ -512,7 +513,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
     // Skip entries that will resolve to the target getting linked or
     // are empty.
     cmLinkItem const& item = l;
-    if (item == this->Target->GetName() || item.empty()) {
+    if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) {
       continue;
     }
 
@@ -553,8 +554,8 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
   }
 }
 
-cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
-  int depender_index, const std::string& name)
+cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
+                                                 const std::string& name)
 {
   // Look for a target in the scope of the depender.
   cmGeneratorTarget const* from = this->Target;
@@ -564,7 +565,7 @@ cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
       from = depender;
     }
   }
-  return from->FindTargetToLink(name);
+  return from->ResolveLinkItem(name);
 }
 
 void cmComputeLinkDepends::InferDependencies()

+ 4 - 5
Source/cmComputeLinkDepends.h

@@ -72,19 +72,18 @@ private:
   std::string Config;
   EntryVector FinalLinkEntries;
 
-  std::map<std::string, int>::iterator AllocateLinkEntry(
-    std::string const& item);
+  std::map<cmLinkItem, int>::iterator AllocateLinkEntry(
+    cmLinkItem const& item);
   int AddLinkEntry(cmLinkItem const& item);
   void AddVarLinkEntries(int depender_index, const char* value);
   void AddDirectLinkEntries();
   template <typename T>
   void AddLinkEntries(int depender_index, std::vector<T> const& libs);
-  cmGeneratorTarget const* FindTargetToLink(int depender_index,
-                                            const std::string& name);
+  cmLinkItem ResolveLinkItem(int depender_index, const std::string& name);
 
   // One entry for each unique item.
   std::vector<LinkEntry> EntryList;
-  std::map<std::string, int> LinkEntryIndex;
+  std::map<cmLinkItem, int> LinkEntryIndex;
 
   // BFS of initial dependencies.
   struct BFSEntry

+ 25 - 21
Source/cmComputeTargetDepends.cxx

@@ -195,7 +195,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
   // dependencies in all targets, because the generated build-systems can't
   // deal with config-specific dependencies.
   {
-    std::set<std::string> emitted;
+    std::set<cmLinkItem> emitted;
 
     std::vector<std::string> configs;
     depender->Makefile->GetConfigurations(configs);
@@ -206,27 +206,31 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
       std::vector<cmSourceFile const*> objectFiles;
       depender->GetExternalObjects(objectFiles, it);
       for (cmSourceFile const* o : objectFiles) {
-        std::string objLib = o->GetObjectLibrary();
-        if (!objLib.empty() && emitted.insert(objLib).second) {
-          if (depender->GetType() != cmStateEnums::EXECUTABLE &&
-              depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
-              depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
-              depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
-              depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
-            this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
-              cmake::FATAL_ERROR,
-              "Only executables and libraries may reference target objects.",
-              depender->GetBacktrace());
-            return;
+        std::string const& objLib = o->GetObjectLibrary();
+        if (!objLib.empty()) {
+          cmLinkItem const& objItem = depender->ResolveLinkItem(objLib);
+          if (emitted.insert(objItem).second) {
+            if (depender->GetType() != cmStateEnums::EXECUTABLE &&
+                depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
+                depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
+                depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+                depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+              this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+                cmake::FATAL_ERROR,
+                "Only executables and libraries may reference target objects.",
+                depender->GetBacktrace());
+              return;
+            }
+            const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(
+              objLib);
           }
-          const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib);
         }
       }
 
       cmLinkImplementation const* impl = depender->GetLinkImplementation(it);
 
       // A target should not depend on itself.
-      emitted.insert(depender->GetName());
+      emitted.insert(cmLinkItem(depender));
       for (cmLinkImplItem const& lib : impl->Libraries) {
         // Don't emit the same library twice for this target.
         if (emitted.insert(lib).second) {
@@ -240,9 +244,9 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
   // Loop over all utility dependencies.
   {
     std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
-    std::set<std::string> emitted;
+    std::set<cmLinkItem> emitted;
     // A target should not depend on itself.
-    emitted.insert(depender->GetName());
+    emitted.insert(cmLinkItem(depender));
     for (cmLinkItem const& litem : tutils) {
       // Don't emit the same utility twice for this target.
       if (emitted.insert(litem).second) {
@@ -254,7 +258,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
 
 void cmComputeTargetDepends::AddInterfaceDepends(
   int depender_index, const cmGeneratorTarget* dependee,
-  const std::string& config, std::set<std::string>& emitted)
+  const std::string& config, std::set<cmLinkItem>& emitted)
 {
   cmGeneratorTarget const* depender = this->Targets[depender_index];
   if (cmLinkInterface const* iface =
@@ -271,7 +275,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
 
 void cmComputeTargetDepends::AddInterfaceDepends(
   int depender_index, cmLinkItem const& dependee_name,
-  const std::string& config, std::set<std::string>& emitted)
+  const std::string& config, std::set<cmLinkItem>& emitted)
 {
   cmGeneratorTarget const* depender = this->Targets[depender_index];
   cmGeneratorTarget const* dependee = dependee_name.Target;
@@ -285,7 +289,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
 
   if (dependee) {
     // A target should not depend on itself.
-    emitted.insert(depender->GetName());
+    emitted.insert(cmLinkItem(depender));
     this->AddInterfaceDepends(depender_index, dependee, config, emitted);
   }
 }
@@ -324,7 +328,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
         << depender->GetName() << "\" does not exist.";
 
       cmListFileBacktrace const* backtrace =
-        depender->GetUtilityBacktrace(dependee_name);
+        depender->GetUtilityBacktrace(dependee_name.AsStr());
       if (backtrace) {
         cm->IssueMessage(messageType, e.str(), *backtrace);
       } else {

+ 2 - 2
Source/cmComputeTargetDepends.h

@@ -51,11 +51,11 @@ private:
   bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
   void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
                            const std::string& config,
-                           std::set<std::string>& emitted);
+                           std::set<cmLinkItem>& emitted);
   void AddInterfaceDepends(int depender_index,
                            cmGeneratorTarget const* dependee,
                            const std::string& config,
-                           std::set<std::string>& emitted);
+                           std::set<cmLinkItem>& emitted);
   cmGlobalGenerator* GlobalGenerator;
   bool DebugMode;
   bool NoCycles;

+ 1 - 1
Source/cmExportBuildAndroidMKGenerator.cxx

@@ -108,7 +108,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
         // build type of the makefile
         cmGeneratorExpression ge;
         cmGeneratorExpressionDAGChecker dagChecker(
-          target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
+          target, "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
         std::unique_ptr<cmCompiledGeneratorExpression> cge =
           ge.Parse(property.second);
         std::string evaluated = cge->Evaluate(

+ 11 - 1
Source/cmExportFileGenerator.cxx

@@ -831,6 +831,16 @@ void cmExportFileGenerator::SetImportDetailProperties(
   }
 }
 
+static std::string const& asString(std::string const& l)
+{
+  return l;
+}
+
+static std::string const& asString(cmLinkItem const& l)
+{
+  return l.AsStr();
+}
+
 template <typename T>
 void cmExportFileGenerator::SetImportLinkProperty(
   std::string const& suffix, cmGeneratorTarget* target,
@@ -850,7 +860,7 @@ void cmExportFileGenerator::SetImportLinkProperty(
     link_entries += sep;
     sep = ";";
 
-    std::string temp = l;
+    std::string temp = asString(l);
     this->AddTargetNamespace(temp, target, missingTargets);
     link_entries += temp;
   }

+ 1 - 2
Source/cmExportTryCompileFileGenerator.cxx

@@ -65,8 +65,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
 
   cmGeneratorExpression ge;
 
-  cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName, nullptr,
-                                             nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr);
 
   std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
 

+ 6 - 6
Source/cmExtraSublimeTextGenerator.cxx

@@ -354,8 +354,8 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
   lg->GetTargetCompileFlags(gtgt, config, language, flags);
 
   // Add source file specific flags.
-  cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config,
-                                                    gtgt->GetName(), language);
+  cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gtgt,
+                                                    language);
 
   const std::string COMPILE_FLAGS("COMPILE_FLAGS");
   if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
@@ -381,8 +381,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
   cmMakefile* makefile = lg->GetMakefile();
   const std::string& language = source->GetLanguage();
   const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-  cmGeneratorExpressionInterpreter genexInterpreter(
-    lg, target, config, target->GetName(), language);
+  cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+                                                    language);
 
   // Add the export symbol definition for shared library objects.
   if (const char* exportMacro = target->GetExportMacro()) {
@@ -419,8 +419,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes(
   cmMakefile* makefile = lg->GetMakefile();
   const std::string& language = source->GetLanguage();
   const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-  cmGeneratorExpressionInterpreter genexInterpreter(
-    lg, target, config, target->GetName(), language);
+  cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+                                                    language);
 
   // Add include directories for this source file
   const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");

+ 8 - 6
Source/cmGeneratorExpression.cxx

@@ -389,14 +389,16 @@ void cmCompiledGeneratorExpression::GetMaxLanguageStandard(
 const std::string& cmGeneratorExpressionInterpreter::Evaluate(
   const char* expression, const std::string& property)
 {
-  if (this->Target.empty()) {
-    return this->EvaluateExpression(expression);
-  }
+  this->CompiledGeneratorExpression =
+    this->GeneratorExpression.Parse(expression);
 
   // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS
   cmGeneratorExpressionDAGChecker dagChecker(
-    this->Target, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property,
-    nullptr, nullptr);
+    this->HeadTarget,
+    property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr,
+    nullptr);
 
-  return this->EvaluateExpression(expression, &dagChecker);
+  return this->CompiledGeneratorExpression->Evaluate(
+    this->LocalGenerator, this->Config, false, this->HeadTarget, &dagChecker,
+    this->Language);
 }

+ 5 - 50
Source/cmGeneratorExpression.h

@@ -160,24 +160,15 @@ class cmGeneratorExpressionInterpreter
 
 public:
   cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
-                                   cmGeneratorTarget* generatorTarget,
-                                   const std::string& config,
-                                   const std::string& target,
-                                   const std::string& lang)
+                                   std::string const& config,
+                                   cmGeneratorTarget const* headTarget,
+                                   std::string const& lang = std::string())
     : LocalGenerator(localGenerator)
-    , GeneratorTarget(generatorTarget)
     , Config(config)
-    , Target(target)
+    , HeadTarget(headTarget)
     , Language(lang)
   {
   }
-  cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
-                                   cmGeneratorTarget* generatorTarget,
-                                   const std::string& config)
-    : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, config,
-                                       std::string(), std::string())
-  {
-  }
 
   const std::string& Evaluate(const char* expression,
                               const std::string& property);
@@ -188,47 +179,11 @@ public:
   }
 
 protected:
-  cmGeneratorExpression& GetGeneratorExpression()
-  {
-    return this->GeneratorExpression;
-  }
-
-  cmCompiledGeneratorExpression& GetCompiledGeneratorExpression()
-  {
-    return *(this->CompiledGeneratorExpression);
-  }
-
-  cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; }
-
-  cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
-
-  const std::string& GetTargetName() const { return this->Target; }
-  const std::string& GetLanguage() const { return this->Language; }
-
-  const std::string& EvaluateExpression(
-    const char* expression,
-    cmGeneratorExpressionDAGChecker* dagChecker = nullptr)
-  {
-    this->CompiledGeneratorExpression =
-      this->GeneratorExpression.Parse(expression);
-
-    if (dagChecker == nullptr) {
-      return this->CompiledGeneratorExpression->Evaluate(
-        this->LocalGenerator, this->Config, false, this->GeneratorTarget);
-    }
-
-    return this->CompiledGeneratorExpression->Evaluate(
-      this->LocalGenerator, this->Config, false, this->GeneratorTarget,
-      dagChecker, this->Language);
-  }
-
-private:
   cmGeneratorExpression GeneratorExpression;
   std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
   cmLocalGenerator* LocalGenerator = nullptr;
-  cmGeneratorTarget* GeneratorTarget = nullptr;
   std::string Config;
-  std::string Target;
+  cmGeneratorTarget const* HeadTarget = nullptr;
   std::string Language;
 };
 

+ 7 - 6
Source/cmGeneratorExpressionDAGChecker.cxx

@@ -14,7 +14,7 @@
 #include <utility>
 
 cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
-  const cmListFileBacktrace& backtrace, const std::string& target,
+  const cmListFileBacktrace& backtrace, cmGeneratorTarget const* target,
   const std::string& property, const GeneratorExpressionContent* content,
   cmGeneratorExpressionDAGChecker* parent)
   : Parent(parent)
@@ -28,7 +28,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
 }
 
 cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
-  const std::string& target, const std::string& property,
+  cmGeneratorTarget const* target, const std::string& property,
   const GeneratorExpressionContent* content,
   cmGeneratorExpressionDAGChecker* parent)
   : Parent(parent)
@@ -58,8 +58,8 @@ void cmGeneratorExpressionDAGChecker::Initialize()
         TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy)
 #undef TEST_TRANSITIVE_PROPERTY_METHOD
   {
-    std::map<std::string, std::set<std::string>>::const_iterator it =
-      top->Seen.find(this->Target);
+    std::map<cmGeneratorTarget const*, std::set<std::string>>::const_iterator
+      it = top->Seen.find(this->Target);
     if (it != top->Seen.end()) {
       const std::set<std::string>& propSet = it->second;
       if (propSet.find(this->Property) != propSet.end()) {
@@ -166,7 +166,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
   return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
 }
 
-bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
+bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
+  cmGeneratorTarget const* tgt)
 {
   const cmGeneratorExpressionDAGChecker* top = this;
   const cmGeneratorExpressionDAGChecker* parent = this->Parent;
@@ -189,7 +190,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
     strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
 }
 
-std::string cmGeneratorExpressionDAGChecker::TopTarget() const
+cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
 {
   const cmGeneratorExpressionDAGChecker* top = this;
   const cmGeneratorExpressionDAGChecker* parent = this->Parent;

+ 7 - 6
Source/cmGeneratorExpressionDAGChecker.h

@@ -13,6 +13,7 @@
 
 struct GeneratorExpressionContent;
 struct cmGeneratorExpressionContext;
+class cmGeneratorTarget;
 
 #define CM_SELECT_BOTH(F, A1, A2) F(A1, A2)
 #define CM_SELECT_FIRST(F, A1, A2) F(A1)
@@ -41,11 +42,11 @@ struct cmGeneratorExpressionContext;
 struct cmGeneratorExpressionDAGChecker
 {
   cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace,
-                                  const std::string& target,
+                                  cmGeneratorTarget const* target,
                                   const std::string& property,
                                   const GeneratorExpressionContent* content,
                                   cmGeneratorExpressionDAGChecker* parent);
-  cmGeneratorExpressionDAGChecker(const std::string& target,
+  cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target,
                                   const std::string& property,
                                   const GeneratorExpressionContent* content,
                                   cmGeneratorExpressionDAGChecker* parent);
@@ -64,7 +65,7 @@ struct cmGeneratorExpressionDAGChecker
                    const std::string& expr);
 
   bool EvaluatingGenexExpression();
-  bool EvaluatingLinkLibraries(const char* tgt = nullptr);
+  bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
 
 #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
 
@@ -75,7 +76,7 @@ struct cmGeneratorExpressionDAGChecker
   bool GetTransitivePropertiesOnly();
   void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; }
 
-  std::string TopTarget() const;
+  cmGeneratorTarget const* TopTarget() const;
 
 private:
   Result CheckGraph() const;
@@ -83,9 +84,9 @@ private:
 
 private:
   const cmGeneratorExpressionDAGChecker* const Parent;
-  const std::string Target;
+  cmGeneratorTarget const* Target;
   const std::string Property;
-  std::map<std::string, std::set<std::string>> Seen;
+  std::map<cmGeneratorTarget const*, std::set<std::string>> Seen;
   const GeneratorExpressionContent* const Content;
   const cmListFileBacktrace Backtrace;
   Result CheckResult;

+ 6 - 7
Source/cmGeneratorExpressionNode.cxx

@@ -378,8 +378,8 @@ protected:
   {
     if (context->HeadTarget) {
       cmGeneratorExpressionDAGChecker dagChecker(
-        context->Backtrace, context->HeadTarget->GetName(), genexOperator,
-        content, dagCheckerParent);
+        context->Backtrace, context->HeadTarget, genexOperator, content,
+        dagCheckerParent);
       switch (dagChecker.Check()) {
         case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
         case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
@@ -1196,9 +1196,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
       return target->GetLinkerLanguage(context->Config);
     }
 
-    cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
-                                               target->GetName(), propertyName,
-                                               content, dagCheckerParent);
+    cmGeneratorExpressionDAGChecker dagChecker(
+      context->Backtrace, target, propertyName, content, dagCheckerParent);
 
     switch (dagChecker.Check()) {
       case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
@@ -1911,9 +1910,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
       return std::string();
     }
     if (dagChecker &&
-        (dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
+        (dagChecker->EvaluatingLinkLibraries(target) ||
          (dagChecker->EvaluatingSources() &&
-          name == dagChecker->TopTarget()))) {
+          target == dagChecker->TopTarget()))) {
       ::reportError(context, content->GetOriginalExpression(),
                     "Expressions which require the linker language may not "
                     "be used while evaluating link libraries");

+ 46 - 41
Source/cmGeneratorTarget.cxx

@@ -671,9 +671,12 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
     this->UtilityItemsDone = true;
     std::set<std::string> const& utilities = this->GetUtilities();
     for (std::string const& i : utilities) {
-      cmGeneratorTarget* gt =
-        this->LocalGenerator->FindGeneratorTargetToUse(i);
-      this->UtilityItems.insert(cmLinkItem(i, gt));
+      if (cmGeneratorTarget* gt =
+            this->LocalGenerator->FindGeneratorTargetToUse(i)) {
+        this->UtilityItems.insert(cmLinkItem(gt));
+      } else {
+        this->UtilityItems.insert(cmLinkItem(i));
+      }
     }
   }
   return this->UtilityItems;
@@ -770,7 +773,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
 
   if (iter == this->SystemIncludesCache.end()) {
     cmGeneratorExpressionDAGChecker dagChecker(
-      this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
+      this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
 
     bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
 
@@ -816,7 +819,8 @@ static void AddInterfaceEntries(
         thisTarget->GetLinkImplementationLibraries(config)) {
     for (cmLinkImplItem const& lib : impl->Libraries) {
       if (lib.Target) {
-        std::string genex = "$<TARGET_PROPERTY:" + lib + "," + prop + ">";
+        std::string genex =
+          "$<TARGET_PROPERTY:" + lib.AsStr() + "," + prop + ">";
         cmGeneratorExpression ge(lib.Backtrace);
         std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
         cge->SetEvaluateForBuildsystem(true);
@@ -836,7 +840,7 @@ static void AddObjectEntries(
     for (cmLinkImplItem const& lib : impl->Libraries) {
       if (lib.Target &&
           lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-        std::string genex = "$<TARGET_OBJECTS:" + lib + ">";
+        std::string genex = "$<TARGET_OBJECTS:" + lib.AsStr() + ">";
         cmGeneratorExpression ge(lib.Backtrace);
         std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
         cge->SetEvaluateForBuildsystem(true);
@@ -860,7 +864,7 @@ static bool processSources(
 
   for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
     cmLinkImplItem const& item = entry->LinkImplItem;
-    std::string const& targetName = item;
+    std::string const& targetName = item.AsStr();
     std::vector<std::string> entrySources;
     cmSystemTools::ExpandListArgument(
       entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt, tgt,
@@ -960,8 +964,8 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
     this->DebugSourcesDone = true;
   }
 
-  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES",
-                                             nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr,
+                                             nullptr);
 
   std::unordered_set<std::string> uniqueSrcs;
   bool contextDependentDirectSources =
@@ -1756,7 +1760,7 @@ public:
   void Visit(cmLinkItem const& item)
   {
     if (!item.Target) {
-      if (item.find("::") != std::string::npos) {
+      if (item.AsStr().find("::") != std::string::npos) {
         bool noMessage = false;
         cmake::MessageType messageType = cmake::FATAL_ERROR;
         std::ostringstream e;
@@ -1777,7 +1781,7 @@ public:
 
         if (!noMessage) {
           e << "Target \"" << this->Target->GetName()
-            << "\" links to target \"" << item
+            << "\" links to target \"" << item.AsStr()
             << "\" but the target was not found.  Perhaps a find_package() "
                "call is missing for an IMPORTED target, or an ALIAS target is "
                "missing?";
@@ -2074,8 +2078,8 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
   }
   cmGeneratorExpression ge;
 
-  cmGeneratorExpressionDAGChecker dagChecker(
-    this->GetName(), "AUTOUIC_OPTIONS", nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr,
+                                             nullptr);
   cmSystemTools::ExpandListArgument(
     ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this,
                              &dagChecker),
@@ -2477,7 +2481,7 @@ static void processIncludeDirectories(
 {
   for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
     cmLinkImplItem const& item = entry->LinkImplItem;
-    std::string const& targetName = item;
+    std::string const& targetName = item.AsStr();
     bool const fromImported = item.Target && item.Target->IsImported();
     bool const checkCMP0027 = item.FromGenex;
     std::vector<std::string> entryIncludes;
@@ -2584,8 +2588,8 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
   std::vector<std::string> includes;
   std::unordered_set<std::string> uniqueIncludes;
 
-  cmGeneratorExpressionDAGChecker dagChecker(
-    this->GetName(), "INCLUDE_DIRECTORIES", nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
+                                             nullptr, nullptr);
 
   std::vector<std::string> debugProperties;
   const char* debugProp =
@@ -2615,7 +2619,7 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
     cmLinkImplementationLibraries const* impl =
       this->GetLinkImplementationLibraries(config);
     for (cmLinkImplItem const& lib : impl->Libraries) {
-      std::string libDir = cmSystemTools::CollapseFullPath(lib);
+      std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr());
 
       static cmsys::RegularExpression frameworkCheck(
         "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
@@ -2706,8 +2710,8 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
 {
   std::unordered_set<std::string> uniqueOptions;
 
-  cmGeneratorExpressionDAGChecker dagChecker(
-    this->GetName(), "COMPILE_OPTIONS", nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
+                                             nullptr);
 
   std::vector<std::string> debugProperties;
   const char* debugProp =
@@ -2759,8 +2763,8 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
 {
   std::unordered_set<std::string> uniqueFeatures;
 
-  cmGeneratorExpressionDAGChecker dagChecker(
-    this->GetName(), "COMPILE_FEATURES", nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
+                                             nullptr);
 
   std::vector<std::string> debugProperties;
   const char* debugProp =
@@ -2810,8 +2814,8 @@ void cmGeneratorTarget::GetCompileDefinitions(
 {
   std::unordered_set<std::string> uniqueOptions;
 
-  cmGeneratorExpressionDAGChecker dagChecker(
-    this->GetName(), "COMPILE_DEFINITIONS", nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
+                                             nullptr, nullptr);
 
   std::vector<std::string> debugProperties;
   const char* debugProp =
@@ -2891,8 +2895,8 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
 {
   std::unordered_set<std::string> uniqueOptions;
 
-  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_OPTIONS",
-                                             nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
+                                             nullptr);
 
   std::vector<std::string> debugProperties;
   const char* debugProp =
@@ -3039,8 +3043,8 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
   std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
   std::unordered_set<std::string> uniqueOptions;
 
-  cmGeneratorExpressionDAGChecker dagChecker(
-    this->GetName(), "STATIC_LIBRARY_OPTIONS", nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
+                                             nullptr, nullptr);
 
   if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
     std::vector<std::string> options;
@@ -3079,8 +3083,8 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
 {
   std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
   std::unordered_set<std::string> uniqueOptions;
-  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_DEPENDS",
-                                             nullptr, nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
+                                             nullptr);
 
   if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) {
     std::vector<std::string> depends;
@@ -4495,7 +4499,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
     if (name == this->GetName() || name.empty()) {
       continue;
     }
-    items.emplace_back(name, this->FindTargetToLink(name));
+    items.push_back(this->ResolveLinkItem(name));
   }
 }
 
@@ -4505,8 +4509,7 @@ void cmGeneratorTarget::ExpandLinkItems(
   std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
 {
   cmGeneratorExpression ge;
-  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, nullptr,
-                                             nullptr);
+  cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr);
   // The $<LINK_ONLY> expression may be in a link interface to specify private
   // link dependencies that are otherwise excluded from usage requirements.
   if (usage_requirements_only) {
@@ -4571,7 +4574,7 @@ void cmGeneratorTarget::ComputeLinkInterface(
         this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
       // Shared libraries may have runtime implementation dependencies
       // on other shared libraries that are not in the interface.
-      std::unordered_set<std::string> emitted;
+      std::set<cmLinkItem> emitted;
       for (cmLinkItem const& lib : iface.Libraries) {
         emitted.insert(lib);
       }
@@ -5557,8 +5560,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
                                      end = entryRange.end();
        le != end; ++le, ++btIt) {
     std::vector<std::string> llibs;
-    cmGeneratorExpressionDAGChecker dagChecker(
-      this->GetName(), "LINK_LIBRARIES", nullptr, nullptr);
+    cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
+                                               nullptr);
     cmGeneratorExpression ge(*btIt);
     std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
     std::string const& evaluated =
@@ -5603,7 +5606,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
       }
 
       // The entry is meant for this configuration.
-      impl.Libraries.emplace_back(name, this->FindTargetToLink(name), *btIt,
+      impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt,
                                   evaluated != *le);
     }
 
@@ -5631,14 +5634,12 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
         continue;
       }
       // Support OLD behavior for CMP0003.
-      impl.WrongConfigLibraries.emplace_back(name,
-                                             this->FindTargetToLink(name));
+      impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name));
     }
   }
 }
 
-cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
-  std::string const& name) const
+cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const
 {
   cmGeneratorTarget* tgt =
     this->LocalGenerator->FindGeneratorTargetToUse(name);
@@ -5651,7 +5652,11 @@ cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
     tgt = nullptr;
   }
 
-  return tgt;
+  if (tgt) {
+    return cmLinkItem(tgt);
+  }
+
+  return cmLinkItem(name);
 }
 
 std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const

+ 1 - 1
Source/cmGeneratorTarget.h

@@ -357,7 +357,7 @@ public:
                                           cmOptionalLinkImplementation& impl,
                                           const cmGeneratorTarget* head) const;
 
-  cmGeneratorTarget* FindTargetToLink(std::string const& name) const;
+  cmLinkItem ResolveLinkItem(std::string const& name) const;
 
   // Compute the set of languages compiled by the target.  This is
   // computed every time it is called because the languages can change

+ 5 - 7
Source/cmGlobalXCodeGenerator.cxx

@@ -751,11 +751,10 @@ class XCodeGeneratorExpressionInterpreter
 public:
   XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
                                       cmLocalGenerator* localGenerator,
-                                      cmGeneratorTarget* generatorTarget,
+                                      cmGeneratorTarget* headTarget,
                                       const std::string& lang)
-    : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget,
-                                       "NO-PER-CONFIG-SUPPORT-IN-XCODE",
-                                       generatorTarget->GetName(), lang)
+    : cmGeneratorExpressionInterpreter(
+        localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang)
     , SourceFile(sourceFile)
   {
   }
@@ -767,8 +766,7 @@ public:
   {
     const std::string& processed =
       this->cmGeneratorExpressionInterpreter::Evaluate(expression, property);
-    if (this->GetCompiledGeneratorExpression()
-          .GetHadContextSensitiveCondition()) {
+    if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) {
       std::ostringstream e;
       /* clang-format off */
       e <<
@@ -777,7 +775,7 @@ public:
           "specified for source:\n"
           "  " << this->SourceFile->GetFullPath() << "\n";
       /* clang-format on */
-      this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
+      this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
     }
 
     return processed;

+ 72 - 0
Source/cmLinkItem.cxx

@@ -0,0 +1,72 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmLinkItem.h"
+
+#include "cmGeneratorTarget.h"
+
+#include <utility> // IWYU pragma: keep
+
+cmLinkItem::cmLinkItem()
+  : String()
+  , Target(nullptr)
+{
+}
+
+cmLinkItem::cmLinkItem(std::string const& n)
+  : String(n)
+  , Target(nullptr)
+{
+}
+
+cmLinkItem::cmLinkItem(cmGeneratorTarget const* t)
+  : String()
+  , Target(t)
+{
+}
+
+std::string const& cmLinkItem::AsStr() const
+{
+  return this->Target ? this->Target->GetName() : this->String;
+}
+
+bool operator<(cmLinkItem const& l, cmLinkItem const& r)
+{
+  // Order among targets.
+  if (l.Target && r.Target) {
+    return l.Target < r.Target;
+  }
+  // Order targets before strings.
+  if (l.Target) {
+    return true;
+  }
+  if (r.Target) {
+    return false;
+  }
+  // Order among strings.
+  return l.String < r.String;
+}
+
+bool operator==(cmLinkItem const& l, cmLinkItem const& r)
+{
+  return l.Target == r.Target && l.String == r.String;
+}
+
+std::ostream& operator<<(std::ostream& os, cmLinkItem const& item)
+{
+  return os << item.AsStr();
+}
+
+cmLinkImplItem::cmLinkImplItem()
+  : cmLinkItem()
+  , Backtrace()
+  , FromGenex(false)
+{
+}
+
+cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt,
+                               bool fromGenex)
+  : cmLinkItem(std::move(item))
+  , Backtrace(bt)
+  , FromGenex(fromGenex)
+{
+}

+ 13 - 25
Source/cmLinkItem.h

@@ -7,6 +7,7 @@
 
 #include <algorithm>
 #include <map>
+#include <ostream>
 #include <string>
 #include <vector>
 
@@ -17,40 +18,27 @@
 class cmGeneratorTarget;
 
 // Basic information about each link item.
-class cmLinkItem : public std::string
+class cmLinkItem
 {
-  typedef std::string std_string;
+  std::string String;
 
 public:
-  cmLinkItem()
-    : std_string()
-    , Target(nullptr)
-  {
-  }
-  cmLinkItem(const std_string& n, cmGeneratorTarget const* t)
-    : std_string(n)
-    , Target(t)
-  {
-  }
+  cmLinkItem();
+  explicit cmLinkItem(std::string const& s);
+  explicit cmLinkItem(cmGeneratorTarget const* t);
+  std::string const& AsStr() const;
   cmGeneratorTarget const* Target;
+  friend bool operator<(cmLinkItem const& l, cmLinkItem const& r);
+  friend bool operator==(cmLinkItem const& l, cmLinkItem const& r);
+  friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item);
 };
 
 class cmLinkImplItem : public cmLinkItem
 {
 public:
-  cmLinkImplItem()
-    : cmLinkItem()
-    , Backtrace()
-    , FromGenex(false)
-  {
-  }
-  cmLinkImplItem(std::string const& n, cmGeneratorTarget const* t,
-                 cmListFileBacktrace const& bt, bool fromGenex)
-    : cmLinkItem(n, t)
-    , Backtrace(bt)
-    , FromGenex(fromGenex)
-  {
-  }
+  cmLinkImplItem();
+  cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt,
+                 bool fromGenex);
   cmListFileBacktrace Backtrace;
   bool FromGenex;
 };

+ 1 - 2
Source/cmLocalVisualStudio7Generator.cxx

@@ -1497,8 +1497,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
       lang = sourceLang;
     }
 
-    cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i,
-                                                      gt->GetName(), lang);
+    cmGeneratorExpressionInterpreter genexInterpreter(lg, *i, gt, lang);
 
     bool needfc = false;
     if (!objectName.empty()) {

+ 1 - 2
Source/cmMakefileTargetGenerator.cxx

@@ -434,8 +434,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
   std::string config = this->LocalGenerator->GetConfigName();
   std::string configUpper = cmSystemTools::UpperCase(config);
   cmGeneratorExpressionInterpreter genexInterpreter(
-    this->LocalGenerator, this->GeneratorTarget, config,
-    this->GeneratorTarget->GetName(), lang);
+    this->LocalGenerator, config, this->GeneratorTarget, lang);
 
   // Add Fortran format flags.
   if (lang == "Fortran") {

+ 4 - 7
Source/cmNinjaTargetGenerator.cxx

@@ -136,9 +136,8 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
 
   // Add source file specific flags.
   cmGeneratorExpressionInterpreter genexInterpreter(
-    this->LocalGenerator, this->GeneratorTarget,
-    this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
-    language);
+    this->LocalGenerator, this->LocalGenerator->GetConfigName(),
+    this->GeneratorTarget, language);
 
   const std::string COMPILE_FLAGS("COMPILE_FLAGS");
   if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
@@ -188,8 +187,7 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
   std::set<std::string> defines;
   const std::string config = this->LocalGenerator->GetConfigName();
   cmGeneratorExpressionInterpreter genexInterpreter(
-    this->LocalGenerator, this->GeneratorTarget, config,
-    this->GeneratorTarget->GetName(), language);
+    this->LocalGenerator, config, this->GeneratorTarget, language);
 
   const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
   if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
@@ -217,8 +215,7 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
   std::vector<std::string> includes;
   const std::string config = this->LocalGenerator->GetConfigName();
   cmGeneratorExpressionInterpreter genexInterpreter(
-    this->LocalGenerator, this->GeneratorTarget, config,
-    this->GeneratorTarget->GetName(), language);
+    this->LocalGenerator, config, this->GeneratorTarget, language);
 
   const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
   if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {

+ 4 - 5
Source/cmServerProtocol.cxx

@@ -722,8 +722,8 @@ static void PopulateFileGroupData(
         ? languageDataMap.at(kInterfaceSourcesLanguageDataKey)
         : languageDataMap.at(fileData.Language);
       cmLocalGenerator* lg = target->GetLocalGenerator();
-      cmGeneratorExpressionInterpreter genexInterpreter(
-        lg, target, config, target->GetName(), fileData.Language);
+      cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+                                                        fileData.Language);
 
       std::string compileFlags = ld.Flags;
       const std::string COMPILE_FLAGS("COMPILE_FLAGS");
@@ -817,7 +817,7 @@ static Json::Value DumpSourceFilesList(
   auto targetProp = target->Target->GetProperty("INTERFACE_SOURCES");
   if (targetProp != nullptr) {
     cmGeneratorExpressionInterpreter genexInterpreter(
-      target->GetLocalGenerator(), target, config, target->GetName(), "");
+      target->GetLocalGenerator(), config, target);
 
     auto evaluatedSources = cmsys::SystemTools::SplitString(
       genexInterpreter.Evaluate(targetProp, "INTERFACE_SOURCES"), ';');
@@ -977,8 +977,7 @@ static void CreateInterfaceSourcesEntry(
   LanguageData& ld = languageDataMap[kInterfaceSourcesLanguageDataKey];
   ld.Language = "";
 
-  cmGeneratorExpressionInterpreter genexInterpreter(lg, target, config,
-                                                    target->GetName(), "");
+  cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target);
   std::vector<std::string> propertyValue;
   GetTargetProperty(genexInterpreter, target, "INTERFACE_INCLUDE_DIRECTORIES",
                     propertyValue);

+ 1 - 2
Source/cmVisualStudio10TargetGenerator.cxx

@@ -2117,8 +2117,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
         flagtable = gg->GetCSharpFlagTable();
       }
       cmGeneratorExpressionInterpreter genexInterpreter(
-        this->LocalGenerator, this->GeneratorTarget, config,
-        this->GeneratorTarget->GetName(), lang);
+        this->LocalGenerator, config, this->GeneratorTarget, lang);
       cmVS10GeneratorOptions clOptions(
         this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
         flagtable, this);

+ 1 - 0
Tests/CMakeLists.txt

@@ -396,6 +396,7 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
   ADD_TEST_MACRO(AliasTarget AliasTarget)
   ADD_TEST_MACRO(StagingPrefix StagingPrefix)
+  ADD_TEST_MACRO(ImportedSameName ImportedSameName)
   ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary)
   if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
     set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=Debug)

+ 8 - 0
Tests/ImportedSameName/A/CMakeLists.txt

@@ -0,0 +1,8 @@
+add_library(a STATIC a.c)
+target_compile_definitions(a INTERFACE DEF_A)
+
+add_library(sameName INTERFACE IMPORTED)
+target_link_libraries(sameName INTERFACE a)
+
+add_library(ifaceA INTERFACE)
+target_link_libraries(ifaceA INTERFACE sameName)

+ 3 - 0
Tests/ImportedSameName/A/a.c

@@ -0,0 +1,3 @@
+void a(void)
+{
+}

+ 8 - 0
Tests/ImportedSameName/B/CMakeLists.txt

@@ -0,0 +1,8 @@
+add_library(b STATIC b.c)
+target_compile_definitions(b INTERFACE DEF_B)
+
+add_library(sameName INTERFACE IMPORTED)
+target_link_libraries(sameName INTERFACE b)
+
+add_library(ifaceB INTERFACE)
+target_link_libraries(ifaceB INTERFACE sameName)

+ 3 - 0
Tests/ImportedSameName/B/b.c

@@ -0,0 +1,3 @@
+void b(void)
+{
+}

+ 8 - 0
Tests/ImportedSameName/CMakeLists.txt

@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.12)
+project(ImportedSameName C)
+
+add_subdirectory(A)
+add_subdirectory(B)
+
+add_executable(ImportedSameName main.c)
+target_link_libraries(ImportedSameName PRIVATE ifaceA ifaceB)

+ 16 - 0
Tests/ImportedSameName/main.c

@@ -0,0 +1,16 @@
+#ifndef DEF_A
+#  error "DEF_A not defined"
+#endif
+#ifndef DEF_B
+#  error "DEF_B not defined"
+#endif
+
+extern void a(void);
+extern void b(void);
+
+int main(void)
+{
+  a();
+  b();
+  return 0;
+}

+ 1 - 0
bootstrap

@@ -352,6 +352,7 @@ CMAKE_CXX_SOURCES="\
   cmInstallTargetsCommand \
   cmInstalledFile \
   cmLinkDirectoriesCommand \
+  cmLinkItem \
   cmLinkLineComputer \
   cmListCommand \
   cmListFileCache \