From e36a05fd7f7d008c4c1e75ebf46eac3072ef71b1 Mon Sep 17 00:00:00 2001
From: Robert Goulet <robert.goulet@autodesk.com>
Date: Tue, 11 Aug 2015 15:18:39 -0400
Subject: [PATCH] cmTarget: Detect and diagnose recursion in GetOutputInfo

---
 Source/cmTarget.cxx | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d3170e4ae5..d2d4c671f1 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -66,6 +66,8 @@ struct cmTarget::OutputInfo
   std::string OutDir;
   std::string ImpDir;
   std::string PdbDir;
+  bool empty() const
+    { return OutDir.empty() && ImpDir.empty() && PdbDir.empty(); }
 };
 
 //----------------------------------------------------------------------------
@@ -2609,19 +2611,35 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(
     config_upper = cmSystemTools::UpperCase(config);
     }
   typedef cmTargetInternals::OutputInfoMapType OutputInfoMapType;
-  OutputInfoMapType::const_iterator i =
+  OutputInfoMapType::iterator i =
     this->Internal->OutputInfoMap.find(config_upper);
   if(i == this->Internal->OutputInfoMap.end())
     {
+    // Add empty info in map to detect potential recursion.
     OutputInfo info;
+    OutputInfoMapType::value_type entry(config_upper, info);
+    i = this->Internal->OutputInfoMap.insert(entry).first;
+
+    // Compute output directories.
     this->ComputeOutputDir(config, false, info.OutDir);
     this->ComputeOutputDir(config, true, info.ImpDir);
     if(!this->ComputePDBOutputDir("PDB", config, info.PdbDir))
       {
       info.PdbDir = info.OutDir;
       }
-    OutputInfoMapType::value_type entry(config_upper, info);
-    i = this->Internal->OutputInfoMap.insert(entry).first;
+
+    // Now update the previously-prepared map entry.
+    i->second = info;
+    }
+  else if(i->second.empty())
+    {
+    // An empty map entry indicates we have been called recursively
+    // from the above block.
+    this->Makefile->GetCMakeInstance()->IssueMessage(
+      cmake::FATAL_ERROR,
+      "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
+      this->GetBacktrace());
+    return 0;
     }
   return &i->second;
 }
-- 
GitLab